Initial open source commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
from golang as builder
|
||||
|
||||
# Add files
|
||||
RUN mkdir /app
|
||||
WORKDIR /app
|
||||
ADD ./go-app/main.go /app
|
||||
ADD ./go-app/walkoff.go /app
|
||||
ADD ./go-app/docker.go /app
|
||||
ADD ./go-app/codegen.go /app
|
||||
|
||||
ADD ./go-app/go.mod /app
|
||||
|
||||
RUN go get -v
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o webapp .
|
||||
|
||||
# Certificate build
|
||||
FROM alpine:latest as certs
|
||||
RUN apk --update add ca-certificates
|
||||
|
||||
from scratch
|
||||
COPY --from=builder /app/ /
|
||||
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
|
||||
EXPOSE 5001
|
||||
CMD ["./webapp"]
|
||||
@@ -0,0 +1,61 @@
|
||||
# Backend setup
|
||||
1 Go to https://console.cloud.google.com/apis/credentials?project=shuffle-241517&folder&organizationId and get credentials
|
||||
2. Move the file to current folder (or make step 3 be your download folder or w/e)
|
||||
3. export GOOGLE_APPLICATION_CREDENTIALS=$(pwd)/Shuffle-2a19ff64af66.json
|
||||
|
||||
# Backend run testserver (appengine)
|
||||
1. Set up gcloud locally
|
||||
```bash
|
||||
dev_appserver.py go-app/ --port=5001 --host=0.0.0.0 --enable_host_checking=false
|
||||
```
|
||||
|
||||
# Backend deploy
|
||||
* I created a simple script that moves the data into your GOPATH and deploys for you. This will require more tests in the future.
|
||||
|
||||
# OpenAPI spec checks
|
||||
Paths:
|
||||
* /path/{variablename}?queryvar= <-- variable
|
||||
* ^variablename needs to be part of parameters too.
|
||||
* ^queryvar needs to be part of parameters too.
|
||||
```
|
||||
parameters:
|
||||
- name: variablename
|
||||
in: path
|
||||
description: Blah blah
|
||||
required: true/false
|
||||
schema:
|
||||
type: string
|
||||
enum: [a, b, c] # <-- not necessary, but could be great
|
||||
- name: queryvar
|
||||
in: query
|
||||
description: blah blah
|
||||
required: true/false
|
||||
schema:
|
||||
type: string
|
||||
enum: [a, b, c]
|
||||
```
|
||||
* requestBody? Not in GET, DELETE & HEAD. Can consume JSON, XML, form data, plai ntext & others. Can use markdown for the description.
|
||||
* Do I care about the response? Maybe :o
|
||||
|
||||
```
|
||||
requestBody:
|
||||
description: Optional kind of description
|
||||
required: false/true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
fav_number:
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
- email
|
||||
encoding:
|
||||
color:
|
||||
style: form
|
||||
explode: false
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
# 2. docker run -p 8000:8000
|
||||
FROM google/cloud-sdk
|
||||
|
||||
EXPOSE 8000
|
||||
CMD ["gcloud", "beta", "emulators", "datastore", "start", "--project=shuffle", "--host-port", "0.0.0.0:8000", "--data-dir=/etc/shuffle"]
|
||||
@@ -0,0 +1,8 @@
|
||||
# Deploys to backend
|
||||
echo "Deploying to appengine."
|
||||
mkdir -p $GOPATH/src/github.com/frikky/shuffle
|
||||
cp -r go-app/* $GOPATH/src/github.com/frikky/shuffle
|
||||
cd $GOPATH/src/github.com/frikky/shuffle
|
||||
go build
|
||||
go test
|
||||
gcloud app deploy $GOPATH/src/github.com/frikky/shuffle/app.yaml
|
||||
@@ -0,0 +1,6 @@
|
||||
## RUN
|
||||
```bash
|
||||
cd shaffuru/
|
||||
dev_appserver.py --port=5001 --host=0.0.0.0 --enable_host_checking=false .
|
||||
```
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
runtime: go111
|
||||
|
||||
env_variables:
|
||||
|
||||
automatic_scaling:
|
||||
max_instances: 1
|
||||
min_instances: 1
|
||||
|
||||
handlers:
|
||||
- url: /api/(.*)
|
||||
script: auto
|
||||
secure: always
|
||||
- url: /static/js/(.*)
|
||||
static_files: build/static/js/\1
|
||||
upload: build/static/js/(.*)
|
||||
secure: always
|
||||
- url: /static/css/(.*)
|
||||
static_files: build/static/css/\1
|
||||
upload: build/static/css/(.*)
|
||||
secure: always
|
||||
- url: /images/(.*)
|
||||
static_files: build/images/\1
|
||||
upload: build/images/(.*)
|
||||
secure: always
|
||||
- url: /(.*\.(json|ico))$
|
||||
static_files: build/\1
|
||||
upload: build/.*\.(json|ico)$
|
||||
secure: always
|
||||
- url: /manifest.json
|
||||
static_files: build/manifest.json
|
||||
upload: build/manifest.json
|
||||
secure: always
|
||||
|
||||
# lol.. wildcard doesn't work with /api/(.*) for some reason
|
||||
- url: /
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /home
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /passwordreset
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /login
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /register
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /workflows
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /workflows/(.*)
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /info/(.*)
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /docs/(.*)
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /docs
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /settings
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /apps
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /contact
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /apps/(.*)
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /register/(.*)
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
- url: /passwordreset/(.*)
|
||||
static_files: build/index.html
|
||||
upload: build/index.html
|
||||
secure: always
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,644 @@
|
||||
package main
|
||||
|
||||
// Docker
|
||||
import (
|
||||
"archive/tar"
|
||||
"path/filepath"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
network "github.com/docker/docker/api/types/network"
|
||||
"github.com/docker/docker/client"
|
||||
natting "github.com/docker/go-connections/nat"
|
||||
"github.com/go-git/go-billy/v5"
|
||||
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
//"google.golang.org/appengine"
|
||||
)
|
||||
|
||||
// Parses a directory with a Dockerfile into a tar for Docker images..
|
||||
func getParsedTar(tw *tar.Writer, baseDir, extra string) error {
|
||||
return filepath.Walk(baseDir, func(file string, fi os.FileInfo, err error) error {
|
||||
if file == baseDir {
|
||||
return nil
|
||||
}
|
||||
|
||||
//log.Printf("File: %s", file)
|
||||
//log.Printf("Fileinfo: %#v", fi)
|
||||
switch mode := fi.Mode(); {
|
||||
case mode.IsDir():
|
||||
// do directory recursion
|
||||
//log.Printf("DIR: %s", file)
|
||||
|
||||
// Append "src" as extra here
|
||||
filenamesplit := strings.Split(file, "/")
|
||||
filename := fmt.Sprintf("%s%s/", extra, filenamesplit[len(filenamesplit)-1])
|
||||
|
||||
tmpExtra := fmt.Sprintf(filename)
|
||||
//log.Printf("TmpExtra: %s", tmpExtra)
|
||||
err = getParsedTar(tw, file, tmpExtra)
|
||||
if err != nil {
|
||||
log.Printf("Directory parse issue: %s", err)
|
||||
return err
|
||||
}
|
||||
case mode.IsRegular():
|
||||
// do file stuff
|
||||
//log.Printf("FILE: %s", file)
|
||||
|
||||
fileReader, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the actual Dockerfile
|
||||
readFile, err := ioutil.ReadAll(fileReader)
|
||||
if err != nil {
|
||||
log.Printf("Not file: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
filenamesplit := strings.Split(file, "/")
|
||||
filename := fmt.Sprintf("%s%s", extra, filenamesplit[len(filenamesplit)-1])
|
||||
//log.Printf("Filename: %s", filename)
|
||||
tarHeader := &tar.Header{
|
||||
Name: filename,
|
||||
Size: int64(len(readFile)),
|
||||
}
|
||||
|
||||
//Writes the header described for the TAR file
|
||||
err = tw.WriteHeader(tarHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Writes the dockerfile data to the TAR file
|
||||
_, err = tw.Write(readFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Custom TAR builder in memory for Docker images
|
||||
func getParsedTarMemory(fs billy.Filesystem, tw *tar.Writer, baseDir, extra string) error {
|
||||
// This one has to use baseDir + Extra
|
||||
newBase := fmt.Sprintf("%s%s", baseDir, extra)
|
||||
dir, err := fs.ReadDir(newBase)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range dir {
|
||||
// Folder?
|
||||
switch mode := file.Mode(); {
|
||||
case mode.IsDir():
|
||||
filename := file.Name()
|
||||
filenamesplit := strings.Split(filename, "/")
|
||||
|
||||
tmpExtra := fmt.Sprintf("%s%s/", extra, filenamesplit[len(filenamesplit)-1])
|
||||
//log.Printf("EXTRA: %s", tmpExtra)
|
||||
err = getParsedTarMemory(fs, tw, baseDir, tmpExtra)
|
||||
if err != nil {
|
||||
log.Printf("Directory parse issue: %s", err)
|
||||
return err
|
||||
}
|
||||
case mode.IsRegular():
|
||||
filenamesplit := strings.Split(file.Name(), "/")
|
||||
filename := fmt.Sprintf("%s%s", extra, filenamesplit[len(filenamesplit)-1])
|
||||
// Newbase
|
||||
path := fmt.Sprintf("%s%s", newBase, file.Name())
|
||||
|
||||
fileReader, err := fs.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
readFile, err := ioutil.ReadAll(fileReader)
|
||||
if err != nil {
|
||||
log.Printf("Not file: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
//log.Printf("Filename: %s", filename)
|
||||
// FIXME - might need the folder from EXTRA here
|
||||
// Name has to be e.g. just "requirements.txt"
|
||||
tarHeader := &tar.Header{
|
||||
Name: filename,
|
||||
Size: int64(len(readFile)),
|
||||
}
|
||||
|
||||
//Writes the header described for the TAR file
|
||||
err = tw.WriteHeader(tarHeader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Writes the dockerfile data to the TAR file
|
||||
_, err = tw.Write(readFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Custom Docker image builder wrapper in memory
|
||||
func buildImageMemory(fs billy.Filesystem, tags []string, dockerfileFolder string) error {
|
||||
ctx := context.Background()
|
||||
client, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
log.Printf("Unable to create docker client: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
tw := tar.NewWriter(buf)
|
||||
defer tw.Close()
|
||||
|
||||
log.Printf("Setting up memory build structure for folder: %s", dockerfileFolder)
|
||||
err = getParsedTarMemory(fs, tw, dockerfileFolder, "")
|
||||
if err != nil {
|
||||
log.Printf("Tar issue: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
dockerFileTarReader := bytes.NewReader(buf.Bytes())
|
||||
|
||||
// Dockerfile is inside the TAR itself. Not local context
|
||||
buildOptions := types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
Tags: tags,
|
||||
}
|
||||
|
||||
// Build the actual image
|
||||
imageBuildResponse, err := client.ImageBuild(
|
||||
ctx,
|
||||
dockerFileTarReader,
|
||||
buildOptions,
|
||||
)
|
||||
|
||||
log.Printf("IMAGERESPONSE: %#v", imageBuildResponse.Body)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the STDOUT from the build process
|
||||
defer imageBuildResponse.Body.Close()
|
||||
_, err = io.Copy(os.Stdout, imageBuildResponse.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildImage(tags []string, dockerfileFolder string) error {
|
||||
ctx := context.Background()
|
||||
client, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
log.Printf("Unable to create docker client: %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("Tags: %s", tags)
|
||||
dockerfileSplit := strings.Split(dockerfileFolder, "/")
|
||||
|
||||
// Create a buffer
|
||||
buf := new(bytes.Buffer)
|
||||
tw := tar.NewWriter(buf)
|
||||
defer tw.Close()
|
||||
baseDir := strings.Join(dockerfileSplit[0:len(dockerfileSplit)-1], "/")
|
||||
|
||||
// Builds the entire folder into buf
|
||||
err = getParsedTar(tw, baseDir, "")
|
||||
if err != nil {
|
||||
log.Printf("Tar issue: %s", err)
|
||||
}
|
||||
|
||||
dockerFileTarReader := bytes.NewReader(buf.Bytes())
|
||||
buildOptions := types.ImageBuildOptions{
|
||||
Remove: true,
|
||||
Tags: tags,
|
||||
}
|
||||
|
||||
// Build the actual image
|
||||
imageBuildResponse, err := client.ImageBuild(
|
||||
ctx,
|
||||
dockerFileTarReader,
|
||||
buildOptions,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Read the STDOUT from the build process
|
||||
defer imageBuildResponse.Body.Close()
|
||||
_, err = io.Copy(os.Stdout, imageBuildResponse.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME - very specific for webhooks. Make it easier?
|
||||
func stopWebhook(image string, identifier string) error {
|
||||
ctx := context.Background()
|
||||
|
||||
containername := fmt.Sprintf("%s-%s", image, identifier)
|
||||
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
log.Println("Unable to create docker client")
|
||||
return err
|
||||
}
|
||||
|
||||
// containers, err := cli.ContainerList(ctx, types.ContainerListOptions{
|
||||
// All: true,
|
||||
// })
|
||||
|
||||
if err := cli.ContainerStop(ctx, containername, nil); err != nil {
|
||||
log.Printf("Unable to stop container %s - running removal anyway, just in case: %s", containername, err)
|
||||
}
|
||||
|
||||
removeOptions := types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
Force: true,
|
||||
}
|
||||
|
||||
if err := cli.ContainerRemove(ctx, containername, removeOptions); err != nil {
|
||||
log.Printf("Unable to remove container: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME - remember to set DOCKER_API_VERSION
|
||||
// FIXME - remove github.com/docker/docker/vendor
|
||||
// FIXME - Library dependencies for NAT is fucked..
|
||||
// https://docs.docker.com/develop/sdk/examples/
|
||||
func deployWebhook(image string, identifier string, path string, port string, callbackurl string, apikey string) error {
|
||||
cli, err := client.NewEnvClient()
|
||||
if err != nil {
|
||||
fmt.Println("Unable to create docker client")
|
||||
return err
|
||||
}
|
||||
|
||||
newport, err := natting.NewPort("tcp", port)
|
||||
if err != nil {
|
||||
fmt.Println("Unable to create docker port")
|
||||
return err
|
||||
}
|
||||
|
||||
// FIXME - logging?
|
||||
|
||||
hostConfig := &container.HostConfig{
|
||||
PortBindings: natting.PortMap{
|
||||
newport: []natting.PortBinding{
|
||||
{
|
||||
HostIP: "0.0.0.0",
|
||||
HostPort: port,
|
||||
},
|
||||
},
|
||||
},
|
||||
RestartPolicy: container.RestartPolicy{
|
||||
Name: "always",
|
||||
},
|
||||
LogConfig: container.LogConfig{
|
||||
Type: "json-file",
|
||||
Config: map[string]string{},
|
||||
},
|
||||
}
|
||||
|
||||
//networkConfig := &network.NetworkSettings{}
|
||||
networkConfig := &network.NetworkingConfig{
|
||||
EndpointsConfig: map[string]*network.EndpointSettings{},
|
||||
}
|
||||
|
||||
test := &network.EndpointSettings{
|
||||
Gateway: "helo",
|
||||
}
|
||||
|
||||
networkConfig.EndpointsConfig["bridge"] = test
|
||||
|
||||
exposedPorts := map[natting.Port]struct{}{
|
||||
newport: struct{}{},
|
||||
}
|
||||
|
||||
config := &container.Config{
|
||||
Image: image,
|
||||
Env: []string{
|
||||
fmt.Sprintf("URIPATH=%s", path),
|
||||
fmt.Sprintf("HOOKPORT=%s", port),
|
||||
fmt.Sprintf("CALLBACKURL=%s", callbackurl),
|
||||
fmt.Sprintf("APIKEY=%s", apikey),
|
||||
fmt.Sprintf("HOOKID=%s", identifier),
|
||||
},
|
||||
ExposedPorts: exposedPorts,
|
||||
Hostname: fmt.Sprintf("%s-%s", image, identifier),
|
||||
}
|
||||
|
||||
cont, err := cli.ContainerCreate(
|
||||
context.Background(),
|
||||
config,
|
||||
hostConfig,
|
||||
networkConfig,
|
||||
fmt.Sprintf("%s-%s", image, identifier),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
cli.ContainerStart(context.Background(), cont.ID, types.ContainerStartOptions{})
|
||||
log.Printf("Container %s is created", cont.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Starts a new webhook
|
||||
func handleStopHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
location := strings.Split(request.URL.String(), "/")
|
||||
|
||||
var fileId string
|
||||
if location[1] == "api" {
|
||||
if len(location) <= 4 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
fileId = location[4]
|
||||
}
|
||||
|
||||
if len(fileId) != 32 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "message": "ID not valid"}`))
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
hook, err := getHook(ctx, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting hook: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Status: %s", hook.Status)
|
||||
log.Printf("Running: %t", hook.Running)
|
||||
if !hook.Running {
|
||||
message := fmt.Sprintf("Error: %s isn't running", hook.Id)
|
||||
log.Println(message)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "%s"}`, message)))
|
||||
return
|
||||
}
|
||||
|
||||
hook.Status = "stopped"
|
||||
hook.Running = false
|
||||
hook.Actions = []HookAction{}
|
||||
err = setHook(ctx, *hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting hook: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
image := "webhook"
|
||||
|
||||
// This is here to force stop and remove the old webhook
|
||||
err = stopWebhook(image, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Container stop issue for %s-%s: %s", image, fileId, err)
|
||||
}
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true, "message": "Stopped webhook"}`))
|
||||
}
|
||||
|
||||
// THis is an example
|
||||
// Can also be used as base data?
|
||||
var webhook = `{
|
||||
"id": "d6ef8912e8bd37776e654cbc14c2629c",
|
||||
"info": {
|
||||
"url": "http://localhost:5001",
|
||||
"name": "TheHive",
|
||||
"description": "Webhook for TheHive"
|
||||
},
|
||||
"transforms": {},
|
||||
"actions": {},
|
||||
"type": "webhook",
|
||||
"running": false,
|
||||
"status": "stopped"
|
||||
}`
|
||||
|
||||
// Starts a new webhook
|
||||
func handleDeleteHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
ctx := context.Background()
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
location := strings.Split(request.URL.String(), "/")
|
||||
|
||||
var fileId string
|
||||
if location[1] == "api" {
|
||||
if len(location) <= 4 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
fileId = location[4]
|
||||
}
|
||||
|
||||
if len(fileId) != 32 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "message": "ID not valid"}`))
|
||||
return
|
||||
}
|
||||
|
||||
err := DeleteKey(ctx, "hooks", fileId)
|
||||
if err != nil {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "message": "Can't delete"}`))
|
||||
return
|
||||
}
|
||||
|
||||
image := "webhook"
|
||||
|
||||
// This is here to force stop and remove the old webhook
|
||||
err = stopWebhook(image, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Container stop issue for %s-%s: %s", image, fileId, err)
|
||||
resp.Write([]byte(`{"success": false, "message": "Couldn't stop webhook"}`))
|
||||
return
|
||||
}
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true, "message": "Deleted webhook"}`))
|
||||
}
|
||||
|
||||
// Starts a new webhook
|
||||
func handleStartHookDocker(resp http.ResponseWriter, request *http.Request) {
|
||||
cors := handleCors(resp, request)
|
||||
if cors {
|
||||
return
|
||||
}
|
||||
|
||||
location := strings.Split(request.URL.String(), "/")
|
||||
|
||||
var fileId string
|
||||
if location[1] == "api" {
|
||||
if len(location) <= 4 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
fileId = location[4]
|
||||
}
|
||||
|
||||
if len(fileId) != 32 {
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false, "message": "ID not valid"}`))
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
hook, err := getHook(ctx, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting hook: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
if len(hook.Info.Url) == 0 {
|
||||
log.Printf("Hook url can't be empty.")
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Status: %s", hook.Status)
|
||||
log.Printf("Running: %t", hook.Running)
|
||||
if hook.Running || hook.Status == "Running" {
|
||||
message := fmt.Sprintf("Error: %s is already running", hook.Id)
|
||||
log.Println(message)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "%s"}`, message)))
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME - verify?
|
||||
// FIXME - static port? Generate from available range.
|
||||
image := "webhook"
|
||||
filepath := "/webhook"
|
||||
baseUrl := "http://localhost"
|
||||
callbackUrl := "http://localhost:8001"
|
||||
|
||||
// This is here to force stop and remove the old webhook
|
||||
err = stopWebhook(image, fileId)
|
||||
if err != nil {
|
||||
log.Printf("Container stop issue for %s-%s: %s", image, fileId, err)
|
||||
}
|
||||
|
||||
// Dynamic ish ports
|
||||
var startPort int64 = 5001
|
||||
var endPort int64 = 5010
|
||||
port := findAvailablePorts(startPort, endPort)
|
||||
if len(port) == 0 {
|
||||
message := fmt.Sprintf("Not ports available in the range %d-%d", startPort, endPort)
|
||||
log.Println(message)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": false, "message": "%s"}`, message)))
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
hook.Status = "running"
|
||||
hook.Running = true
|
||||
|
||||
// Set this for more than just hooks?
|
||||
if hook.Type == "webhook" {
|
||||
hook.Info.Url = fmt.Sprintf("%s:%s%s", baseUrl, port, filepath)
|
||||
}
|
||||
err = setHook(ctx, *hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting hook: %s", err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// Cloud run? Let's make a generic webhook that can be deployed easily
|
||||
log.Printf("Should run a webhook with the following: \nUrl: %s\nId: %s\n", hook.Info.Url, hook.Id)
|
||||
|
||||
// FIXME - set port based on what the user specified / what was generated
|
||||
// FIXME - add nonstatic APIKEY
|
||||
apiKey := "ASD"
|
||||
|
||||
err = deployWebhook(image, fileId, filepath, port, callbackUrl, apiKey)
|
||||
if err != nil {
|
||||
log.Printf("Failed starting container %s-%s: %s", image, fileId, err)
|
||||
resp.WriteHeader(401)
|
||||
resp.Write([]byte(`{"success": false}`))
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME - get some real data?
|
||||
log.Printf("Successfully started %s-%s on port %s with filepath %s", image, fileId, port, filepath)
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(`{"success": true, "message": "Started webhook"}`))
|
||||
return
|
||||
}
|
||||
|
||||
func hookTest() {
|
||||
var hook Hook
|
||||
err := json.Unmarshal([]byte(webhook), &hook)
|
||||
log.Println(webhook)
|
||||
if err != nil {
|
||||
log.Printf("Failed hook unmarshaling: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err = setHook(ctx, hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed setting hook: %s", err)
|
||||
}
|
||||
|
||||
returnHook, err := getHook(ctx, hook.Id)
|
||||
if err != nil {
|
||||
log.Printf("Failed getting hook: %s", err)
|
||||
}
|
||||
|
||||
if len(returnHook.Id) > 0 {
|
||||
log.Printf("Success! - %s", returnHook.Id)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
@@ -0,0 +1,29 @@
|
||||
import requests
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from walkoff_app_sdk.app_base import AppBase
|
||||
|
||||
class Asd37fff3ea5fa10cdde521f21134320c26(AppBase):
|
||||
"""
|
||||
Autogenerated class by Shuffler
|
||||
"""
|
||||
|
||||
__version__ = "1.0"
|
||||
app_name = "Asd37fff3ea5fa10cdde521f21134320c26"
|
||||
|
||||
def __init__(self, redis, logger, console_logger=None):
|
||||
self.verify = False
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
super().__init__(redis, logger, console_logger)
|
||||
|
||||
async def get_hello(self, apikey):
|
||||
headers={}
|
||||
url=f"https://google.com/lol"
|
||||
headers["what"] = apikey
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(Asd37fff3ea5fa10cdde521f21134320c26.run(), debug=True)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
name: Uber API
|
||||
is_valid: true
|
||||
id: 6a707aa0-892b-42a0-b0a4-b10b6b56e6e5
|
||||
link: https://api.uber.com
|
||||
app_version: 1.0.0
|
||||
generated: true
|
||||
sharing: false
|
||||
verified: false
|
||||
tested: false
|
||||
owner: 2501f368-edf2-4fee-bb7e-457d65d7410c
|
||||
private_id: 547f1803-edf7-433f-8016-d508ed978f65
|
||||
description: Move your app forward with the Uber API
|
||||
environment: cloud
|
||||
smallimage: ""
|
||||
large_image: ""
|
||||
contact_info:
|
||||
name: ""
|
||||
url: ""
|
||||
actions:
|
||||
- description: The Price Estimates endpoint returns an estimated price range for each
|
||||
product offered at a given location. The price estimate is provided as a formatted
|
||||
string with the full price range and the localized currency symbol.<br><br>The
|
||||
response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217)
|
||||
currency code for situations requiring currency conversion. When surge is active
|
||||
for a particular product, its surge_multiplier will be greater than 1, but the
|
||||
price estimate already factors in this multiplier.
|
||||
name: get_price_estimates
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Latitude component of start location.
|
||||
name: start_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of start location.
|
||||
name: start_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Latitude component of end location.
|
||||
name: end_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of end location.
|
||||
name: end_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The Time Estimates endpoint returns ETAs for all products offered at
|
||||
a given location, with the responses expressed as integers in seconds. We recommend
|
||||
that this endpoint be called every minute to provide the most accurate, up-to-date
|
||||
ETAs.
|
||||
name: get_time_estimates
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Latitude component of start location.
|
||||
name: start_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of start location.
|
||||
name: start_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Unique customer identifier to be used for experience customization.
|
||||
name: customer_uuid
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: Unique identifier representing a specific product for a given latitude
|
||||
& longitude.
|
||||
name: product_id
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The User Activity endpoint returns data about a user's lifetime activity
|
||||
with Uber. The response will include pickup locations and times, dropoff locations
|
||||
and times, the distance of past requests, and information about which products
|
||||
were requested.<br><br>The history array in the response will have a maximum length
|
||||
based on the limit parameter. The response value count may exceed limit, therefore
|
||||
subsequent API requests may be necessary.
|
||||
name: get_user_activity
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Offset the list of returned results by this amount. Default is zero.
|
||||
name: offset
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: Number of items to retrieve. Default is 5, maximum is 100.
|
||||
name: limit
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The User Profile endpoint returns information about the Uber user that
|
||||
has authorized with the application.
|
||||
name: get_user_profile
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters: []
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The Products endpoint returns information about the Uber products offered
|
||||
at a given location. The response includes the display name and other details
|
||||
about each product, and lists the products in the proper display order.
|
||||
name: get_product_types
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Latitude component of location.
|
||||
name: latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of location.
|
||||
name: longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
authentication:
|
||||
required: true
|
||||
parameters:
|
||||
- description: ""
|
||||
id: ""
|
||||
name: ""
|
||||
example: ""
|
||||
value: ""
|
||||
multiline: false
|
||||
required: true
|
||||
in: ""
|
||||
scheme: ""
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import requests
|
||||
import asyncio
|
||||
import json
|
||||
import urllib3
|
||||
|
||||
from walkoff_app_sdk.app_base import AppBase
|
||||
|
||||
class UberAPI547f1803edf7433f8016d508ed978f65(AppBase):
|
||||
"""
|
||||
Autogenerated class by Shuffler
|
||||
"""
|
||||
|
||||
__version__ = "1.0"
|
||||
app_name = "UberAPI547f1803edf7433f8016d508ed978f65"
|
||||
|
||||
def __init__(self, redis, logger, console_logger=None):
|
||||
self.verify = False
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
super().__init__(redis, logger, console_logger)
|
||||
|
||||
async def get_price_estimates(self, start_latitude, start_longitude, end_latitude, end_longitude):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/estimates/price?start_latitude={start_latitude}&start_longitude={start_longitude}&end_latitude={end_latitude}&end_longitude={end_longitude}"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_time_estimates(self, start_latitude, start_longitude, customer_uuid="", product_id="", ):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/estimates/time?start_latitude={start_latitude}&start_longitude={start_longitude}"
|
||||
|
||||
|
||||
if customer_uuid:
|
||||
url += f"&customer_uuid={customer_uuid}"
|
||||
if product_id:
|
||||
url += f"&product_id={product_id}"
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_user_activity(self, offset="", limit="", ):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/history"
|
||||
|
||||
|
||||
if offset:
|
||||
url += f"&offset={offset}"
|
||||
if limit:
|
||||
url += f"&limit={limit}"
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_user_profile(self):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/me"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_product_types(self, latitude, longitude):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/products?latitude={latitude}&longitude={longitude}"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(UberAPI547f1803edf7433f8016d508ed978f65.run(), debug=True)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
name: Uber API
|
||||
is_valid: true
|
||||
id: 547f1803-edf7-433f-8016-d508ed978f65
|
||||
link: https://api.uber.com
|
||||
app_version: 1.0.0
|
||||
generated: true
|
||||
sharing: false
|
||||
verified: false
|
||||
tested: false
|
||||
owner: 2501f368-edf2-4fee-bb7e-457d65d7410c
|
||||
private_id: 795ed46f-2dbd-43d6-9d0c-1f6b9cce14ea
|
||||
description: Move your app forward with the Uber API
|
||||
environment: cloud
|
||||
smallimage: ""
|
||||
large_image: ""
|
||||
contact_info:
|
||||
name: ""
|
||||
url: ""
|
||||
actions:
|
||||
- description: The Price Estimates endpoint returns an estimated price range for each
|
||||
product offered at a given location. The price estimate is provided as a formatted
|
||||
string with the full price range and the localized currency symbol.<br><br>The
|
||||
response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217)
|
||||
currency code for situations requiring currency conversion. When surge is active
|
||||
for a particular product, its surge_multiplier will be greater than 1, but the
|
||||
price estimate already factors in this multiplier.
|
||||
name: get_price_estimates
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Latitude component of start location.
|
||||
name: start_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of start location.
|
||||
name: start_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Latitude component of end location.
|
||||
name: end_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of end location.
|
||||
name: end_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The Time Estimates endpoint returns ETAs for all products offered at
|
||||
a given location, with the responses expressed as integers in seconds. We recommend
|
||||
that this endpoint be called every minute to provide the most accurate, up-to-date
|
||||
ETAs.
|
||||
name: get_time_estimates
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Latitude component of start location.
|
||||
name: start_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of start location.
|
||||
name: start_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Unique customer identifier to be used for experience customization.
|
||||
name: customer_uuid
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: Unique identifier representing a specific product for a given latitude
|
||||
& longitude.
|
||||
name: product_id
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The User Activity endpoint returns data about a user's lifetime activity
|
||||
with Uber. The response will include pickup locations and times, dropoff locations
|
||||
and times, the distance of past requests, and information about which products
|
||||
were requested.<br><br>The history array in the response will have a maximum length
|
||||
based on the limit parameter. The response value count may exceed limit, therefore
|
||||
subsequent API requests may be necessary.
|
||||
name: get_user_activity
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Offset the list of returned results by this amount. Default is zero.
|
||||
name: offset
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: Number of items to retrieve. Default is 5, maximum is 100.
|
||||
name: limit
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The User Profile endpoint returns information about the Uber user that
|
||||
has authorized with the application.
|
||||
name: get_user_profile
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters: []
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The Products endpoint returns information about the Uber products offered
|
||||
at a given location. The response includes the display name and other details
|
||||
about each product, and lists the products in the proper display order.
|
||||
name: get_product_types
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: Latitude component of location.
|
||||
name: latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of location.
|
||||
name: longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
authentication:
|
||||
required: true
|
||||
parameters:
|
||||
- description: ""
|
||||
id: ""
|
||||
name: ""
|
||||
example: ""
|
||||
value: ""
|
||||
multiline: false
|
||||
required: true
|
||||
in: ""
|
||||
scheme: ""
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import requests
|
||||
import asyncio
|
||||
import json
|
||||
import urllib3
|
||||
|
||||
from walkoff_app_sdk.app_base import AppBase
|
||||
|
||||
class UberAPI795ed46f2dbd43d69d0c1f6b9cce14ea(AppBase):
|
||||
"""
|
||||
Autogenerated class by Shuffler
|
||||
"""
|
||||
|
||||
__version__ = "1.0"
|
||||
app_name = "UberAPI795ed46f2dbd43d69d0c1f6b9cce14ea"
|
||||
|
||||
def __init__(self, redis, logger, console_logger=None):
|
||||
self.verify = False
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
super().__init__(redis, logger, console_logger)
|
||||
|
||||
async def get_price_estimates(self, start_latitude, start_longitude, end_latitude, end_longitude):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/estimates/price?start_latitude={start_latitude}&start_longitude={start_longitude}&end_latitude={end_latitude}&end_longitude={end_longitude}"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_time_estimates(self, start_latitude, start_longitude, customer_uuid="", product_id="", ):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/estimates/time?start_latitude={start_latitude}&start_longitude={start_longitude}"
|
||||
|
||||
|
||||
if customer_uuid:
|
||||
url += f"&customer_uuid={customer_uuid}"
|
||||
if product_id:
|
||||
url += f"&product_id={product_id}"
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_user_activity(self, offset="", limit="", ):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/history"
|
||||
|
||||
|
||||
if offset:
|
||||
url += f"&offset={offset}"
|
||||
if limit:
|
||||
url += f"&limit={limit}"
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_user_profile(self):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/me"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_product_types(self, latitude, longitude):
|
||||
headers={}
|
||||
url=f"https://api.uber.com/products?latitude={latitude}&longitude={longitude}"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(UberAPI795ed46f2dbd43d69d0c1f6b9cce14ea.run(), debug=True)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
+228
@@ -0,0 +1,228 @@
|
||||
name: Uber API
|
||||
is_valid: true
|
||||
id: 795ed46f-2dbd-43d6-9d0c-1f6b9cce14ea
|
||||
link: ""
|
||||
app_version: 1.0.0
|
||||
generated: true
|
||||
sharing: false
|
||||
verified: false
|
||||
tested: false
|
||||
owner: 2501f368-edf2-4fee-bb7e-457d65d7410c
|
||||
private_id: f97a44dd-f1c3-48ae-b46f-ceb19ce3039c
|
||||
description: Move your app forward with the Uber API
|
||||
environment: cloud
|
||||
smallimage: ""
|
||||
large_image: ""
|
||||
contact_info:
|
||||
name: ""
|
||||
url: ""
|
||||
actions:
|
||||
- description: The Time Estimates endpoint returns ETAs for all products offered at
|
||||
a given location, with the responses expressed as integers in seconds. We recommend
|
||||
that this endpoint be called every minute to provide the most accurate, up-to-date
|
||||
ETAs.
|
||||
name: get_time_estimates
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: The URL of the app
|
||||
name: url
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Latitude component of start location.
|
||||
name: start_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of start location.
|
||||
name: start_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Unique customer identifier to be used for experience customization.
|
||||
name: customer_uuid
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: Unique identifier representing a specific product for a given latitude
|
||||
& longitude.
|
||||
name: product_id
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The User Activity endpoint returns data about a user's lifetime activity
|
||||
with Uber. The response will include pickup locations and times, dropoff locations
|
||||
and times, the distance of past requests, and information about which products
|
||||
were requested.<br><br>The history array in the response will have a maximum length
|
||||
based on the limit parameter. The response value count may exceed limit, therefore
|
||||
subsequent API requests may be necessary.
|
||||
name: get_user_activity
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: The URL of the app
|
||||
name: url
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Offset the list of returned results by this amount. Default is zero.
|
||||
name: offset
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- description: Number of items to retrieve. Default is 5, maximum is 100.
|
||||
name: limit
|
||||
example: ""
|
||||
multiline: false
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The User Profile endpoint returns information about the Uber user that
|
||||
has authorized with the application.
|
||||
name: get_user_profile
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: The URL of the app
|
||||
name: url
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The Products endpoint returns information about the Uber products offered
|
||||
at a given location. The response includes the display name and other details
|
||||
about each product, and lists the products in the proper display order.
|
||||
name: get_product_types
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: The URL of the app
|
||||
name: url
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Latitude component of location.
|
||||
name: latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of location.
|
||||
name: longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
- description: The Price Estimates endpoint returns an estimated price range for each
|
||||
product offered at a given location. The price estimate is provided as a formatted
|
||||
string with the full price range and the localized currency symbol.<br><br>The
|
||||
response also includes low and high estimates, and the [ISO 4217](http://en.wikipedia.org/wiki/ISO_4217)
|
||||
currency code for situations requiring currency conversion. When surge is active
|
||||
for a particular product, its surge_multiplier will be greater than 1, but the
|
||||
price estimate already factors in this multiplier.
|
||||
name: get_price_estimates
|
||||
nodetype: action
|
||||
environment: cloud
|
||||
sharing: false
|
||||
privateid: ""
|
||||
appid: ""
|
||||
tested: false
|
||||
parameters:
|
||||
- description: The URL of the app
|
||||
name: url
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Latitude component of start location.
|
||||
name: start_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of start location.
|
||||
name: start_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Latitude component of end location.
|
||||
name: end_latitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: Longitude component of end location.
|
||||
name: end_longitude
|
||||
example: ""
|
||||
multiline: false
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
returns:
|
||||
schema:
|
||||
type: string
|
||||
authentication:
|
||||
required: true
|
||||
parameters:
|
||||
- description: ""
|
||||
id: ""
|
||||
name: ""
|
||||
example: ""
|
||||
value: ""
|
||||
multiline: false
|
||||
required: true
|
||||
in: ""
|
||||
scheme: ""
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
import requests
|
||||
import asyncio
|
||||
import json
|
||||
import urllib3
|
||||
|
||||
from walkoff_app_sdk.app_base import AppBase
|
||||
|
||||
class UberAPIf97a44ddf1c348aeb46fceb19ce3039c(AppBase):
|
||||
"""
|
||||
Autogenerated class by Shuffler
|
||||
"""
|
||||
|
||||
__version__ = "1.0"
|
||||
app_name = "UberAPIf97a44ddf1c348aeb46fceb19ce3039c"
|
||||
|
||||
def __init__(self, redis, logger, console_logger=None):
|
||||
self.verify = False
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
super().__init__(redis, logger, console_logger)
|
||||
|
||||
async def get_time_estimates(self, baseurl, start_latitude, start_longitude, customer_uuid="", product_id="", ):
|
||||
headers={}
|
||||
url=f"{baseurl}/estimates/time?start_latitude={start_latitude}&start_longitude={start_longitude}"
|
||||
|
||||
|
||||
if customer_uuid:
|
||||
url += f"&customer_uuid={customer_uuid}"
|
||||
if product_id:
|
||||
url += f"&product_id={product_id}"
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_user_activity(self, baseurl, offset="", limit="", ):
|
||||
headers={}
|
||||
url=f"{baseurl}/history"
|
||||
|
||||
|
||||
if offset:
|
||||
url += f"&offset={offset}"
|
||||
if limit:
|
||||
url += f"&limit={limit}"
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_user_profile(self, baseurl):
|
||||
headers={}
|
||||
url=f"{baseurl}/me"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_product_types(self, baseurl, latitude, longitude):
|
||||
headers={}
|
||||
url=f"{baseurl}/products?latitude={latitude}&longitude={longitude}"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
async def get_price_estimates(self, baseurl, start_latitude, start_longitude, end_latitude, end_longitude):
|
||||
headers={}
|
||||
url=f"{baseurl}/estimates/price?start_latitude={start_latitude}&start_longitude={start_longitude}&end_latitude={end_latitude}&end_longitude={end_longitude}"
|
||||
|
||||
|
||||
return requests.get(url, headers=headers).text
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(UberAPIf97a44ddf1c348aeb46fceb19ce3039c.run(), debug=True)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
@@ -0,0 +1,31 @@
|
||||
name: a
|
||||
is_valid: true
|
||||
id: 31e2332c-8baa-41e9-98af-c2457d64d946
|
||||
link: ""
|
||||
app_version: 1.0.0
|
||||
generated: true
|
||||
sharing: false
|
||||
verified: false
|
||||
tested: false
|
||||
owner: c2dbe917-f982-40ed-9045-462872c4ca1e
|
||||
private_id: 757f74fead843a8d9b5a954d2fadfa69
|
||||
description: ""
|
||||
environment: cloud
|
||||
smallimage: ""
|
||||
large_image: ""
|
||||
contact_info:
|
||||
name: ""
|
||||
url: ""
|
||||
actions: []
|
||||
authentication:
|
||||
required: true
|
||||
parameters:
|
||||
- description: ""
|
||||
id: ""
|
||||
name: ""
|
||||
example: ""
|
||||
value: ""
|
||||
multiline: false
|
||||
required: true
|
||||
in: ""
|
||||
scheme: ""
|
||||
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
@@ -0,0 +1,23 @@
|
||||
import requests
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from walkoff_app_sdk.app_base import AppBase
|
||||
|
||||
class a757f74fead843a8d9b5a954d2fadfa69(AppBase):
|
||||
"""
|
||||
Autogenerated class by Shuffler
|
||||
"""
|
||||
|
||||
__version__ = "1.0"
|
||||
app_name = "a757f74fead843a8d9b5a954d2fadfa69"
|
||||
|
||||
def __init__(self, redis, logger, console_logger=None):
|
||||
self.verify = False
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
super().__init__(redis, logger, console_logger)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(a757f74fead843a8d9b5a954d2fadfa69.run(), debug=True)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Base our app image off of the WALKOFF App SDK image
|
||||
FROM frikky/shuffle:app_sdk as base
|
||||
|
||||
# We're going to stage away all of the bloat from the build tools so lets create a builder stage
|
||||
FROM base as builder
|
||||
|
||||
# Install all alpine build tools needed for our pip installs
|
||||
RUN apk --no-cache add --update alpine-sdk libffi libffi-dev musl-dev openssl-dev
|
||||
|
||||
# Install all of our pip packages in a single directory that we can copy to our base image later
|
||||
RUN mkdir /install
|
||||
WORKDIR /install
|
||||
COPY requirements.txt /requirements.txt
|
||||
RUN pip install --prefix="/install" -r /requirements.txt
|
||||
|
||||
# Switch back to our base image and copy in all of our built packages and source code
|
||||
FROM base
|
||||
COPY --from=builder /install /usr/local
|
||||
COPY src /app
|
||||
|
||||
# Install any binary dependencies needed in our final image - this can be a lot of different stuff
|
||||
RUN apk --no-cache add --update libmagic
|
||||
|
||||
# Finally, lets run our app!
|
||||
WORKDIR /app
|
||||
CMD python app.py --log-level DEBUG
|
||||
@@ -0,0 +1,31 @@
|
||||
name: test
|
||||
is_valid: true
|
||||
id: a29d4143-fa3b-4456-86c4-fee2d402ddf6
|
||||
link: https://test.com
|
||||
app_version: 1.0.0
|
||||
generated: true
|
||||
sharing: false
|
||||
verified: false
|
||||
tested: false
|
||||
owner: c2dbe917-f982-40ed-9045-462872c4ca1e
|
||||
private_id: f383aa4f34d36802daf465e2af5f7aa1
|
||||
description: test
|
||||
environment: cloud
|
||||
smallimage: ""
|
||||
large_image: ""
|
||||
contact_info:
|
||||
name: ""
|
||||
url: ""
|
||||
actions: []
|
||||
authentication:
|
||||
required: true
|
||||
parameters:
|
||||
- description: ""
|
||||
id: ""
|
||||
name: ""
|
||||
example: ""
|
||||
value: ""
|
||||
multiline: false
|
||||
required: true
|
||||
in: ""
|
||||
scheme: ""
|
||||
@@ -0,0 +1,3 @@
|
||||
# No extra requirements needed
|
||||
requests
|
||||
urllib3
|
||||
@@ -0,0 +1,23 @@
|
||||
import requests
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
from walkoff_app_sdk.app_base import AppBase
|
||||
|
||||
class testf383aa4f34d36802daf465e2af5f7aa1(AppBase):
|
||||
"""
|
||||
Autogenerated class by Shuffler
|
||||
"""
|
||||
|
||||
__version__ = "1.0"
|
||||
app_name = "testf383aa4f34d36802daf465e2af5f7aa1"
|
||||
|
||||
def __init__(self, redis, logger, console_logger=None):
|
||||
self.verify = False
|
||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
||||
super().__init__(redis, logger, console_logger)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(testf383aa4f34d36802daf465e2af5f7aa1.run(), debug=True)
|
||||
@@ -0,0 +1,31 @@
|
||||
module shuffle
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.57.0
|
||||
cloud.google.com/go/datastore v1.1.0
|
||||
cloud.google.com/go/pubsub v1.3.1
|
||||
cloud.google.com/go/storage v1.7.0
|
||||
github.com/basgys/goxml2json v1.1.0
|
||||
github.com/docker/distribution v2.7.1+incompatible // indirect
|
||||
github.com/docker/docker v1.13.1
|
||||
github.com/docker/go-connections v0.4.0
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/getkin/kin-openapi v0.8.0
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/go-git/go-billy/v5 v5.0.0
|
||||
github.com/go-git/go-git/v5 v5.0.0
|
||||
github.com/google/go-github/v28 v28.1.1
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/h2non/filetype v1.0.12
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
|
||||
github.com/satori/go.uuid v1.2.0
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
google.golang.org/api v0.23.0
|
||||
google.golang.org/appengine v1.6.6
|
||||
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86
|
||||
)
|
||||
@@ -0,0 +1,400 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
|
||||
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
|
||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||
cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms=
|
||||
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||
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.6.0/go.mod h1:hyFDG0qSGdHNz8Q6nDN8rYIkld0q/+5uBZaelxiDLfE=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
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=
|
||||
cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU=
|
||||
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||
cloud.google.com/go/storage v1.7.0 h1:DzdLPI8Em+DEk7IzA2a10ivq3mxIEASC9GeNJ6FFt5Q=
|
||||
cloud.google.com/go/storage v1.7.0/go.mod h1:jGMIBwF+L/tL6WN/W5InNgYYu4HP0DvGB6rQ1mufWfs=
|
||||
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/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
|
||||
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
|
||||
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/getkin/kin-openapi v0.8.0 h1:a6TQjTqwkyscC4/hShJX7WhCVE+4bi9lzw61XHQW5hE=
|
||||
github.com/getkin/kin-openapi v0.8.0/go.mod h1:zZQMFkVgRHCdhgb6ihCTIo9dyDZFvX0k/xAKqw1FhPw=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
|
||||
github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
|
||||
github.com/go-git/go-billy v4.2.0+incompatible h1:Z6QtVXd5tjxUtcODLugkJg4WaZnGg13CD8qB9pr+7q0=
|
||||
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
|
||||
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
|
||||
github.com/go-git/go-git v4.7.0+incompatible h1:+W9rgGY4DOKKdX2x6HxSR7HNeTxqiKrOvKnuittYVdA=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
|
||||
github.com/go-git/go-git/v5 v5.0.0 h1:k5RWPm4iJwYtfWoxIJy4wJX9ON7ihPeZZYC1fLYDnpg=
|
||||
github.com/go-git/go-git/v5 v5.0.0/go.mod h1:oYD8y9kWsGINPFJoLdaScGCN6dlKg23blmClfZwtUVA=
|
||||
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/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=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github/v28 v28.1.1 h1:kORf5ekX5qwXO2mGzXXOjMe/g6ap8ahVe0sBEulhSxo=
|
||||
github.com/google/go-github/v28 v28.1.1/go.mod h1:bsqJWQX05omyWVmc00nEUql9mhQyv38lDZ8kPZcQVoM=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
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/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/h2non/filetype v1.0.12 h1:yHCsIe0y2cvbDARtJhGBTD2ecvqMSTvlIcph9En/Zao=
|
||||
github.com/h2non/filetype v1.0.12/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||
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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
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/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88=
|
||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-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=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-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=
|
||||
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
|
||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-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-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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-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-20200122134326-e047566fdf82/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=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e h1:hq86ru83GdWTlfQFZGO4nZJTU4Bs2wfHl8oFHRaXsfc=
|
||||
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
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=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-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=
|
||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20200409170454-77362c5149f0/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||
google.golang.org/api v0.23.0 h1:YlvGEOq2NA2my8cZ/9V8BcEO9okD48FlJcdqN0xJL3s=
|
||||
google.golang.org/api v0.23.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||
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=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
|
||||
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200409111301-baae70f3302d/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 h1:Bz1qTn2YRWV+9OKJtxHJiQKCiXIdf+kwuKXdt9cBxyU=
|
||||
google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
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=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/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.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 h1:OfFoIUYv/me30yv7XlMy4F9RJw8DEm8WQ6QG1Ph4bH0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
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=
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable
BIN
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
#!/bin/sh
|
||||
# docker stop nginx
|
||||
# docker rm nginx
|
||||
# docker rmi nginx
|
||||
#
|
||||
# echo "Running build for website"
|
||||
# sudo npm run build
|
||||
# docker build . -t nginx
|
||||
|
||||
echo "Starting server"
|
||||
docker run -it \
|
||||
-p 5001:5001 \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
--env DATASTORE_EMULATOR_HOST=192.168.3.6:8000 \
|
||||
frikky/shuffle:backend
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
curl http://localhost:5001/api/v1/execution_cleanup -H "Authorization: Bearer e08c6f22-9a55-4557-b008-04388cc51fb0"
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
curl -XPOST http://localhost:5001/api/v1/workflows/1d9d8ce2-566e-4c3f-8a37-5d6c7d2000b5/execute -d '{"execution_argument":""}' -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26"
|
||||
|
||||
|
||||
curl -XPOST http://localhost:5001/api/v1/workflows/1d9d8ce2-566e-4c3f-8a37-5d6c7d2000b5/execute -d '{"execution_argument":""}' -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjYwZjQwNjBlNThkNzVmZDNmNzBiZWZmODhjNzk0YTc3NTMyN2FhMzEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL3NodWZmbGVyLmlvL2FwaS92MS93b3JrZmxvd3MvMWQ5ZDhjZTItNTY2ZS00YzNmLThhMzctNWQ2YzdkMjAwMGI1L2V4ZWN1dGUiLCJhenAiOiIxMDMwNzY3ODIwNjE0MjQ2MTg0MjIiLCJlbWFpbCI6InNjaGVkdWxlckBzaHVmZmxlLTI0MTUxNy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1NjU1Mjc1NTEsImlhdCI6MTU2NTUyMzk1MSwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAzMDc2NzgyMDYxNDI0NjE4NDIyIn0.r0EDq9fjhf_5CPTiltyfk_L3uYJp577Uy0yYPcCAl2nv50_z_oUtbWGBpQLL8gcj-NGd3g4E52Qur8k6hCMIQweLS6WAb1279vGffEoCNDfkWb3Oy-yJGP1kzwLvqFJqnHLkSWYXNWvSyWnEimW8Rryx_m1BXS5wcA8l4NIr83kS7fPZrTwjnwFSeGSThwk91DVARzapQb8r0GEgOUyHZ1aBXnV98mikzSUt-5xFKe9eMdD22YJAj0Ru-DxAxs5nOqghX4PMRysWjshjOMrlR1piPWxqAmewp8YKZDCQ5gXskpeAFBDoULT971Wsx_NCohnJsFqx1JfPS9ZYMTW2oQ"
|
||||
@@ -0,0 +1,24 @@
|
||||
#curl localhost:5000/api/v1/hooks
|
||||
|
||||
# Starts a webhook
|
||||
# curl localhost:5000/api/v1/hooks/d6ef8912e8bd37776e654cbc14c2629c/start
|
||||
|
||||
# Runs a request towards the webhook created
|
||||
#curl -XPOST localhost:5002/webhook -d '{"helo": "hi"}'
|
||||
|
||||
# Gets the ID of a new hook
|
||||
|
||||
#curl -X PUT localhost:5001/api/v1/hooks/e6f77059e6d469a6c4c314cc06d5a4c0 -d '{"name": "asd", "description": "hola", "type": "webhook", "id": "e6f77059e6d469a6c4c314cc06d5a4c0", "status": "stopped", "info": {"name": "lul", "url": "http://test"}}'
|
||||
|
||||
#curl -X POST localhost:5000/api/v1/hooks/new -d '{"name": "asd", "description": "hola", "type": "webhook"}'
|
||||
|
||||
#curl -X POST "https://europe-west1-shuffle-241517.cloudfunctions.net/webhook_982995716e67c3a549092d3a3a7921cd" -H "Content-Type:application/json" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data '{"name":"Keyboard Cat"}' -v
|
||||
|
||||
|
||||
#jcurl http://localhost:5001/api/v1/hooks/b4ba07c9-45d4-41f2-b260-83c8e99eba0c -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26"
|
||||
#curl https://shuffler.io/api/v1/hooks/b4ba07c9-45d4-41f2-b260-83c8e99eba0c -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26"
|
||||
#curl -X POST "http://localhost:8080" -H "Content-Type:application/json" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data '{"test": {"hello": "HEYOOOO"}}' -v
|
||||
|
||||
#curl -X POST "https://europe-west1-shuffle-241517.cloudfunctions.net/webhook_3ceff795-ce9a-43a2-a2f5-d4401a6e772d" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data 'wut'
|
||||
curl POST "https://europe-west1-shuffler.cloudfunctions.net/outlooktrigger_be4dbb0a-d396-4544-bc36-e57d1bdb2e40" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data 'wut' -vvv
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
# This is a script to test a function by itself
|
||||
|
||||
import requests
|
||||
import json
|
||||
|
||||
def invoke(url, headers, message):
|
||||
# Used for testing
|
||||
try:
|
||||
ret = requests.post(url, headers=headers, json=message, timeout=5)
|
||||
print(ret.text)
|
||||
print(ret.status_code)
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
print(f"Requesterror: {e}")
|
||||
|
||||
def invoke_multi(url, headers, message):
|
||||
cnt = 0
|
||||
maxcnt = 100
|
||||
print("Running %d requests towards %s." % (maxcnt, url))
|
||||
while(1):
|
||||
try:
|
||||
ret = requests.post(url, headers=headers, json=message, timeout=1)
|
||||
print(ret.status_code)
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
print(f"Connectionerror: {e}")
|
||||
except requests.exceptions.ReadTimeout as e:
|
||||
print(f"Readtimeout: {e}")
|
||||
|
||||
cnt += 1
|
||||
if cnt == maxcnt:
|
||||
break
|
||||
|
||||
print("Done :)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Specific thingies for hello_world
|
||||
message = {
|
||||
"parameters": [{
|
||||
"id_": "asd",
|
||||
"name": "call",
|
||||
"value": "REPEAT THIS DATA PLEASE THANKS",
|
||||
"variant": "STATIC_VALUE",
|
||||
}],
|
||||
"name": "repeat_back_to_me",
|
||||
"execution_id": "asd",
|
||||
"label": "",
|
||||
"position": "",
|
||||
"app_name": "hello_world",
|
||||
"app_version": "1.0.0",
|
||||
"label": "lul",
|
||||
"priority": "1",
|
||||
"id_": "test",
|
||||
"id": "test",
|
||||
"authorization": "hey",
|
||||
}
|
||||
|
||||
apikey = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjYwZjQwNjBlNThkNzVmZDNmNzBiZWZmODhjNzk0YTc3NTMyN2FhMzEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL3NodWZmbGVyLmlvL2FwaS92MS93b3JrZmxvd3MvMWQ5ZDhjZTItNTY2ZS00YzNmLThhMzctNWQ2YzdkMjAwMGI1L2V4ZWN1dGUiLCJhenAiOiIxMDMwNzY3ODIwNjE0MjQ2MTg0MjIiLCJlbWFpbCI6InNjaGVkdWxlckBzaHVmZmxlLTI0MTUxNy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1NjU1Mjc1NTEsImlhdCI6MTU2NTUyMzk1MSwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAzMDc2NzgyMDYxNDI0NjE4NDIyIn0.r0EDq9fjhf_5CPTiltyfk_L3uYJp577Uy0yYPcCAl2nv50_z_oUtbWGBpQLL8gcj-NGd3g4E52Qur8k6hCMIQweLS6WAb1279vGffEoCNDfkWb3Oy-yJGP1kzwLvqFJqnHLkSWYXNWvSyWnEimW8Rryx_m1BXS5wcA8l4NIr83kS7fPZrTwjnwFSeGSThwk91DVARzapQb8r0GEgOUyHZ1aBXnV98mikzSUt-5xFKe9eMdD22YJAj0Ru-DxAxs5nOqghX4PMRysWjshjOMrlR1piPWxqAmewp8YKZDCQ5gXskpeAFBDoULT971Wsx_NCohnJsFqx1JfPS9ZYMTW2oQ"
|
||||
headers = {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {apikey}"
|
||||
}
|
||||
|
||||
location = "europe-west2"
|
||||
functionname = "hello-world-1-0-6"
|
||||
project = "shuffler"
|
||||
|
||||
url = f"https://{location}-{project}.cloudfunctions.net/{functionname}"
|
||||
print(url)
|
||||
invoke(url, headers, message)
|
||||
#invoke_multi(url, headers, message)
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
curl localhost:5000/api/v1/schedules/apps
|
||||
@@ -0,0 +1,2 @@
|
||||
# Fails cus of unmarshal
|
||||
curl -XPOST http://localhost:5001/api/v1/workflows/1d9d8ce2-566e-4c3f-8a37-5d6c7d2000b5/schedule -d '{"name": "hey", "frequency": "*/1 * * * *", "execution_argument": "{\"test\": \"hey\"}"}' -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjYwZjQwNjBlNThkNzVmZDNmNzBiZWZmODhjNzk0YTc3NTMyN2FhMzEiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJodHRwczovL3NodWZmbGVyLmlvL2FwaS92MS93b3JrZmxvd3MvMWQ5ZDhjZTItNTY2ZS00YzNmLThhMzctNWQ2YzdkMjAwMGI1L2V4ZWN1dGUiLCJhenAiOiIxMDMwNzY3ODIwNjE0MjQ2MTg0MjIiLCJlbWFpbCI6InNjaGVkdWxlckBzaHVmZmxlLTI0MTUxNy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1NjU1Mjc1NTEsImlhdCI6MTU2NTUyMzk1MSwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tIiwic3ViIjoiMTAzMDc2NzgyMDYxNDI0NjE4NDIyIn0.r0EDq9fjhf_5CPTiltyfk_L3uYJp577Uy0yYPcCAl2nv50_z_oUtbWGBpQLL8gcj-NGd3g4E52Qur8k6hCMIQweLS6WAb1279vGffEoCNDfkWb3Oy-yJGP1kzwLvqFJqnHLkSWYXNWvSyWnEimW8Rryx_m1BXS5wcA8l4NIr83kS7fPZrTwjnwFSeGSThwk91DVARzapQb8r0GEgOUyHZ1aBXnV98mikzSUt-5xFKe9eMdD22YJAj0Ru-DxAxs5nOqghX4PMRysWjshjOMrlR1piPWxqAmewp8YKZDCQ5gXskpeAFBDoULT971Wsx_NCohnJsFqx1JfPS9ZYMTW2oQ"
|
||||
@@ -0,0 +1,3 @@
|
||||
#curl -X POST -H "Content-Type: application/json" shuffler.io/functions/sendmail -H "Authorization: Bearer " -d '{"target": "frikky@shuffler.io", "body": "Hey, this is a body for something to look at", "subject": "SOS check me", "type": "alert", "sender_company": "shuffler"}'
|
||||
|
||||
curl -X POST -H "Content-Type: application/json" localhost:5001/functions/sendmail -H "Authorization: Bearer " -d '{"targets": ["frikky@shuffler.io", "rheyix.yt@gmail.com"], "body": "Hey, this is a body for something to look at", "subject": "SOS check me", "type": "alert", "sender_company": "shuffler"}'
|
||||
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Should give 401
|
||||
curl localhost:5000/api/v1/uploadResult/asdasd -d {}
|
||||
echo
|
||||
|
||||
# Should give 200 if it exists
|
||||
curl localhost:5000/api/v1/uploadResult/e07910a06a086c83ba41827aa00b26ed -d '{"title": "helo","description": "wut", "type": "hi", "source": "wutface", "sourceRef": "halvor hei"}'
|
||||
@@ -0,0 +1 @@
|
||||
curl -H "Content-Type: application/json" localhost:5001/api/v1/triggers/9e845679-5843-4959-a76c-a6d664e9df35 -H "Authorization: Bearer 377469e8-dd5d-4521-8d9e-416d8d2f6fd4"
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
curl http://localhost:5001/ws -H "Connections: Upgrade"
|
||||
|
||||
#curl -X POST "https://europe-west1-shuffle-241517.cloudfunctions.net/webhook_982995716e67c3a549092d3a3a7921cd" -H "Content-Type:application/json" -H "Authorization: Bearer 144308d0-6aab-4d4f-8bb2-75189281ee26" --data '{"name":"Keyboard Cat"}' -v
|
||||
@@ -0,0 +1,202 @@
|
||||
[
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"app_name": "hello_world",
|
||||
"app_version": "1.0.0",
|
||||
"errors": [],
|
||||
"id_": "2686a5d4-531d-158f-6b1a-0c1d23481304",
|
||||
"is_valid": true,
|
||||
"label": "check_bool",
|
||||
"name": "check_bool",
|
||||
"environment": "cloud",
|
||||
"parameters": [],
|
||||
"position": {
|
||||
"x": 329.98133726556375,
|
||||
"y": 160.01013778166904
|
||||
},
|
||||
"priority": 3
|
||||
}
|
||||
],
|
||||
"branches": [
|
||||
{
|
||||
"destination_id": "6478ecae-b10e-88e9-e34d-9bbe6aff393d",
|
||||
"id_": "5fd6a357-ae33-b1af-5dc2-0306efa28887",
|
||||
"source_id": "2686a5d4-531d-158f-6b1a-0c1d23481304"
|
||||
},
|
||||
{
|
||||
"destination_id": "2686a5d4-531d-158f-6b1a-0c1d23481304",
|
||||
"id_": "d46d0b05-5757-5084-c339-70ac63985781",
|
||||
"source_id": "6478ecae-b10e-88e9-e34d-9bbe6aff393d"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
{
|
||||
"app_name": "Builtin",
|
||||
"app_version": "1.0.0",
|
||||
"conditional": "",
|
||||
"errors": [],
|
||||
"id_": "6478ecae-b10e-88e9-e34d-9bbe6aff393d",
|
||||
"is_valid": true,
|
||||
"label": "Condition",
|
||||
"name": "Condition",
|
||||
"position": {
|
||||
"x": 320.97142988802364,
|
||||
"y": 394.9753467582139
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "",
|
||||
"errors": [],
|
||||
"id_": "a5f82cfd-0f38-3474-20e2-f757f3718707",
|
||||
"is_valid": true,
|
||||
"name": "asd2",
|
||||
"start": "2686a5d4-531d-158f-6b1a-0c1d23481304",
|
||||
"tags": [],
|
||||
"transforms": [],
|
||||
"triggers": [],
|
||||
"workflow_variables": []
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"app_name": "hello_world",
|
||||
"app_version": "1.0.0",
|
||||
"errors": [],
|
||||
"id_": "51df7c4f-b856-1aca-402b-9fec660b6505",
|
||||
"is_valid": true,
|
||||
"label": "wut",
|
||||
"name": "hello_world",
|
||||
"parameters": [],
|
||||
"position": {
|
||||
"x": 250,
|
||||
"y": 150
|
||||
},
|
||||
"priority": 3
|
||||
},
|
||||
{
|
||||
"app_name": "hello_world",
|
||||
"app_version": "1.0.0",
|
||||
"errors": [],
|
||||
"id_": "36975212-3b9a-2e4c-4ad7-0ee5a6325842",
|
||||
"is_valid": true,
|
||||
"label": "check_bool",
|
||||
"name": "check_bool",
|
||||
"parameters": [],
|
||||
"position": {
|
||||
"x": 241.00207363715955,
|
||||
"y": 294.9896318142021
|
||||
},
|
||||
"priority": 3
|
||||
}
|
||||
],
|
||||
"branches": [
|
||||
{
|
||||
"destination_id": "36975212-3b9a-2e4c-4ad7-0ee5a6325842",
|
||||
"id_": "44231b8f-4331-764e-0c1d-ccbc901d1309",
|
||||
"source_id": "51df7c4f-b856-1aca-402b-9fec660b6505"
|
||||
},
|
||||
{
|
||||
"destination_id": "51df7c4f-b856-1aca-402b-9fec660b6505",
|
||||
"id_": "9b3dc561-e879-4877-c32e-ab7149d83b39",
|
||||
"source_id": "36975212-3b9a-2e4c-4ad7-0ee5a6325842"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"description": "",
|
||||
"errors": [],
|
||||
"id_": "4e437698-fc18-29d3-e875-969b57354685",
|
||||
"is_valid": true,
|
||||
"name": "hi",
|
||||
"start": "51df7c4f-b856-1aca-402b-9fec660b6505",
|
||||
"tags": [],
|
||||
"transforms": [],
|
||||
"triggers": [],
|
||||
"workflow_variables": []
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"app_name": "hello_world",
|
||||
"app_version": "1.0.0",
|
||||
"errors": [],
|
||||
"id_": "d0dbd1c4-dd61-6d4a-70e1-ac05dad0fe1f",
|
||||
"is_valid": true,
|
||||
"label": "i am bool",
|
||||
"name": "check_bool",
|
||||
"parameters": [],
|
||||
"position": {
|
||||
"x": 377.9998262128892,
|
||||
"y": 330.01190441708906
|
||||
},
|
||||
"priority": 3
|
||||
},
|
||||
{
|
||||
"app_name": "hello_world",
|
||||
"app_version": "1.0.0",
|
||||
"errors": [],
|
||||
"id_": "39353c1c-b179-152c-f977-615a15a5de37",
|
||||
"is_valid": true,
|
||||
"label": "hello_world",
|
||||
"name": "hello_world",
|
||||
"parameters": [],
|
||||
"position": {
|
||||
"x": 375.2590614780782,
|
||||
"y": 160.6226941577116
|
||||
},
|
||||
"priority": 3
|
||||
}
|
||||
],
|
||||
"branches": [
|
||||
{
|
||||
"destination_id": "d0dbd1c4-dd61-6d4a-70e1-ac05dad0fe1f",
|
||||
"id_": "7c81993f-5fd6-fc83-2f41-8074d6c8dc25",
|
||||
"source_id": "39353c1c-b179-152c-f977-615a15a5de37"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"description": "",
|
||||
"errors": [],
|
||||
"id_": "af8467be-43ca-d38b-3f7e-9aeb922fb21a",
|
||||
"is_valid": true,
|
||||
"name": "new!",
|
||||
"start": "39353c1c-b179-152c-f977-615a15a5de37",
|
||||
"tags": [],
|
||||
"transforms": [],
|
||||
"triggers": [],
|
||||
"workflow_variables": []
|
||||
},
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"app_name": "Builtin",
|
||||
"app_version": "1.0.0",
|
||||
"errors": [],
|
||||
"id_": "7dddec9a-b493-8b58-9234-1b74dd9b420a",
|
||||
"is_valid": true,
|
||||
"label": "Boolean",
|
||||
"name": "Boolean",
|
||||
"parameters": [],
|
||||
"position": {
|
||||
"x": 350,
|
||||
"y": 250
|
||||
},
|
||||
"priority": 3
|
||||
}
|
||||
],
|
||||
"branches": [],
|
||||
"conditions": [],
|
||||
"description": "",
|
||||
"errors": [
|
||||
"Action Builtin.Boolean does not exist"
|
||||
],
|
||||
"id_": "07bae551-21e6-c0f5-4db3-81e8a1e8a805",
|
||||
"is_valid": false,
|
||||
"name": "wutface",
|
||||
"start": "7dddec9a-b493-8b58-9234-1b74dd9b420a",
|
||||
"tags": [],
|
||||
"transforms": [],
|
||||
"triggers": [],
|
||||
"workflow_variables": []
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
#curl -X POST -H "Content-Type: application/json" localhost:5001/api/v1/workflows/3d14ca4a-67bd-8dfb-2673-2864f1ccf59c/execute -d '{"workflow_id": "3d14ca4a-67bd-8dfb-2673-2864f1ccf59c", "execution_id": "eaaa8d19-a761-12b8-cac2-f34eb50c3711"}'
|
||||
|
||||
curl -X POST -H "Content-Type: application/json" https://shuffle-241517.appspot.com/api/v1/workflows/3d14ca4a-67bd-8dfb-2673-2864f1ccf59c/execute -d '{"workflow_id": "3d14ca4a-67bd-8dfb-2673-2864f1ccf59c", "execution_id": "eaaa8d19-a761-12b8-cac2-f34eb50c3711"}'
|
||||
|
||||
#curl -X POST http://localhost:5001/api/v1/workflows/streams -H "Content-Type: application/json" \
|
||||
# -d '{"execution_id": "eaaa8d19-a761-12b8-cac2-f34eb50c3711",
|
||||
# "result": "hello_result",
|
||||
# "started_at": 1562309342,
|
||||
# "authorization": "afcc298d-c6c2-4b0d-8221-1603b44d072d",
|
||||
# "status": "ABORTED",
|
||||
# "action": {
|
||||
# "app_name": "hi",
|
||||
# "app_version": "ho",
|
||||
# "id_": "this_is_an_id",
|
||||
# "label": "wut",
|
||||
# "name": "stream_testing",
|
||||
# "parameters": [],
|
||||
# "position": {
|
||||
# "x": 100,
|
||||
# "y": 100
|
||||
# },
|
||||
# "priority": 1
|
||||
# }}'
|
||||
@@ -0,0 +1,15 @@
|
||||
# Get all workflows
|
||||
curl localhost:5001/api/v1/workflows
|
||||
|
||||
# Get A workflow
|
||||
#curl localhost:5001/api/v1/workflows/a5f82cfd-0f38-3474-20e2-f757f3718707
|
||||
|
||||
# NEW workflow
|
||||
# curl -XPOST localhost:5001/api/v1/workflows -d '{"tags":[],"actions":[],"branches":[],"conditions":[{"label":"Condition","app_name":"Builtin","name":"Condition","conditional":"","id_":"18165f42-aab9-6c9a-0ef4-4e5a37a3b2ad","app_version":"1.0.0","position":{"x":224,"y":168}}],"workflow_variables":[],"name":"asd","start":"18165f42-aab9-6c9a-0ef4-4e5a37a3b2ad","id_":"3d14ca4a-67bd-8dfb-2673-2864f1ccf59c"}'
|
||||
|
||||
# Add a workflow
|
||||
#curl localhost:5001/api/v1/workflows/a5f82cfd-0f38-3474-20e2-f757f3718707 -d '{"actions":[{"app_name":"hello_world","app_version":"1.0.0","errors":[],"id_":"2686a5d4-531d-158f-6b1a-0c1d23481304","is_valid":true,"label":"check_bool","name":"check_bool","parameters":[],"position":{"x":329.98133726556375,"y":160.01013778166904},"priority":3}],"branches":[{"destination_id":"6478ecae-b10e-88e9-e34d-9bbe6aff393d","id_":"5fd6a357-ae33-b1af-5dc2-0306efa28887","source_id":"2686a5d4-531d-158f-6b1a-0c1d23481304"},{"destination_id":"2686a5d4-531d-158f-6b1a-0c1d23481304","id_":"d46d0b05-5757-5084-c339-70ac63985781","source_id":"6478ecae-b10e-88e9-e34d-9bbe6aff393d"}],"conditions":[{"app_name":"Builtin","app_version":"1.0.0","conditional":"","errors":[],"id_":"6478ecae-b10e-88e9-e34d-9bbe6aff393d","is_valid":true,"label":"Condition","name":"Condition","position":{"x":320.97142988802364,"y":394.9753467582139}}],"description":"","errors":[],"id_":"a5f82cfd-0f38-3474-20e2-f757f3718707","is_valid":true,"name":"asd2","start":"2686a5d4-531d-158f-6b1a-0c1d23481304","tags":[],"transforms":[],"triggers":[],"workflow_variables":[]}'
|
||||
|
||||
# Execute a workflow
|
||||
# curl -H "Content-Type: application/json" localhost:5001/api/v1/workflows/3d14ca4a-67bd-8dfb-2673-2864f1ccf59c/execute
|
||||
#curl -X POST -H "Content-Type: application/json" localhost:5001/api/v1/workflows/3d14ca4a-67bd-8dfb-2673-2864f1ccf59c/execute -d '{"workflow_id": "3d14ca4a-67bd-8dfb-2673-2864f1ccf59c", "execution_id": "eaaa8d19-a761-12b8-cac2-f34eb50c3711"}'
|
||||
@@ -0,0 +1,15 @@
|
||||
# Build environment
|
||||
# production environment
|
||||
from golang as builder
|
||||
|
||||
RUN go get github.com/gorilla/handlers
|
||||
RUN go get github.com/gorilla/mux
|
||||
|
||||
WORKDIR /app
|
||||
COPY webhook.go /app/webhook.go
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o webhook .
|
||||
|
||||
from scratch
|
||||
COPY --from=builder /app/ /
|
||||
|
||||
CMD ["./webhook"]
|
||||
@@ -0,0 +1,7 @@
|
||||
# Steps to deploy to Google cloud function
|
||||
1.
|
||||
```bash
|
||||
zip webhook.zip *
|
||||
```
|
||||
2. Go to google cloud bucket and upload the zip
|
||||
3. Go to worker for webhook and upload
|
||||
@@ -0,0 +1,44 @@
|
||||
package function
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetUserDetails - Get one user's details from randomuser.me API
|
||||
func GetUserDetails(w http.ResponseWriter, r *http.Request) {
|
||||
randomUserClient := http.Client{
|
||||
Timeout: time.Second * 3,
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, "https://randomuser.me/api/", nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
}
|
||||
|
||||
res, err2 := randomUserClient.Do(req)
|
||||
if err2 != nil {
|
||||
log.Fatal(err2)
|
||||
return
|
||||
}
|
||||
|
||||
body, err3 := ioutil.ReadAll(res.Body)
|
||||
if err3 != nil {
|
||||
log.Fatal(err3)
|
||||
}
|
||||
|
||||
var o map[string]interface{}
|
||||
json.Unmarshal([]byte(body), &o)
|
||||
|
||||
results := o["results"].([]interface{})
|
||||
result := results[0].(map[string]interface{})
|
||||
|
||||
result["generator"] = "google-cloud-function"
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(result)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
docker build . -t gcr.io/shuffle-241517/webhook
|
||||
docker push gcr.io/shuffle-241517/webhook
|
||||
|
||||
gcloud beta run deploy webhook --image gcr.io/shuffle-241517/webhook
|
||||
@@ -0,0 +1,16 @@
|
||||
docker stop webhook
|
||||
docker rm webhook
|
||||
docker rmi webhook
|
||||
|
||||
docker build . -t webhook
|
||||
docker run -d \
|
||||
-e "HOOKPORT=5001" \
|
||||
-e "URIPATH=/webhook" \
|
||||
-e "CALLBACKURL=http://192.168.159.151:5000/api/v1/hooks/d6ef8912e8bd37776e654cbc14c2629c/result" \
|
||||
-p 5001:5001 \
|
||||
--name webhook \
|
||||
-h webhook \
|
||||
--restart always \
|
||||
webhook
|
||||
|
||||
docker logs -f webhook
|
||||
@@ -0,0 +1,260 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type Info struct {
|
||||
Url string `json:"url" datastore:"url"`
|
||||
Name string `json:"name" datastore:"name"`
|
||||
Description string `json:"description" datastore:"description"`
|
||||
}
|
||||
|
||||
// Actions to be done by webhooks etc
|
||||
// Field is the actual field to use from json
|
||||
type HookAction struct {
|
||||
Type string `json:"type" datastore:"type"`
|
||||
Name string `json:"name" datastore:"name"`
|
||||
Id string `json:"id" datastore:"id"`
|
||||
Field string `json:"field" datastore:"field"`
|
||||
}
|
||||
|
||||
type Hook struct {
|
||||
Id string `json:"id" datastore:"id"`
|
||||
Info Info `json:"info" datastore:"info"`
|
||||
Transforms struct{} `json:"transforms" datastore:"transforms"`
|
||||
Actions []HookAction `json:"actions" datastore:"actions"`
|
||||
Type string `json:"type" datastore:"type"`
|
||||
Status string `json:"status" datastore:"status"`
|
||||
Running bool `json:"running" datastore:"running"`
|
||||
}
|
||||
|
||||
var hook Hook
|
||||
|
||||
func handleWorkflowAction(request *http.Request, action HookAction) error {
|
||||
//log.Printf("WORKFLOW!: %#v", action)
|
||||
log.Printf("Should execute workflow %s", action.Id)
|
||||
|
||||
callbackUrl := os.Getenv("CALLBACKURL")
|
||||
apikey := os.Getenv("APIKEY")
|
||||
fullUrl := fmt.Sprintf("%s/api/v1/workflows/%s/execute", callbackUrl, action.Id)
|
||||
|
||||
// ret = requests.post(fullurl, headers=headers, json=data)
|
||||
//if ret.status_code != 202:
|
||||
// print(ret.text)
|
||||
// print(ret.status_code)
|
||||
// print("Exiting workflows - run queue")
|
||||
// exit()
|
||||
|
||||
body, err := ioutil.ReadAll(request.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Execute a workflow
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest(
|
||||
"POST",
|
||||
fullUrl,
|
||||
bytes.NewBuffer(body),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Error making http request: %s", req)
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", fmt.Sprintf(`Bearer %s`, apikey))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("Error in http request: %s", req)
|
||||
}
|
||||
|
||||
log.Printf("%#v", resp)
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME - refresh hook information once in a while. Compare timestamps or something
|
||||
func callback(resp http.ResponseWriter, request *http.Request) {
|
||||
//apikey = os.Getenv("APIKEY")
|
||||
//hookId = os.Getenv("HOOKID")
|
||||
|
||||
handledWorkflowIds := []string{}
|
||||
for _, item := range hook.Actions {
|
||||
if item.Type == "" {
|
||||
log.Printf("CONTINUE AAS EMPTY ITEM: %#v", item)
|
||||
continue
|
||||
}
|
||||
|
||||
if item.Type == "workflow" {
|
||||
found := false
|
||||
for _, workflowId := range handledWorkflowIds {
|
||||
if item.Id == workflowId {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
continue
|
||||
}
|
||||
|
||||
handledWorkflowIds = append(handledWorkflowIds, item.Id)
|
||||
err := handleWorkflowAction(request, item)
|
||||
if err != nil {
|
||||
log.Printf("Error in workflow exec: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME - send the webhookdata to a logging service? Idk
|
||||
//body, err := ioutil.ReadAll(request.Body)
|
||||
//if err != nil {
|
||||
// log.Println("Failed reading body")
|
||||
// resp.WriteHeader(401)
|
||||
// resp.Write([]byte(fmt.Sprintf(`{"success": false}`)))
|
||||
// return
|
||||
//}
|
||||
|
||||
//callback, err := http.Post(callbackUrl, "application/json", bytes.NewBuffer(body))
|
||||
//if err != nil {
|
||||
// log.Printf("Failed sending callback to %s", callbackUrl)
|
||||
//}
|
||||
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
|
||||
return
|
||||
}
|
||||
|
||||
func loadConfiguration(fullUrl string, apikey string) error {
|
||||
client := &http.Client{}
|
||||
|
||||
req, err := http.NewRequest(
|
||||
"GET",
|
||||
fullUrl,
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("Error making http request: %s", req)
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Add("Authorization", fmt.Sprintf(`Bearer %s`, apikey))
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("Error in http request: %s", req)
|
||||
return err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("Error reading response: %s", req)
|
||||
return err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &hook)
|
||||
if err != nil {
|
||||
log.Printf("Failed unmarshaling hook API", req)
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("%#v", hook)
|
||||
log.Println(hook.Actions)
|
||||
return nil
|
||||
}
|
||||
|
||||
func webhook() {
|
||||
// FIXME - remove static
|
||||
ip := "0.0.0.0"
|
||||
|
||||
// Basic webserver stuff
|
||||
baseFilePath := os.Getenv("URIPATH")
|
||||
basePort := os.Getenv("HOOKPORT")
|
||||
callbackUrl := os.Getenv("CALLBACKURL")
|
||||
apikey := os.Getenv("APIKEY")
|
||||
hookId := os.Getenv("HOOKID")
|
||||
|
||||
if len(baseFilePath) == 0 {
|
||||
log.Println("Env URIPATH not set")
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
if len(basePort) == 0 {
|
||||
log.Println("Env HOOKPORT not set")
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
if len(callbackUrl) == 0 {
|
||||
log.Println("Env CALLBACKURL not set")
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
if len(apikey) == 0 {
|
||||
log.Println("Env APIKEY not set")
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
if len(hookId) == 0 {
|
||||
log.Println("Env HOOKID not set")
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
log.Println("Loading hook configuration")
|
||||
err := loadConfiguration(
|
||||
fmt.Sprintf("%s/api/v1/hooks/%s", callbackUrl, hookId),
|
||||
apikey,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Error loading config: %s", err)
|
||||
}
|
||||
|
||||
// Optional
|
||||
// if len(callbackOpts) == 0 {
|
||||
// log.Println("Env CALLBACKOPTS not set")
|
||||
// os.Exit(3)
|
||||
// }
|
||||
|
||||
port := fmt.Sprintf(":%s", basePort)
|
||||
log.Printf("Starting webhook on %s%s with path %s", ip, port, baseFilePath)
|
||||
|
||||
// Routing
|
||||
mux := mux.NewRouter()
|
||||
mux.SkipClean(true)
|
||||
|
||||
// FIXME - Add path for updating the hook? Can be a specific POST requeuest from backend
|
||||
mux.HandleFunc(baseFilePath, callback).Methods("POST")
|
||||
|
||||
handlers.LoggingHandler(os.Stdout, mux)
|
||||
loggedRouter := handlers.LoggingHandler(os.Stdout, mux)
|
||||
|
||||
err = http.ListenAndServe(
|
||||
port,
|
||||
loggedRouter,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServer: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func F(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
w.Write([]byte(r.Header.Get("X-Forwarded-For")))
|
||||
}
|
||||
|
||||
func main() {
|
||||
webhook()
|
||||
}
|
||||
Reference in New Issue
Block a user