mirror of
https://github.com/prometheus-community/postgres_exporter
synced 2025-03-18 08:32:01 +00:00
Update for Prometheus Community
Add standard Prometheus build setup * CircleCI config * Makefile * Go modules * Golang-CI Lint * promu config * Remove /vendor * Remove mage build * Update READMEs https://github.com/prometheus-community/postgres_exporter/issues/478 Signed-off-by: Ben Kochie <superq@gmail.com>
This commit is contained in:
parent
8531abac46
commit
b67b69acd3
57
.circleci/config.yml
Normal file
57
.circleci/config.yml
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
version: 2.1
|
||||
|
||||
orbs:
|
||||
prometheus: prometheus/prometheus@0.8.0
|
||||
|
||||
executors:
|
||||
# This must match .promu.yml.
|
||||
golang:
|
||||
docker:
|
||||
- image: circleci/golang:1.15
|
||||
|
||||
jobs:
|
||||
test:
|
||||
executor: golang
|
||||
|
||||
steps:
|
||||
- prometheus/setup_environment
|
||||
- run: make
|
||||
- prometheus/store_artifact:
|
||||
file: postgres_exporter
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
postgres_exporter:
|
||||
jobs:
|
||||
- test:
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- prometheus/build:
|
||||
name: build
|
||||
filters:
|
||||
tags:
|
||||
only: /.*/
|
||||
- prometheus/publish_master:
|
||||
context: org-context
|
||||
docker_hub_organization: prometheuscommunity
|
||||
quay_io_organization: prometheuscommunity
|
||||
requires:
|
||||
- test
|
||||
- build
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- prometheus/publish_release:
|
||||
context: org-context
|
||||
docker_hub_organization: prometheuscommunity
|
||||
quay_io_organization: prometheuscommunity
|
||||
requires:
|
||||
- test
|
||||
- build
|
||||
filters:
|
||||
tags:
|
||||
only: /^v.*/
|
||||
branches:
|
||||
ignore: /.*/
|
@ -1,2 +0,0 @@
|
||||
*
|
||||
!bin/
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,3 +19,4 @@
|
||||
/.metrics.*.added
|
||||
/.metrics.*.removed
|
||||
/tools/src
|
||||
/vendor
|
||||
|
10
.golangci.yml
Normal file
10
.golangci.yml
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
issues:
|
||||
exclude-rules:
|
||||
- path: _test.go
|
||||
linters:
|
||||
- errcheck
|
||||
|
||||
linters-settings:
|
||||
errcheck:
|
||||
exclude: scripts/errcheck_excludes.txt
|
19
.promu.yml
Normal file
19
.promu.yml
Normal file
@ -0,0 +1,19 @@
|
||||
go:
|
||||
# This must match .circle/config.yml.
|
||||
version: 1.15
|
||||
repository:
|
||||
path: github.com/prometheus-community/postgres_exporter
|
||||
build:
|
||||
binaries:
|
||||
- name: postgres_exporter
|
||||
path: ./cmd/postgres_exporter
|
||||
flags: -a -tags 'netgo static_build'
|
||||
ldflags: |
|
||||
-X github.com/prometheus/common/version.Version={{.Version}}
|
||||
-X github.com/prometheus/common/version.Revision={{.Revision}}
|
||||
-X github.com/prometheus/common/version.Branch={{.Branch}}
|
||||
-X github.com/prometheus/common/version.BuildUser={{user}}@{{host}}
|
||||
-X github.com/prometheus/common/version.BuildDate={{date "20060102-15:04:05"}}
|
||||
tarball:
|
||||
files:
|
||||
- LICENSE
|
46
.travis.yml
46
.travis.yml
@ -1,46 +0,0 @@
|
||||
sudo: required
|
||||
services:
|
||||
- docker
|
||||
language: go
|
||||
go:
|
||||
- '1.11'
|
||||
before_install:
|
||||
- go get -v github.com/mattn/goveralls
|
||||
- sudo wget -O /usr/local/bin/p2 https://github.com/wrouesnel/p2cli/releases/download/r4/p2
|
||||
&& sudo chmod +x /usr/local/bin/p2
|
||||
- sudo wget -O /usr/local/bin/docker-compose https://github.com/docker/compose/releases/download/1.9.0-rc4/docker-compose-Linux-x86_64
|
||||
&& sudo chmod +x /usr/local/bin/docker-compose
|
||||
- sudo apt-get update && sudo apt-get install postgresql-client-common
|
||||
script:
|
||||
- "./gh-assets-clone.sh"
|
||||
- go run mage.go -v all
|
||||
- "$HOME/gopath/bin/goveralls -coverprofile=cover.out -service=travis-ci"
|
||||
- go run mage.go docker
|
||||
after_success:
|
||||
- docker login -u $DOCKER_USER -p $DOCKER_PASS
|
||||
- if [ ! -z "$TRAVIS_TAG" ]; then docker tag wrouesnel/postgres_exporter:latest wrouesnel/postgres_exporter:$TRAVIS_TAG
|
||||
; docker push wrouesnel/postgres_exporter:$TRAVIS_TAG ; fi
|
||||
- if [ "$TRAVIS_BRANCH" == "master" ]; then docker push wrouesnel/postgres_exporter
|
||||
; fi
|
||||
- "./postgres-metrics-get-changes.sh .assets-branch/metriclists"
|
||||
- if [ "$TRAVIS_BRANCH" == "master" ]; then ./gh-metrics-push.sh ; fi
|
||||
env:
|
||||
global:
|
||||
- DOCKER_USER=wrouesnel
|
||||
- GIT_ASSETS_BRANCH=assets
|
||||
- secure: sl1d85bipYhHlHTZ4fwkWrZ07px+lPMQrKPaiyQ9i5tylQAcMqwDroK0pb5HIyIl6PEx72D5atQWnEqluA/0rFt3SxqxtvT+wj6CPmmZfh2fUSol7I07QzAsi95d7q0fg2mStDdfs134Uu+JjxGKEGRu2SL3Zq+LKpaNPtIZVBqrCYYAySLiEJx+DEOfwt1ktn/qHapV5d5FYdfd7trfV411NITyA8AGk6Gy0HztRDGbfcoLOsM+CnVi1p59uUL9ck/hL2DbsB44qDKeWQaruMLwWNDETu+EVwHlDEHGBPb+wdDALnW+Ts3CAUpuGXftHV35XLLbH7NXOnS6QiH938ycfPf3INY51lV7cL6bNtFWDKMAIcPf4wQO2ts4qFhuiUeFdo7qrC6uEI5Fy/sELBgWl4O2opVY3Tf8s8OO/DSb4Cxy6solKgaETkl6EcShaEj7H/Cn7vT0+SLKCpSQlvVQXDLGg6eZTyBA+OWNElE0UvWV7znxWBlke+9NARIl4FcB/SY4A6v1ztpandHWMjNLLxZyVxFEswfU9hvf0qL9SW38OJ5cIK8pvmH2QWG7Xg/j0B3o7SHMdsM+pcSwrzsM6OENgvxPNBb/DinmMyQKxTCVcVmMo7uIS89RIylvN79E8U6NagdFkiLfa3xEHq8zCzEkHi3bsLRvytgT2X0=
|
||||
- secure: 1JL8KcgkLueQ2DLL81UMYzIHX3qm1TjcO40QL2ZOfdirFWBshOiTwTXeWj5qZaGBzoVV5ezhyZaBY+t3/pObslm20ERce879hEw+TSnKN30wfBqNyv2r7rfsbKkXauultb8RNu9y/9XS0DCEyGdSTQh9UaCa4z6ulu39hffDddrGQjwW1P2gT3Npu1cDYd1iSO36rrA6yXjaoN8OW8U4znKVjOGnarxxFnXJkiYv2PfIrZA6BpL3d0syJtWDyr1G+B48oK9VK+fBV9K0G0E67fJvqB3ANXN3D41il3S+cs8Ulcd7hF+LWxpMsP2r1/XHYSDw3Iiz0QFKKzoyxNdipvdjAVDxrWylyLnmTBYzXk41kRv88mKVLBQM1dbzsLXYcsE2pgIZxxq9OHGZ5CUJ8t0oz5D9oXMUy4QOMQ36jZdvD048aB7DGp4EF2J7ILIhUZrHHErOlXotnsYvNMvamNwqB5Jg4NC+y5QHxERJ+HK5oPrLy+iCb2kmWatSB6vO5OeX/F7IRiqtZghJRddEeMdQ1a6H0GeV1BF7Hx8j3TPMJ66qSAb0RA1lQQCN4l+/YMEWmQD8amf1O5NY116waf+Co4qkvt3c4QctQOMwu3Ra7uLlp6GG61OmHhPTCGSv/LZp6CVtROLY5IltKv7qBzksjvXkO1SzhJOxi0JkZmg=
|
||||
branches:
|
||||
except:
|
||||
- assets
|
||||
deploy:
|
||||
skip_cleanup: true
|
||||
provider: releases
|
||||
api_key:
|
||||
secure: rwlge/Rs3wnWyfKRhD9fd5GviVe0foYUp20DY3AjKdDjhtwScA1EeR9QHOkB3raze52en0+KkpqlLCWbt3q4CRT7+ku1DNKhd6VWALdTZ1RPJYvNlU6CKJdRnWUJsECmSBsShXlbiYR8axqNVedzFPFGKzS9gYlFN6rr7pez/JZhxqucopZ6I+TkRHMELrFXyQK7/Y2bNRCLC4a+rGsjKeLLtYXbRXCmS0G4BSJEBRk7d69fIRzBApCMfrcLftgHzPuPth616yyUusQSCQYvaZ5tlwrPP8/E0wG3SVJVeDCMuDOSBZ9M6vNzR8W8VR/hxQamegn1OQgC5kNOaLZCTcJ5xguRouqb+FNFBqrd/Zi6vESo7RiVLULawzwxkh9sIPa3WZYDb3VK/Z/cpggUeR7wAu0S5ZYEvJHRefIZpqofZEHzDE3Blqp5yErz05e/zmjpd6HHK3f/UHmRRYfbulkvGT3aL/dlq5GcFvuxVC/vTL2VPvg9cGbqtf7PakC5IhoHpDs35tOyLxifOBLHvkwtGSxEfsCohIG8Hz2XFD83EsxgOiKSXVPLNd6yxjdqZj7OeAKFFU3bzGndnRbDIXaf987IN1imgUtP6wegfImoRStqxN4gEwwIMFsZCF86Ug4eLhlajLbWhudriDxDPBM/F9950aVxLwmWh9l5cRI=
|
||||
file_glob: true
|
||||
file: release/*
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
repo: wrouesnel/postgres_exporter
|
20
Dockerfile
20
Dockerfile
@ -1,12 +1,12 @@
|
||||
FROM debian:10-slim
|
||||
RUN useradd -u 20001 postgres_exporter
|
||||
ARG ARCH="amd64"
|
||||
ARG OS="linux"
|
||||
FROM quay.io/prometheus/busybox-${OS}-${ARCH}:latest
|
||||
LABEL maintainer="The Prometheus Authors <prometheus-developers@googlegroups.com>"
|
||||
|
||||
USER postgres_exporter
|
||||
ARG ARCH="amd64"
|
||||
ARG OS="linux"
|
||||
COPY .build/${OS}-${ARCH}/postgres_exporter /bin/postgres_exporter
|
||||
|
||||
ARG binary
|
||||
|
||||
COPY $binary /postgres_exporter
|
||||
|
||||
EXPOSE 9187
|
||||
|
||||
ENTRYPOINT [ "/postgres_exporter" ]
|
||||
EXPOSE 9187
|
||||
USER nobody
|
||||
ENTRYPOINT [ "/bin/postgres_exporter" ]
|
||||
|
10
Makefile
Normal file
10
Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
# Ensure that 'all' is the default target otherwise it will be the first target from Makefile.common.
|
||||
all::
|
||||
|
||||
# Needs to be defined before including Makefile.common to auto-generate targets
|
||||
DOCKER_ARCHS ?= amd64 armv7 arm64 ppc64le
|
||||
DOCKER_REPO ?= prometheuscommunity
|
||||
|
||||
include Makefile.common
|
||||
|
||||
DOCKER_IMAGE_NAME ?= postgres-exporter
|
@ -69,12 +69,21 @@ else
|
||||
GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)
|
||||
endif
|
||||
|
||||
PROMU_VERSION ?= 0.4.0
|
||||
GOTEST := $(GO) test
|
||||
GOTEST_DIR :=
|
||||
ifneq ($(CIRCLE_JOB),)
|
||||
ifneq ($(shell which gotestsum),)
|
||||
GOTEST_DIR := test-results
|
||||
GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml --
|
||||
endif
|
||||
endif
|
||||
|
||||
PROMU_VERSION ?= 0.7.0
|
||||
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
|
||||
|
||||
GOLANGCI_LINT :=
|
||||
GOLANGCI_LINT_OPTS ?=
|
||||
GOLANGCI_LINT_VERSION ?= v1.16.0
|
||||
GOLANGCI_LINT_VERSION ?= v1.36.0
|
||||
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64.
|
||||
# windows isn't included here because of the path separator being different.
|
||||
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
|
||||
@ -86,6 +95,8 @@ endif
|
||||
PREFIX ?= $(shell pwd)
|
||||
BIN_DIR ?= $(shell pwd)
|
||||
DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD))
|
||||
DOCKERFILE_PATH ?= ./Dockerfile
|
||||
DOCKERBUILD_CONTEXT ?= ./
|
||||
DOCKER_REPO ?= prom
|
||||
|
||||
DOCKER_ARCHS ?= amd64
|
||||
@ -139,15 +150,29 @@ else
|
||||
$(GO) get $(GOOPTS) -t ./...
|
||||
endif
|
||||
|
||||
.PHONY: update-go-deps
|
||||
update-go-deps:
|
||||
@echo ">> updating Go dependencies"
|
||||
@for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \
|
||||
$(GO) get $$m; \
|
||||
done
|
||||
GO111MODULE=$(GO111MODULE) $(GO) mod tidy
|
||||
ifneq (,$(wildcard vendor))
|
||||
GO111MODULE=$(GO111MODULE) $(GO) mod vendor
|
||||
endif
|
||||
|
||||
.PHONY: common-test-short
|
||||
common-test-short:
|
||||
common-test-short: $(GOTEST_DIR)
|
||||
@echo ">> running short tests"
|
||||
GO111MODULE=$(GO111MODULE) $(GO) test -short $(GOOPTS) $(pkgs)
|
||||
GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs)
|
||||
|
||||
.PHONY: common-test
|
||||
common-test:
|
||||
common-test: $(GOTEST_DIR)
|
||||
@echo ">> running all tests"
|
||||
GO111MODULE=$(GO111MODULE) $(GO) test $(test-flags) $(GOOPTS) $(pkgs)
|
||||
GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs)
|
||||
|
||||
$(GOTEST_DIR):
|
||||
@mkdir -p $@
|
||||
|
||||
.PHONY: common-format
|
||||
common-format:
|
||||
@ -199,7 +224,7 @@ endif
|
||||
.PHONY: common-build
|
||||
common-build: promu
|
||||
@echo ">> building binaries"
|
||||
GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX)
|
||||
GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES)
|
||||
|
||||
.PHONY: common-tarball
|
||||
common-tarball: promu
|
||||
@ -210,19 +235,22 @@ common-tarball: promu
|
||||
common-docker: $(BUILD_DOCKER_ARCHS)
|
||||
$(BUILD_DOCKER_ARCHS): common-docker-%:
|
||||
docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \
|
||||
-f $(DOCKERFILE_PATH) \
|
||||
--build-arg ARCH="$*" \
|
||||
--build-arg OS="linux" \
|
||||
.
|
||||
$(DOCKERBUILD_CONTEXT)
|
||||
|
||||
.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
|
||||
common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
|
||||
$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
|
||||
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)"
|
||||
|
||||
DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION)))
|
||||
.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS)
|
||||
common-docker-tag-latest: $(TAG_DOCKER_ARCHS)
|
||||
$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
|
||||
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"
|
||||
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"
|
||||
|
||||
.PHONY: common-docker-manifest
|
||||
common-docker-manifest:
|
||||
@ -247,7 +275,9 @@ proto:
|
||||
ifdef GOLANGCI_LINT
|
||||
$(GOLANGCI_LINT):
|
||||
mkdir -p $(FIRST_GOPATH)/bin
|
||||
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION)
|
||||
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_LINT_VERSION)/install.sh \
|
||||
| sed -e '/install -d/d' \
|
||||
| sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION)
|
||||
endif
|
||||
|
||||
ifdef GOVENDOR
|
@ -3,7 +3,7 @@
|
||||
### When using postgres-exporter with Amazon Web Services' RDS, the
|
||||
rolname "rdsadmin" and datname "rdsadmin" must be excluded.
|
||||
|
||||
I had success running docker container 'wrouesnel/postgres_exporter:latest'
|
||||
I had success running docker container 'quay.io/prometheuscommunity/postgres-exporter:latest'
|
||||
with queries.yaml as the PG_EXPORTER_EXTEND_QUERY_PATH. errors
|
||||
mentioned in issue#335 appeared and I had to modify the
|
||||
'pg_stat_statements' query with the following:
|
||||
@ -24,7 +24,7 @@ Running postgres-exporter in a container like so:
|
||||
-e PG_EXPORTER_DISABLE_DEFAULT_METRICS=true \
|
||||
-e PG_EXPORTER_DISABLE_SETTINGS_METRICS=true \
|
||||
-e PG_EXPORTER_EXTEND_QUERY_PATH='/var/lib/postgresql/queries.yaml' \
|
||||
wrouesnel/postgres_exporter
|
||||
quay.io/prometheuscommunity/postgres-exporter
|
||||
```
|
||||
|
||||
### Expected changes to RDS:
|
||||
|
46
README.md
46
README.md
@ -1,7 +1,7 @@
|
||||
[](https://travis-ci.org/wrouesnel/postgres_exporter)
|
||||
[](https://coveralls.io/github/wrouesnel/postgres_exporter?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/wrouesnel/postgres_exporter)
|
||||
[](https://hub.docker.com/r/wrouesnel/postgres_exporter/tags)
|
||||
[](https://circleci.com/gh/prometheus-community/postgres_exporter)
|
||||
[](https://coveralls.io/github/prometheus-community/postgres_exporter?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/prometheus-community/postgres_exporter)
|
||||
[](https://hub.docker.com/r/prometheuscommunity/postgres-exporter/tags)
|
||||
|
||||
# PostgreSQL Server Exporter
|
||||
|
||||
@ -15,31 +15,30 @@ This package is available for Docker:
|
||||
# Start an example database
|
||||
docker run --net=host -it --rm -e POSTGRES_PASSWORD=password postgres
|
||||
# Connect to it
|
||||
docker run --net=host -e DATA_SOURCE_NAME="postgresql://postgres:password@localhost:5432/postgres?sslmode=disable" wrouesnel/postgres_exporter
|
||||
docker run \
|
||||
--net=host \
|
||||
-e DATA_SOURCE_NAME="postgresql://postgres:password@localhost:5432/postgres?sslmode=disable" \
|
||||
quay.io/prometheuscommunity/postgres-exporter
|
||||
```
|
||||
|
||||
## Building and running
|
||||
|
||||
The build system is based on [Mage](https://magefile.org)
|
||||
git clone https://github.com/prometheus-community/postgres_exporter.git
|
||||
cd postgres_exporter
|
||||
make build
|
||||
./postgres_exporter <flags>
|
||||
|
||||
The default make file behavior is to build the binary:
|
||||
```
|
||||
$ go get github.com/wrouesnel/postgres_exporter
|
||||
$ cd ${GOPATH-$HOME/go}/src/github.com/wrouesnel/postgres_exporter
|
||||
$ go run mage.go binary
|
||||
$ export DATA_SOURCE_NAME="postgresql://login:password@hostname:port/dbname"
|
||||
$ ./postgres_exporter <flags>
|
||||
```
|
||||
To build the Docker image:
|
||||
|
||||
To build the dockerfile, run `go run mage.go docker`.
|
||||
make promu
|
||||
promu crossbuild -p linux/amd64 -p linux/armv7 -p linux/amd64 -p linux/ppc64le
|
||||
make docker
|
||||
|
||||
This will build the docker image as `wrouesnel/postgres_exporter:latest`. This
|
||||
is a minimal docker image containing *just* postgres_exporter. By default no SSL
|
||||
certificates are included, if you need to use SSL you should either bind-mount
|
||||
`/etc/ssl/certs/ca-certificates.crt` or derive a new image containing them.
|
||||
This will build the docker image as `prometheuscommunity/postgres_exporter:${branch}`.
|
||||
|
||||
### Vendoring
|
||||
Package vendoring is handled with [`govendor`](https://github.com/kardianos/govendor)
|
||||
|
||||
Package vendoring is handled with Go modules.
|
||||
|
||||
### Flags
|
||||
|
||||
@ -277,10 +276,3 @@ GRANT SELECT ON postgres_exporter.pg_stat_statements TO postgres_exporter;
|
||||
> ```
|
||||
> DATA_SOURCE_NAME=postgresql://postgres_exporter:password@localhost:5432/postgres?sslmode=disable
|
||||
> ```
|
||||
|
||||
# Hacking
|
||||
* To build a copy for your current architecture run `go run mage.go binary`.
|
||||
This will create a symlink to the just built binary in the root directory.
|
||||
* To build release tar balls run `go run mage.go release`.
|
||||
* Build system is a bit temperamental at the moment since the conversion to mage - I am working on getting it
|
||||
to be a perfect out of the box experience, but am time-constrained on it at the moment.
|
||||
|
@ -1,3 +1,16 @@
|
||||
// Copyright 2021 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
@ -1,3 +1,16 @@
|
||||
// Copyright 2021 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !integration
|
||||
|
||||
package main
|
||||
|
@ -1,3 +1,16 @@
|
||||
// Copyright 2021 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -1260,7 +1273,7 @@ func newDesc(subsystem, name, help string, labels prometheus.Labels) *prometheus
|
||||
}
|
||||
|
||||
func queryDatabases(server *Server) ([]string, error) {
|
||||
rows, err := server.db.Query("SELECT datname FROM pg_database WHERE datallowconn = true AND datistemplate = false AND datname != current_database()") // nolint: safesql
|
||||
rows, err := server.db.Query("SELECT datname FROM pg_database WHERE datallowconn = true AND datistemplate = false AND datname != current_database()")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error retrieving databases: %v", err)
|
||||
}
|
||||
@ -1299,9 +1312,9 @@ func queryNamespaceMapping(server *Server, namespace string, mapping MetricMapNa
|
||||
if !found {
|
||||
// I've no idea how to avoid this properly at the moment, but this is
|
||||
// an admin tool so you're not injecting SQL right?
|
||||
rows, err = server.db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) // nolint: gas, safesql
|
||||
rows, err = server.db.Query(fmt.Sprintf("SELECT * FROM %s;", namespace)) // nolint: gas
|
||||
} else {
|
||||
rows, err = server.db.Query(query) // nolint: safesql
|
||||
rows, err = server.db.Query(query)
|
||||
}
|
||||
if err != nil {
|
||||
return []prometheus.Metric{}, []error{}, fmt.Errorf("Error running query on database %q: %s %v", server, namespace, err)
|
||||
|
@ -1,3 +1,16 @@
|
||||
// Copyright 2021 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// These are specialized integration tests. We only build them when we're doing
|
||||
// a lot of additional work to keep the external docker environment they require
|
||||
// working.
|
||||
@ -75,7 +88,7 @@ func (s *IntegrationSuite) TestAllNamespacesReturnResults(c *C) {
|
||||
}
|
||||
|
||||
// TestInvalidDsnDoesntCrash tests that specifying an invalid DSN doesn't crash
|
||||
// the exporter. Related to https://github.com/wrouesnel/postgres_exporter/issues/93
|
||||
// the exporter. Related to https://github.com/prometheus-community/postgres_exporter/issues/93
|
||||
// although not a replication of the scenario.
|
||||
func (s *IntegrationSuite) TestInvalidDsnDoesntCrash(c *C) {
|
||||
// Setup a dummy channel to consume metrics
|
||||
|
@ -1,3 +1,16 @@
|
||||
// Copyright 2021 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build !integration
|
||||
|
||||
package main
|
||||
|
14
go.mod
Normal file
14
go.mod
Normal file
@ -0,0 +1,14 @@
|
||||
module github.com/prometheus-community/postgres_exporter
|
||||
|
||||
go 1.14
|
||||
|
||||
require (
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/lib/pq v1.9.0
|
||||
github.com/prometheus/client_golang v1.9.0
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/prometheus/common v0.17.0
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
432
go.sum
Normal file
432
go.sum
Normal file
@ -0,0 +1,432 @@
|
||||
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=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
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 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.9.0 h1:Rrch9mh17XcxvEu9D9DEpb4isxjGBtcevQjKvxPRQIU=
|
||||
github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0 h1:L+1lyG48J1zAQXA3RBX/nG/B3gjlHq0zTt2tlbJLyCY=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.17.0 h1:kDIZLI74SS+3tedSvEkykgBkD7txMxaJAPj8DtJUKYA=
|
||||
github.com/prometheus/common v0.17.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
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-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
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/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/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
|
||||
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/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-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
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.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
11
mage.go
11
mage.go
@ -1,11 +0,0 @@
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/magefile/mage/mage"
|
||||
)
|
||||
|
||||
func main() { os.Exit(mage.Main()) }
|
788
magefile.go
788
magefile.go
@ -1,788 +0,0 @@
|
||||
// +build mage
|
||||
// Self-contained go-project magefile.
|
||||
|
||||
// nolint: deadcode
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/magefile/mage/mg"
|
||||
"github.com/magefile/mage/sh"
|
||||
"github.com/magefile/mage/target"
|
||||
|
||||
"errors"
|
||||
"math/bits"
|
||||
"strconv"
|
||||
|
||||
"github.com/mholt/archiver"
|
||||
)
|
||||
|
||||
var curDir = func() string {
|
||||
name, _ := os.Getwd()
|
||||
return name
|
||||
}()
|
||||
|
||||
const constCoverageDir = ".coverage"
|
||||
const constToolDir = "tools"
|
||||
const constBinDir = "bin"
|
||||
const constReleaseDir = "release"
|
||||
const constCmdDir = "cmd"
|
||||
const constCoverFile = "cover.out"
|
||||
const constAssets = "assets"
|
||||
const constAssetsGenerated = "assets/generated"
|
||||
|
||||
var coverageDir = mustStr(filepath.Abs(path.Join(curDir, constCoverageDir)))
|
||||
var toolDir = mustStr(filepath.Abs(path.Join(curDir, constToolDir)))
|
||||
var binDir = mustStr(filepath.Abs(path.Join(curDir, constBinDir)))
|
||||
var releaseDir = mustStr(filepath.Abs(path.Join(curDir, constReleaseDir)))
|
||||
var cmdDir = mustStr(filepath.Abs(path.Join(curDir, constCmdDir)))
|
||||
var assetsGenerated = mustStr(filepath.Abs(path.Join(curDir, constAssetsGenerated)))
|
||||
|
||||
// Calculate file paths
|
||||
var toolsGoPath = toolDir
|
||||
var toolsSrcDir = mustStr(filepath.Abs(path.Join(toolDir, "src")))
|
||||
var toolsBinDir = mustStr(filepath.Abs(path.Join(toolDir, "bin")))
|
||||
var toolsVendorDir = mustStr(filepath.Abs(path.Join(toolDir, "vendor")))
|
||||
|
||||
var outputDirs = []string{binDir, releaseDir, toolsGoPath, toolsBinDir,
|
||||
toolsVendorDir, assetsGenerated, coverageDir}
|
||||
|
||||
var toolsEnv = map[string]string{"GOPATH": toolsGoPath}
|
||||
|
||||
var containerName = func() string {
|
||||
if name := os.Getenv("CONTAINER_NAME"); name != "" {
|
||||
return name
|
||||
}
|
||||
return "wrouesnel/postgres_exporter:latest"
|
||||
}()
|
||||
|
||||
type Platform struct {
|
||||
OS string
|
||||
Arch string
|
||||
BinSuffix string
|
||||
}
|
||||
|
||||
func (p *Platform) String() string {
|
||||
return fmt.Sprintf("%s-%s", p.OS, p.Arch)
|
||||
}
|
||||
|
||||
func (p *Platform) PlatformDir() string {
|
||||
platformDir := path.Join(binDir, fmt.Sprintf("%s_%s_%s", productName, versionShort, p.String()))
|
||||
return platformDir
|
||||
}
|
||||
|
||||
func (p *Platform) PlatformBin(cmd string) string {
|
||||
platformBin := fmt.Sprintf("%s%s", cmd, p.BinSuffix)
|
||||
return path.Join(p.PlatformDir(), platformBin)
|
||||
}
|
||||
|
||||
func (p *Platform) ArchiveDir() string {
|
||||
return fmt.Sprintf("%s_%s_%s", productName, versionShort, p.String())
|
||||
}
|
||||
|
||||
func (p *Platform) ReleaseBase() string {
|
||||
return path.Join(releaseDir, fmt.Sprintf("%s_%s_%s", productName, versionShort, p.String()))
|
||||
}
|
||||
|
||||
// Supported platforms
|
||||
var platforms []Platform = []Platform{
|
||||
{"linux", "amd64", ""},
|
||||
{"linux", "386", ""},
|
||||
{"linux", "arm64", ""},
|
||||
{"linux", "mips64le", ""},
|
||||
{"darwin", "amd64", ""},
|
||||
{"darwin", "386", ""},
|
||||
{"windows", "amd64", ".exe"},
|
||||
{"windows", "386", ".exe"},
|
||||
{"freebsd", "amd64", ""},
|
||||
}
|
||||
|
||||
// productName can be overridden by environ product name
|
||||
var productName = func() string {
|
||||
if name := os.Getenv("PRODUCT_NAME"); name != "" {
|
||||
return name
|
||||
}
|
||||
name, _ := os.Getwd()
|
||||
return path.Base(name)
|
||||
}()
|
||||
|
||||
// Source files
|
||||
var goSrc []string
|
||||
var goDirs []string
|
||||
var goPkgs []string
|
||||
var goCmds []string
|
||||
|
||||
var branch = func() string {
|
||||
if v := os.Getenv("BRANCH"); v != "" {
|
||||
return v
|
||||
}
|
||||
out, _ := sh.Output("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
|
||||
return out
|
||||
}()
|
||||
|
||||
var buildDate = func() string {
|
||||
if v := os.Getenv("BUILDDATE"); v != "" {
|
||||
return v
|
||||
}
|
||||
return time.Now().Format("2006-01-02T15:04:05-0700")
|
||||
}()
|
||||
|
||||
var revision = func() string {
|
||||
if v := os.Getenv("REVISION"); v != "" {
|
||||
return v
|
||||
}
|
||||
out, _ := sh.Output("git", "rev-parse", "HEAD")
|
||||
|
||||
return out
|
||||
}()
|
||||
|
||||
var version = func() string {
|
||||
if v := os.Getenv("VERSION"); v != "" {
|
||||
return v
|
||||
}
|
||||
out, _ := sh.Output("git", "describe", "--dirty")
|
||||
|
||||
if out == "" {
|
||||
return "v0.0.0"
|
||||
}
|
||||
|
||||
return out
|
||||
}()
|
||||
|
||||
var versionShort = func() string {
|
||||
if v := os.Getenv("VERSION_SHORT"); v != "" {
|
||||
return v
|
||||
}
|
||||
out, _ := sh.Output("git", "describe", "--abbrev=0")
|
||||
|
||||
if out == "" {
|
||||
return "v0.0.0"
|
||||
}
|
||||
|
||||
return out
|
||||
}()
|
||||
|
||||
var concurrency = func() int {
|
||||
if v := os.Getenv("CONCURRENCY"); v != "" {
|
||||
pv, err := strconv.ParseUint(v, 10, bits.UintSize)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return int(pv)
|
||||
}
|
||||
return runtime.NumCPU()
|
||||
}()
|
||||
|
||||
var linterDeadline = func() time.Duration {
|
||||
if v := os.Getenv("LINTER_DEADLINE"); v != "" {
|
||||
d, _ := time.ParseDuration(v)
|
||||
if d != 0 {
|
||||
return d
|
||||
}
|
||||
}
|
||||
return time.Second * 60
|
||||
}()
|
||||
|
||||
func Log(args ...interface{}) {
|
||||
if mg.Verbose() {
|
||||
fmt.Println(args...)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Set environment
|
||||
os.Setenv("PATH", fmt.Sprintf("%s:%s", toolsBinDir, os.Getenv("PATH")))
|
||||
Log("Build PATH: ", os.Getenv("PATH"))
|
||||
Log("Concurrency:", concurrency)
|
||||
goSrc = func() []string {
|
||||
results := new([]string)
|
||||
filepath.Walk(".", func(relpath string, info os.FileInfo, err error) error {
|
||||
// Ensure absolute path so globs work
|
||||
path, err := filepath.Abs(relpath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Look for files
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Exclusions
|
||||
for _, exclusion := range []string{toolDir, binDir, releaseDir, coverageDir} {
|
||||
if strings.HasPrefix(path, exclusion) {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if strings.Contains(path, "/vendor/") {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.Contains(path, ".git") {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(path, ".go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
*results = append(*results, path)
|
||||
return nil
|
||||
})
|
||||
return *results
|
||||
}()
|
||||
goDirs = func() []string {
|
||||
resultMap := make(map[string]struct{})
|
||||
for _, path := range goSrc {
|
||||
absDir, err := filepath.Abs(filepath.Dir(path))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
resultMap[absDir] = struct{}{}
|
||||
}
|
||||
results := []string{}
|
||||
for k := range resultMap {
|
||||
results = append(results, k)
|
||||
}
|
||||
return results
|
||||
}()
|
||||
goPkgs = func() []string {
|
||||
results := []string{}
|
||||
out, err := sh.Output("go", "list", "./...")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, line := range strings.Split(out, "\n") {
|
||||
if !strings.Contains(line, "/vendor/") {
|
||||
results = append(results, line)
|
||||
}
|
||||
}
|
||||
return results
|
||||
}()
|
||||
goCmds = func() []string {
|
||||
results := []string{}
|
||||
|
||||
finfos, err := ioutil.ReadDir(cmdDir)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, finfo := range finfos {
|
||||
results = append(results, finfo.Name())
|
||||
}
|
||||
return results
|
||||
}()
|
||||
|
||||
// Ensure output dirs exist
|
||||
for _, dir := range outputDirs {
|
||||
os.MkdirAll(dir, os.FileMode(0777))
|
||||
}
|
||||
}
|
||||
|
||||
func mustStr(r string, err error) string {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func getCoreTools() []string {
|
||||
staticTools := []string{
|
||||
"github.com/kardianos/govendor",
|
||||
"github.com/wadey/gocovmerge",
|
||||
"github.com/mattn/goveralls",
|
||||
"github.com/tmthrgd/go-bindata/go-bindata",
|
||||
"github.com/GoASTScanner/gas/cmd/gas", // workaround for Ast scanner
|
||||
"github.com/alecthomas/gometalinter",
|
||||
}
|
||||
return staticTools
|
||||
}
|
||||
|
||||
func getMetalinters() []string {
|
||||
// Gometalinter should now be on the command line
|
||||
dynamicTools := []string{}
|
||||
|
||||
goMetalinterHelp, _ := sh.Output("gometalinter", "--help")
|
||||
linterRx := regexp.MustCompile(`\s+\w+:\s*\((.+)\)`)
|
||||
for _, l := range strings.Split(goMetalinterHelp, "\n") {
|
||||
linter := linterRx.FindStringSubmatch(l)
|
||||
if len(linter) > 1 {
|
||||
dynamicTools = append(dynamicTools, linter[1])
|
||||
}
|
||||
}
|
||||
return dynamicTools
|
||||
}
|
||||
|
||||
func ensureVendorSrcLink() error {
|
||||
Log("Symlink vendor to tools dir")
|
||||
if err := sh.Rm(toolsSrcDir); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Symlink(toolsVendorDir, toolsSrcDir); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// concurrencyLimitedBuild executes a certain number of commands limited by concurrency
|
||||
func concurrencyLimitedBuild(buildCmds ...interface{}) error {
|
||||
resultsCh := make(chan error, len(buildCmds))
|
||||
concurrencyControl := make(chan struct{}, concurrency)
|
||||
for _, buildCmd := range buildCmds {
|
||||
go func(buildCmd interface{}) {
|
||||
concurrencyControl <- struct{}{}
|
||||
resultsCh <- buildCmd.(func() error)()
|
||||
<-concurrencyControl
|
||||
|
||||
}(buildCmd)
|
||||
}
|
||||
// Doesn't work at the moment
|
||||
// mg.Deps(buildCmds...)
|
||||
results := []error{}
|
||||
var resultErr error = nil
|
||||
for len(results) < len(buildCmds) {
|
||||
err := <-resultsCh
|
||||
results = append(results, err)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
resultErr = errors.New("parallel build failed")
|
||||
}
|
||||
fmt.Printf("Finished %v of %v\n", len(results), len(buildCmds))
|
||||
}
|
||||
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// Tools builds build tools of the project and is depended on by all other build targets.
|
||||
func Tools() (err error) {
|
||||
// Catch panics and convert to errors
|
||||
defer func() {
|
||||
if perr := recover(); perr != nil {
|
||||
err = perr.(error)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := ensureVendorSrcLink(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toolBuild := func(toolType string, tools ...string) error {
|
||||
toolTargets := []interface{}{}
|
||||
for _, toolImport := range tools {
|
||||
toolParts := strings.Split(toolImport, "/")
|
||||
toolBin := path.Join(toolsBinDir, toolParts[len(toolParts)-1])
|
||||
Log("Check for changes:", toolBin, toolsVendorDir)
|
||||
changed, terr := target.Dir(toolBin, toolsVendorDir)
|
||||
if terr != nil {
|
||||
if !os.IsNotExist(terr) {
|
||||
panic(terr)
|
||||
}
|
||||
changed = true
|
||||
}
|
||||
if changed {
|
||||
localToolImport := toolImport
|
||||
f := func() error { return sh.RunWith(toolsEnv, "go", "install", "-v", localToolImport) }
|
||||
toolTargets = append(toolTargets, f)
|
||||
}
|
||||
}
|
||||
|
||||
Log("Build", toolType, "tools")
|
||||
if berr := concurrencyLimitedBuild(toolTargets...); berr != nil {
|
||||
return berr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if berr := toolBuild("static", getCoreTools()...); berr != nil {
|
||||
return berr
|
||||
}
|
||||
|
||||
if berr := toolBuild("static", getMetalinters()...); berr != nil {
|
||||
return berr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateTools automatically updates tool dependencies to the latest version.
|
||||
func UpdateTools() error {
|
||||
if err := ensureVendorSrcLink(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure govendor is up to date without doing anything
|
||||
govendorPkg := "github.com/kardianos/govendor"
|
||||
govendorParts := strings.Split(govendorPkg, "/")
|
||||
govendorBin := path.Join(toolsBinDir, govendorParts[len(govendorParts)-1])
|
||||
|
||||
sh.RunWith(toolsEnv, "go", "get", "-v", "-u", govendorPkg)
|
||||
|
||||
if changed, cerr := target.Dir(govendorBin, toolsSrcDir); changed || os.IsNotExist(cerr) {
|
||||
if err := sh.RunWith(toolsEnv, "go", "install", "-v", govendorPkg); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if cerr != nil {
|
||||
panic(cerr)
|
||||
}
|
||||
|
||||
// Set current directory so govendor has the right path
|
||||
previousPwd, wderr := os.Getwd()
|
||||
if wderr != nil {
|
||||
return wderr
|
||||
}
|
||||
if err := os.Chdir(toolDir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// govendor fetch core tools
|
||||
for _, toolImport := range append(getCoreTools(), getMetalinters()...) {
|
||||
sh.RunV("govendor", "fetch", "-v", toolImport)
|
||||
}
|
||||
|
||||
// change back to original working directory
|
||||
if err := os.Chdir(previousPwd); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Assets builds binary assets to be bundled into the binary.
|
||||
func Assets() error {
|
||||
mg.Deps(Tools)
|
||||
|
||||
if err := os.MkdirAll("assets/generated", os.FileMode(0777)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sh.RunV("go-bindata", "-pkg=assets", "-o", "assets/bindata.go", "-ignore=bindata.go",
|
||||
"-ignore=.*.map$", "-prefix=assets/generated", "assets/generated/...")
|
||||
}
|
||||
|
||||
// Lint runs gometalinter for code quality. CI will run this before accepting PRs.
|
||||
func Lint() error {
|
||||
mg.Deps(Tools)
|
||||
args := []string{"-j", fmt.Sprintf("%v", concurrency), fmt.Sprintf("--deadline=%s",
|
||||
linterDeadline.String()), "--enable-all", "--line-length=120",
|
||||
"--disable=gocyclo", "--disable=testify", "--disable=test", "--disable=lll", "--exclude=assets/bindata.go"}
|
||||
return sh.RunV("gometalinter", append(args, goDirs...)...)
|
||||
}
|
||||
|
||||
// Style checks formatting of the file. CI will run this before acceptiing PRs.
|
||||
func Style() error {
|
||||
mg.Deps(Tools)
|
||||
args := []string{"--disable-all", "--enable=gofmt", "--enable=goimports"}
|
||||
return sh.RunV("gometalinter", append(args, goSrc...)...)
|
||||
}
|
||||
|
||||
// Fmt automatically formats all source code files
|
||||
func Fmt() error {
|
||||
mg.Deps(Tools)
|
||||
fmtErr := sh.RunV("gofmt", append([]string{"-s", "-w"}, goSrc...)...)
|
||||
if fmtErr != nil {
|
||||
return fmtErr
|
||||
}
|
||||
impErr := sh.RunV("goimports", append([]string{"-w"}, goSrc...)...)
|
||||
if impErr != nil {
|
||||
return fmtErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func listCoverageFiles() ([]string, error) {
|
||||
result := []string{}
|
||||
finfos, derr := ioutil.ReadDir(coverageDir)
|
||||
if derr != nil {
|
||||
return result, derr
|
||||
}
|
||||
for _, finfo := range finfos {
|
||||
result = append(result, path.Join(coverageDir, finfo.Name()))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Test run test suite
|
||||
func Test() error {
|
||||
mg.Deps(Tools)
|
||||
|
||||
// Ensure coverage directory exists
|
||||
if err := os.MkdirAll(coverageDir, os.FileMode(0777)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean up coverage directory
|
||||
coverFiles, derr := listCoverageFiles()
|
||||
if derr != nil {
|
||||
return derr
|
||||
}
|
||||
for _, coverFile := range coverFiles {
|
||||
if err := sh.Rm(coverFile); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Run tests
|
||||
coverProfiles := []string{}
|
||||
for _, pkg := range goPkgs {
|
||||
coverProfile := path.Join(coverageDir, fmt.Sprintf("%s%s", strings.Replace(pkg, "/", "-", -1), ".out"))
|
||||
testErr := sh.Run("go", "test", "-v", "-covermode", "count", fmt.Sprintf("-coverprofile=%s", coverProfile),
|
||||
pkg)
|
||||
if testErr != nil {
|
||||
return testErr
|
||||
}
|
||||
coverProfiles = append(coverProfiles, coverProfile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build the intgration test binary
|
||||
func IntegrationTestBinary() error {
|
||||
changed, err := target.Path("postgres_exporter_integration_test", goSrc...)
|
||||
if (changed && (err == nil)) || os.IsNotExist(err) {
|
||||
return sh.RunWith(map[string]string{"CGO_ENABLED": "0"}, "go", "test", "./cmd/postgres_exporter",
|
||||
"-c", "-tags", "integration",
|
||||
"-a", "-ldflags", "-extldflags '-static'",
|
||||
"-X", fmt.Sprintf("main.Branch=%s", branch),
|
||||
"-X", fmt.Sprintf("main.BuildDate=%s", buildDate),
|
||||
"-X", fmt.Sprintf("main.Revision=%s", revision),
|
||||
"-X", fmt.Sprintf("main.VersionShort=%s", versionShort),
|
||||
"-o", "postgres_exporter_integration_test", "-cover", "-covermode", "count")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// TestIntegration runs integration tests
|
||||
func TestIntegration() error {
|
||||
mg.Deps(Binary, IntegrationTestBinary)
|
||||
|
||||
exporterPath := mustStr(filepath.Abs("postgres_exporter"))
|
||||
testBinaryPath := mustStr(filepath.Abs("postgres_exporter_integration_test"))
|
||||
testScriptPath := mustStr(filepath.Abs("postgres_exporter_integration_test_script"))
|
||||
|
||||
integrationCoverageProfile := path.Join(coverageDir, "cover.integration.out")
|
||||
|
||||
return sh.RunV("cmd/postgres_exporter/tests/test-smoke", exporterPath,
|
||||
fmt.Sprintf("%s %s %s", testScriptPath, testBinaryPath, integrationCoverageProfile))
|
||||
}
|
||||
|
||||
// Coverage sums up the coverage profiles in .coverage. It does not clean up after itself or before.
|
||||
func Coverage() error {
|
||||
// Clean up coverage directory
|
||||
coverFiles, derr := listCoverageFiles()
|
||||
if derr != nil {
|
||||
return derr
|
||||
}
|
||||
|
||||
mergedCoverage, err := sh.Output("gocovmerge", coverFiles...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(constCoverFile, []byte(mergedCoverage), os.FileMode(0777))
|
||||
}
|
||||
|
||||
// All runs a full suite suitable for CI
|
||||
func All() error {
|
||||
mg.SerialDeps(Style, Lint, Test, TestIntegration, Coverage, Release)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Release builds release archives under the release/ directory
|
||||
func Release() error {
|
||||
mg.Deps(ReleaseBin)
|
||||
|
||||
for _, platform := range platforms {
|
||||
owd, wderr := os.Getwd()
|
||||
if wderr != nil {
|
||||
return wderr
|
||||
}
|
||||
os.Chdir(binDir)
|
||||
|
||||
if platform.OS == "windows" {
|
||||
// build a zip binary as well
|
||||
err := archiver.Zip.Make(fmt.Sprintf("%s.zip", platform.ReleaseBase()), []string{platform.ArchiveDir()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// build tar gz
|
||||
err := archiver.TarGz.Make(fmt.Sprintf("%s.tar.gz", platform.ReleaseBase()), []string{platform.ArchiveDir()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Chdir(owd)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeBuilder(cmd string, platform Platform) func() error {
|
||||
f := func() error {
|
||||
// Depend on assets
|
||||
mg.Deps(Assets)
|
||||
|
||||
cmdSrc := fmt.Sprintf("./%s/%s", mustStr(filepath.Rel(curDir, cmdDir)), cmd)
|
||||
|
||||
Log("Make platform binary directory:", platform.PlatformDir())
|
||||
if err := os.MkdirAll(platform.PlatformDir(), os.FileMode(0777)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Log("Checking for changes:", platform.PlatformBin(cmd))
|
||||
if changed, err := target.Path(platform.PlatformBin(cmd), goSrc...); !changed {
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Building", platform.PlatformBin(cmd))
|
||||
return sh.RunWith(map[string]string{"CGO_ENABLED": "0", "GOOS": platform.OS, "GOARCH": platform.Arch},
|
||||
"go", "build", "-a", "-ldflags", fmt.Sprintf("-extldflags '-static' -X main.Version=%s", version),
|
||||
"-o", platform.PlatformBin(cmd), cmdSrc)
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func getCurrentPlatform() *Platform {
|
||||
var curPlatform *Platform
|
||||
for _, p := range platforms {
|
||||
if p.OS == runtime.GOOS && p.Arch == runtime.GOARCH {
|
||||
storedP := p
|
||||
curPlatform = &storedP
|
||||
}
|
||||
}
|
||||
Log("Determined current platform:", curPlatform)
|
||||
return curPlatform
|
||||
}
|
||||
|
||||
// Binary build a binary for the current platform
|
||||
func Binary() error {
|
||||
curPlatform := getCurrentPlatform()
|
||||
if curPlatform == nil {
|
||||
return errors.New("current platform is not supported")
|
||||
}
|
||||
|
||||
for _, cmd := range goCmds {
|
||||
err := makeBuilder(cmd, *curPlatform)()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Make a root symlink to the build
|
||||
cmdPath := path.Join(curDir, cmd)
|
||||
os.Remove(cmdPath)
|
||||
if err := os.Symlink(curPlatform.PlatformBin(cmd), cmdPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReleaseBin builds cross-platform release binaries under the bin/ directory
|
||||
func ReleaseBin() error {
|
||||
buildCmds := []interface{}{}
|
||||
|
||||
for _, cmd := range goCmds {
|
||||
for _, platform := range platforms {
|
||||
buildCmds = append(buildCmds, makeBuilder(cmd, platform))
|
||||
}
|
||||
}
|
||||
|
||||
resultsCh := make(chan error, len(buildCmds))
|
||||
concurrencyControl := make(chan struct{}, concurrency)
|
||||
for _, buildCmd := range buildCmds {
|
||||
go func(buildCmd interface{}) {
|
||||
concurrencyControl <- struct{}{}
|
||||
resultsCh <- buildCmd.(func() error)()
|
||||
<-concurrencyControl
|
||||
|
||||
}(buildCmd)
|
||||
}
|
||||
// Doesn't work at the moment
|
||||
// mg.Deps(buildCmds...)
|
||||
results := []error{}
|
||||
var resultErr error = nil
|
||||
for len(results) < len(buildCmds) {
|
||||
err := <-resultsCh
|
||||
results = append(results, err)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
resultErr = errors.New("parallel build failed")
|
||||
}
|
||||
fmt.Printf("Finished %v of %v\n", len(results), len(buildCmds))
|
||||
}
|
||||
|
||||
return resultErr
|
||||
}
|
||||
|
||||
// Docker builds the docker image
|
||||
func Docker() error {
|
||||
mg.Deps(Binary)
|
||||
p := getCurrentPlatform()
|
||||
if p == nil {
|
||||
return errors.New("current platform is not supported")
|
||||
}
|
||||
|
||||
return sh.RunV("docker", "build",
|
||||
fmt.Sprintf("--build-arg=binary=%s",
|
||||
mustStr(filepath.Rel(curDir, p.PlatformBin("postgres_exporter")))),
|
||||
"-t", containerName, ".")
|
||||
}
|
||||
|
||||
// Clean deletes build output and cleans up the working directory
|
||||
func Clean() error {
|
||||
for _, name := range goCmds {
|
||||
if err := sh.Rm(path.Join(binDir, name)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range outputDirs {
|
||||
if err := sh.Rm(name); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Debug prints the value of internal state variables
|
||||
func Debug() error {
|
||||
fmt.Println("Source Files:", goSrc)
|
||||
fmt.Println("Packages:", goPkgs)
|
||||
fmt.Println("Directories:", goDirs)
|
||||
fmt.Println("Command Paths:", goCmds)
|
||||
fmt.Println("Output Dirs:", outputDirs)
|
||||
fmt.Println("Tool Src Dir:", toolsSrcDir)
|
||||
fmt.Println("Tool Vendor Dir:", toolsVendorDir)
|
||||
fmt.Println("Tool GOPATH:", toolsGoPath)
|
||||
fmt.Println("PATH:", os.Getenv("PATH"))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Autogen configure local git repository with commit hooks
|
||||
func Autogen() error {
|
||||
fmt.Println("Installing git hooks in local repository...")
|
||||
return os.Link(path.Join(curDir, toolDir, "pre-commit"), ".git/hooks/pre-commit")
|
||||
}
|
0
scripts/errcheck_excludes.txt
Normal file
0
scripts/errcheck_excludes.txt
Normal file
4
tools/.gitignore
vendored
4
tools/.gitignore
vendored
@ -1,4 +0,0 @@
|
||||
/pkg
|
||||
/bin
|
||||
/tools.deps
|
||||
/metatools.deps
|
@ -1,9 +0,0 @@
|
||||
|
||||
Vendored versions of the build tooling.
|
||||
|
||||
gocovmerge is used to merge coverage reports for uploading to a service like
|
||||
coveralls, and gometalinter conveniently incorporates multiple Go linters.
|
||||
|
||||
By vendoring both, we gain a self-contained build system.
|
||||
|
||||
Run `make all` to build, and `make update` to update.
|
7
tools/vendor/github.com/Bowery/prompt/CONTRIBUTORS.md
generated
vendored
7
tools/vendor/github.com/Bowery/prompt/CONTRIBUTORS.md
generated
vendored
@ -1,7 +0,0 @@
|
||||
- [Larz Conwell](https://github.com/larzconwell)
|
||||
- [Steve Kaliski](https://github.com/sjkaliski)
|
||||
- [NHOrus](https://github.com/NHOrus)
|
||||
- [Attila Fülöp](https://github.com/AttilaFueloep)
|
||||
- [Gereon Frey](https://github.com/gfrey)
|
||||
- [Aaron Bieber](https://github.com/qbit)
|
||||
- [Ricky Medina](https://github.com/r-medina)
|
21
tools/vendor/github.com/Bowery/prompt/LICENSE
generated
vendored
21
tools/vendor/github.com/Bowery/prompt/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Bowery, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
38
tools/vendor/github.com/Bowery/prompt/README.md
generated
vendored
38
tools/vendor/github.com/Bowery/prompt/README.md
generated
vendored
@ -1,38 +0,0 @@
|
||||
# Prompt
|
||||
|
||||
[](https://circleci.com/gh/Bowery/prompt/tree/master)
|
||||
|
||||
[](https://godoc.org/github.com/Bowery/prompt)
|
||||
|
||||
Prompt is a cross platform line-editing prompting library. Read the GoDoc page
|
||||
for more info and for API details.
|
||||
|
||||
## Features
|
||||
- Keyboard shortcuts in prompts
|
||||
- History support
|
||||
- Secure password prompt
|
||||
- Custom prompt support
|
||||
- Fallback prompt for unsupported terminals
|
||||
- ANSI conversion for Windows
|
||||
|
||||
## Todo
|
||||
- Multi-line prompt as a Terminal option
|
||||
- Make refresh less jittery on Windows([possible reason](https://github.com/Bowery/prompt/blob/master/output_windows.go#L108))
|
||||
- Multi-byte character support on Windows
|
||||
- `AnsiWriter` should execute the equivalent ANSI escape code functionality on Windows
|
||||
- Support for more ANSI escape codes on Windows.
|
||||
- More keyboard shortcuts from Readlines shortcut list
|
||||
|
||||
## Contributing
|
||||
|
||||
Make sure Go is setup and running the latest release version, and make sure your `GOPATH` is setup properly.
|
||||
|
||||
Follow the guidelines [here](https://guides.github.com/activities/contributing-to-open-source/#contributing).
|
||||
|
||||
Please be sure to `gofmt` any code before doing commits. You can simply run `gofmt -w .` to format all the code in the directory.
|
||||
|
||||
Lastly don't forget to add your name to [`CONTRIBUTORS.md`](https://github.com/Bowery/prompt/blob/master/CONTRIBUTORS.md)
|
||||
|
||||
## License
|
||||
|
||||
Prompt is MIT licensed, details can be found [here](https://raw.githubusercontent.com/Bowery/prompt/master/LICENSE).
|
39
tools/vendor/github.com/Bowery/prompt/ansi_unix.go
generated
vendored
39
tools/vendor/github.com/Bowery/prompt/ansi_unix.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// AnsiReader is an io.Reader that wraps an *os.File.
|
||||
type AnsiReader struct {
|
||||
file *os.File
|
||||
}
|
||||
|
||||
// NewAnsiReader creates a AnsiReader from the given input file.
|
||||
func NewAnsiReader(in *os.File) *AnsiReader {
|
||||
return &AnsiReader{file: in}
|
||||
}
|
||||
|
||||
// Read reads data from the input file into b.
|
||||
func (ar *AnsiReader) Read(b []byte) (int, error) {
|
||||
return ar.file.Read(b)
|
||||
}
|
||||
|
||||
// AnsiWriter is an io.Writer that wraps an *os.File.
|
||||
type AnsiWriter struct {
|
||||
file *os.File
|
||||
}
|
||||
|
||||
// NewAnsiWriter creates a AnsiWriter from the given output file.
|
||||
func NewAnsiWriter(out *os.File) *AnsiWriter {
|
||||
return &AnsiWriter{file: out}
|
||||
}
|
||||
|
||||
// Write writes data from b into the input file.
|
||||
func (aw *AnsiWriter) Write(b []byte) (int, error) {
|
||||
return aw.file.Write(b)
|
||||
}
|
510
tools/vendor/github.com/Bowery/prompt/ansi_windows.go
generated
vendored
510
tools/vendor/github.com/Bowery/prompt/ansi_windows.go
generated
vendored
@ -1,510 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// keyEventType is the key event type for an input record.
|
||||
const keyEventType = 0x0001
|
||||
|
||||
var (
|
||||
readConsoleInput = kernel.NewProc("ReadConsoleInputW")
|
||||
)
|
||||
|
||||
// inputRecord describes a input event from a console.
|
||||
type inputRecord struct {
|
||||
eventType uint16
|
||||
// Magic to get around the union C type, cast
|
||||
// event to the type using unsafe.Pointer.
|
||||
_ [2]byte
|
||||
event [16]byte
|
||||
}
|
||||
|
||||
// keyEventRecord describes a keyboard event.
|
||||
type keyEventRecord struct {
|
||||
keyDown int32
|
||||
repeatCount uint16
|
||||
virtualKeyCode uint16
|
||||
virtualScanCode uint16
|
||||
char uint16
|
||||
controlKeyState uint32
|
||||
}
|
||||
|
||||
// AnsiReader is an io.Reader that reads from a given file and converts Windows
|
||||
// key codes to their equivalent ANSI escape codes.
|
||||
type AnsiReader struct {
|
||||
fd uintptr
|
||||
buf []rune
|
||||
}
|
||||
|
||||
// NewAnsiReader creates a AnsiReader from the given input file.
|
||||
func NewAnsiReader(in *os.File) *AnsiReader {
|
||||
return &AnsiReader{fd: in.Fd()}
|
||||
}
|
||||
|
||||
// Read reads data from the input converting to ANSI escape codes that can be
|
||||
// read over multiple Reads.
|
||||
func (ar *AnsiReader) Read(b []byte) (int, error) {
|
||||
if len(b) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if len(ar.buf) == 0 {
|
||||
var runes []rune
|
||||
var read uint32
|
||||
rec := new(inputRecord)
|
||||
|
||||
for runes == nil {
|
||||
ret, _, err := readConsoleInput.Call(ar.fd, uintptr(unsafe.Pointer(rec)),
|
||||
1, uintptr(unsafe.Pointer(&read)))
|
||||
if ret == 0 {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if rec.eventType != keyEventType {
|
||||
continue
|
||||
}
|
||||
|
||||
ke := (*keyEventRecord)(unsafe.Pointer(&rec.event))
|
||||
if ke.keyDown == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
shift := false
|
||||
if ke.controlKeyState&shiftKey != 0 {
|
||||
shift = true
|
||||
}
|
||||
|
||||
ctrl := false
|
||||
if ke.controlKeyState&leftCtrlKey != 0 || ke.controlKeyState&rightCtrlKey != 0 {
|
||||
ctrl = true
|
||||
}
|
||||
|
||||
alt := false
|
||||
if ke.controlKeyState&leftAltKey != 0 || ke.controlKeyState&rightAltKey != 0 {
|
||||
alt = true
|
||||
}
|
||||
|
||||
// Backspace, Return, Space.
|
||||
if ke.char == ctrlH || ke.char == returnKey || ke.char == spaceKey {
|
||||
code := string(returnKey)
|
||||
if ke.char == ctrlH {
|
||||
code = string(backKey)
|
||||
} else if ke.char == spaceKey {
|
||||
code = string(spaceKey)
|
||||
}
|
||||
|
||||
if alt {
|
||||
code = string(escKey) + code
|
||||
}
|
||||
|
||||
runes = []rune(code)
|
||||
break
|
||||
}
|
||||
|
||||
// Generate runes for the chars and key codes.
|
||||
if ke.char > 0 {
|
||||
runes = []rune{rune(ke.char)}
|
||||
} else {
|
||||
code := string(escKey)
|
||||
|
||||
switch ke.virtualKeyCode {
|
||||
case f1Key:
|
||||
if ctrl {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.shortFunction("P", shift, ctrl, alt)
|
||||
case f2Key:
|
||||
code += ar.shortFunction("Q", shift, ctrl, alt)
|
||||
case f3Key:
|
||||
code += ar.shortFunction("R", shift, ctrl, alt)
|
||||
case f4Key:
|
||||
code += ar.shortFunction("S", shift, ctrl, alt)
|
||||
case f5Key:
|
||||
code += ar.longFunction("15", shift, ctrl, alt)
|
||||
case f6Key:
|
||||
code += ar.longFunction("17", shift, ctrl, alt)
|
||||
case f7Key:
|
||||
code += ar.longFunction("18", shift, ctrl, alt)
|
||||
case f8Key:
|
||||
code += ar.longFunction("19", shift, ctrl, alt)
|
||||
case f9Key:
|
||||
code += ar.longFunction("20", shift, ctrl, alt)
|
||||
case f10Key:
|
||||
code += ar.longFunction("21", shift, ctrl, alt)
|
||||
case f11Key:
|
||||
code += ar.longFunction("23", shift, ctrl, alt)
|
||||
case f12Key:
|
||||
code += ar.longFunction("24", shift, ctrl, alt)
|
||||
case insertKey:
|
||||
if shift || ctrl {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.longFunction("2", shift, ctrl, alt)
|
||||
case deleteKey:
|
||||
code += ar.longFunction("3", shift, ctrl, alt)
|
||||
case homeKey:
|
||||
code += "OH"
|
||||
case endKey:
|
||||
code += "OF"
|
||||
case pgupKey:
|
||||
if shift {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.longFunction("5", shift, ctrl, alt)
|
||||
case pgdownKey:
|
||||
if shift {
|
||||
continue
|
||||
}
|
||||
|
||||
code += ar.longFunction("6", shift, ctrl, alt)
|
||||
case upKey:
|
||||
code += ar.arrow("A", shift, ctrl, alt)
|
||||
case downKey:
|
||||
code += ar.arrow("B", shift, ctrl, alt)
|
||||
case leftKey:
|
||||
code += ar.arrow("D", shift, ctrl, alt)
|
||||
case rightKey:
|
||||
code += ar.arrow("C", shift, ctrl, alt)
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
runes = []rune(code)
|
||||
}
|
||||
}
|
||||
|
||||
ar.buf = runes
|
||||
}
|
||||
|
||||
// Get items from the buffer.
|
||||
var n int
|
||||
for i, r := range ar.buf {
|
||||
if utf8.RuneLen(r) > len(b) {
|
||||
ar.buf = ar.buf[i:]
|
||||
return n, nil
|
||||
}
|
||||
|
||||
nr := utf8.EncodeRune(b, r)
|
||||
b = b[nr:]
|
||||
n += nr
|
||||
}
|
||||
|
||||
ar.buf = nil
|
||||
return n, nil
|
||||
}
|
||||
|
||||
// shortFunction creates a short function code.
|
||||
func (ar *AnsiReader) shortFunction(ident string, shift, ctrl, alt bool) string {
|
||||
code := "O"
|
||||
|
||||
if shift {
|
||||
code += "1;2"
|
||||
} else if ctrl {
|
||||
code += "1;5"
|
||||
} else if alt {
|
||||
code += "1;3"
|
||||
}
|
||||
|
||||
return code + ident
|
||||
}
|
||||
|
||||
// longFunction creates a long function code.
|
||||
func (ar *AnsiReader) longFunction(ident string, shift, ctrl, alt bool) string {
|
||||
code := "["
|
||||
code += ident
|
||||
|
||||
if shift {
|
||||
code += ";2"
|
||||
} else if ctrl {
|
||||
code += ";5"
|
||||
} else if alt {
|
||||
code += ";3"
|
||||
}
|
||||
|
||||
return code + "~"
|
||||
}
|
||||
|
||||
// arrow creates an arrow code.
|
||||
func (ar *AnsiReader) arrow(ident string, shift, ctrl, alt bool) string {
|
||||
code := "["
|
||||
|
||||
if shift {
|
||||
code += "1;2"
|
||||
} else if ctrl {
|
||||
code += "1;5"
|
||||
} else if alt {
|
||||
code += "1;3"
|
||||
}
|
||||
|
||||
return code + ident
|
||||
}
|
||||
|
||||
// AnsiWriter is an io.Writer that writes to a given file and converts ANSI
|
||||
// escape codes to their equivalent Windows functionality.
|
||||
type AnsiWriter struct {
|
||||
file *os.File
|
||||
buf []byte
|
||||
}
|
||||
|
||||
// NewAnsiWriter creates a AnsiWriter from the given output.
|
||||
func NewAnsiWriter(out *os.File) *AnsiWriter {
|
||||
return &AnsiWriter{file: out}
|
||||
}
|
||||
|
||||
// Write writes the buffer filtering out ANSI escape codes and converting to
|
||||
// the Windows functionality needed. ANSI escape codes may be found over multiple
|
||||
// Writes.
|
||||
func (aw *AnsiWriter) Write(b []byte) (int, error) {
|
||||
needsProcessing := bytes.Contains(b, []byte(string(escKey)))
|
||||
if len(aw.buf) > 0 {
|
||||
needsProcessing = true
|
||||
}
|
||||
|
||||
if !needsProcessing {
|
||||
return aw.file.Write(b)
|
||||
}
|
||||
var p []byte
|
||||
|
||||
for _, char := range b {
|
||||
// Found the beginning of an escape.
|
||||
if char == escKey {
|
||||
aw.buf = append(aw.buf, char)
|
||||
continue
|
||||
}
|
||||
|
||||
// Funtion identifiers.
|
||||
if len(aw.buf) == 1 && (char == '_' || char == 'P' || char == '[' ||
|
||||
char == ']' || char == '^' || char == ' ' || char == '#' ||
|
||||
char == '%' || char == '(' || char == ')' || char == '*' ||
|
||||
char == '+') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
continue
|
||||
}
|
||||
|
||||
// Cursor functions.
|
||||
if len(aw.buf) == 1 && (char == '7' || char == '8') {
|
||||
// Add another char before because finish skips 2 items.
|
||||
aw.buf = append(aw.buf, '_', char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Keyboard functions.
|
||||
if len(aw.buf) == 1 && (char == '=' || char == '>') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Bottom left function.
|
||||
if len(aw.buf) == 1 && char == 'F' {
|
||||
// Add extra char for finish.
|
||||
aw.buf = append(aw.buf, '_', char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Reset function.
|
||||
if len(aw.buf) == 1 && char == 'c' {
|
||||
// Add extra char for finish.
|
||||
aw.buf = append(aw.buf, '_', char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Space functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == ' ' && (char == 'F' || char == 'G' ||
|
||||
char == 'L' || char == 'M' || char == 'N') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Number functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '#' && (char >= '3' && char <= '6') ||
|
||||
char == '8' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Percentage functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '%' && (char == '@' || char == 'G') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Character set functions.
|
||||
if len(aw.buf) >= 2 && (aw.buf[1] == '(' || aw.buf[1] == ')' ||
|
||||
aw.buf[1] == '*' || aw.buf[1] == '+') && (char == '0' ||
|
||||
(char >= '4' && char <= '7') || char == '=' || (char >= 'A' &&
|
||||
char <= 'C') || char == 'E' || char == 'H' || char == 'K' ||
|
||||
char == 'Q' || char == 'R' || char == 'Y') {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// APC functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '_' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of APC.
|
||||
if char == '\\' && aw.buf[len(aw.buf)-1] == escKey {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// DC functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == 'P' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of DC.
|
||||
if char == '\\' && aw.buf[len(aw.buf)-1] == escKey {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// CSI functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '[' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of CSI.
|
||||
if char == '@' || (char >= 'A' && char <= 'M') || char == 'P' ||
|
||||
char == 'S' || char == 'T' || char == 'X' || char == 'Z' ||
|
||||
char == '`' || (char >= 'b' && char <= 'd') || (char >= 'f' &&
|
||||
char <= 'i') || (char >= 'l' && char <= 'n') || (char >= 'p' &&
|
||||
char <= 't') || char == 'w' || char == 'x' || char == 'z' ||
|
||||
char == '{' || char == '|' {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// OSC functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == ']' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// Capture incomplete code.
|
||||
if len(aw.buf) == 4 && aw.buf[2] == '0' && char == ';' {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// End of OSC.
|
||||
if (char == '\\' && aw.buf[len(aw.buf)-1] == escKey) || char == ctrlG {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// PM functions.
|
||||
if len(aw.buf) >= 2 && aw.buf[1] == '^' {
|
||||
aw.buf = append(aw.buf, char)
|
||||
|
||||
// End of PM.
|
||||
if char == '\\' && aw.buf[len(aw.buf)-1] == escKey {
|
||||
err := aw.finish(nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
// Normal character, resets escape buffer.
|
||||
if len(aw.buf) > 0 {
|
||||
aw.buf = nil
|
||||
}
|
||||
p = append(p, char)
|
||||
}
|
||||
|
||||
_, err := aw.file.Write(p)
|
||||
return len(b), err
|
||||
}
|
||||
|
||||
// finish finishes an ANSI escape code and calls the parsing function. Afterwards
|
||||
// the escape buffer is emptied.
|
||||
func (aw *AnsiWriter) finish(parse func([]byte) error) error {
|
||||
var err error
|
||||
|
||||
if parse != nil {
|
||||
err = parse(aw.buf[2:])
|
||||
}
|
||||
|
||||
aw.buf = nil
|
||||
return err
|
||||
}
|
152
tools/vendor/github.com/Bowery/prompt/buffer.go
generated
vendored
152
tools/vendor/github.com/Bowery/prompt/buffer.go
generated
vendored
@ -1,152 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Buffer contains state for line editing and writing.
|
||||
type Buffer struct {
|
||||
Out *os.File
|
||||
Prompt string
|
||||
Echo bool
|
||||
Cols int
|
||||
pos int
|
||||
size int
|
||||
data []rune
|
||||
}
|
||||
|
||||
// NewBuffer creates a buffer writing to out if echo is true.
|
||||
func NewBuffer(prompt string, out *os.File, echo bool) *Buffer {
|
||||
return &Buffer{
|
||||
Out: out,
|
||||
Prompt: prompt,
|
||||
Echo: echo,
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the data as a string.
|
||||
func (buf *Buffer) String() string {
|
||||
return string(buf.data[:buf.size])
|
||||
}
|
||||
|
||||
// Insert inserts characters at the cursors position.
|
||||
func (buf *Buffer) Insert(rs ...rune) error {
|
||||
rsLen := len(rs)
|
||||
total := buf.size + rsLen
|
||||
|
||||
if total > len(buf.data) {
|
||||
buf.data = append(buf.data, make([]rune, rsLen)...)
|
||||
}
|
||||
|
||||
// Shift characters to make room in the correct pos.
|
||||
if buf.size != buf.pos {
|
||||
copy(buf.data[buf.pos+rsLen:buf.size+rsLen], buf.data[buf.pos:buf.size])
|
||||
}
|
||||
|
||||
for _, r := range rs {
|
||||
buf.data[buf.pos] = r
|
||||
buf.pos++
|
||||
buf.size++
|
||||
}
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Set sets the content in the buffer.
|
||||
func (buf *Buffer) Set(rs ...rune) error {
|
||||
rsLen := len(rs)
|
||||
buf.data = rs
|
||||
buf.pos = rsLen
|
||||
buf.size = rsLen
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Start moves the cursor to the start.
|
||||
func (buf *Buffer) Start() error {
|
||||
if buf.pos <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos = 0
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// End moves the cursor to the end.
|
||||
func (buf *Buffer) End() error {
|
||||
if buf.pos >= buf.size {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos = buf.size
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Left moves the cursor one character left.
|
||||
func (buf *Buffer) Left() error {
|
||||
if buf.pos <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos--
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Right moves the cursor one character right.
|
||||
func (buf *Buffer) Right() error {
|
||||
if buf.pos >= buf.size {
|
||||
return nil
|
||||
}
|
||||
|
||||
buf.pos++
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// Del removes the character at the cursor position.
|
||||
func (buf *Buffer) Del() error {
|
||||
if buf.pos >= buf.size {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shift characters after position back one.
|
||||
copy(buf.data[buf.pos:], buf.data[buf.pos+1:buf.size])
|
||||
buf.size--
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// DelLeft removes the character to the left.
|
||||
func (buf *Buffer) DelLeft() error {
|
||||
if buf.pos <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Shift characters from position back one.
|
||||
copy(buf.data[buf.pos-1:], buf.data[buf.pos:buf.size])
|
||||
buf.pos--
|
||||
buf.size--
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// EndLine ends the line with CRLF.
|
||||
func (buf *Buffer) EndLine() error {
|
||||
_, err := buf.Out.Write(crlf)
|
||||
return err
|
||||
}
|
||||
|
||||
// toBytes converts a slice of runes to its equivalent in bytes.
|
||||
func toBytes(runes []rune) []byte {
|
||||
var bytes []byte
|
||||
char := make([]byte, utf8.UTFMax)
|
||||
|
||||
for _, r := range runes {
|
||||
n := utf8.EncodeRune(char, r)
|
||||
bytes = append(bytes, char[:n]...)
|
||||
}
|
||||
|
||||
return bytes
|
||||
}
|
76
tools/vendor/github.com/Bowery/prompt/buffer_unix.go
generated
vendored
76
tools/vendor/github.com/Bowery/prompt/buffer_unix.go
generated
vendored
@ -1,76 +0,0 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Refresh rewrites the prompt and buffer.
|
||||
func (buf *Buffer) Refresh() error {
|
||||
// If we're not echoing just write prompt.
|
||||
if !buf.Echo {
|
||||
_, err := buf.Out.Write(mvLeftEdge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(delRight)
|
||||
return err
|
||||
}
|
||||
|
||||
prLen := len(buf.Prompt)
|
||||
start := 0
|
||||
size := buf.size
|
||||
pos := buf.pos
|
||||
|
||||
// Get slice range that should be visible.
|
||||
for prLen+pos >= buf.Cols {
|
||||
start++
|
||||
size--
|
||||
pos--
|
||||
}
|
||||
for prLen+size > buf.Cols {
|
||||
size--
|
||||
}
|
||||
|
||||
_, err := buf.Out.Write(mvLeftEdge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(toBytes(buf.data[start : size+start]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(delRight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(fmt.Sprintf(mvToCol, pos+prLen)))
|
||||
return err
|
||||
}
|
||||
|
||||
// ClsScreen clears the screen and refreshes.
|
||||
func (buf *Buffer) ClsScreen() error {
|
||||
_, err := buf.Out.Write(clsScreen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
150
tools/vendor/github.com/Bowery/prompt/buffer_windows.go
generated
vendored
150
tools/vendor/github.com/Bowery/prompt/buffer_windows.go
generated
vendored
@ -1,150 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var (
|
||||
fillConsoleOutputCharacter = kernel.NewProc("FillConsoleOutputCharacterW")
|
||||
setConsoleCursorPosition = kernel.NewProc("SetConsoleCursorPosition")
|
||||
)
|
||||
|
||||
// Refresh rewrites the prompt and buffer.
|
||||
func (buf *Buffer) Refresh() error {
|
||||
csbi := new(consoleScreenBufferInfo)
|
||||
ret, _, err := getConsoleScreenBufferInfo.Call(buf.Out.Fd(),
|
||||
uintptr(unsafe.Pointer(csbi)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we're not echoing just write prompt.
|
||||
if !buf.Echo {
|
||||
err = buf.delLine(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.mvLeftEdge(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
return err
|
||||
}
|
||||
|
||||
prLen := len(buf.Prompt)
|
||||
start := 0
|
||||
size := buf.size
|
||||
pos := buf.pos
|
||||
|
||||
// Get slice range that should be visible.
|
||||
for prLen+pos >= buf.Cols {
|
||||
start++
|
||||
size--
|
||||
pos--
|
||||
}
|
||||
for prLen+size > buf.Cols {
|
||||
size--
|
||||
}
|
||||
|
||||
err = buf.delLine(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = buf.mvLeftEdge(csbi)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write([]byte(buf.Prompt))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = buf.Out.Write(toBytes(buf.data[start : size+start]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return buf.mvToCol(csbi, pos+prLen)
|
||||
}
|
||||
|
||||
// ClsScreen clears the screen and refreshes.
|
||||
func (buf *Buffer) ClsScreen() error {
|
||||
var written uint32
|
||||
coords := new(coord)
|
||||
|
||||
csbi := new(consoleScreenBufferInfo)
|
||||
ret, _, err := getConsoleScreenBufferInfo.Call(buf.Out.Fd(),
|
||||
uintptr(unsafe.Pointer(csbi)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// Clear everything from 0,0.
|
||||
ret, _, err = fillConsoleOutputCharacter.Call(buf.Out.Fd(), uintptr(' '),
|
||||
uintptr(csbi.size.x*csbi.size.y), uintptr(*(*int32)(unsafe.Pointer(coords))),
|
||||
uintptr(unsafe.Pointer(&written)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set cursor at 0,0.
|
||||
ret, _, err = setConsoleCursorPosition.Call(buf.Out.Fd(),
|
||||
uintptr(*(*int32)(unsafe.Pointer(coords))))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return buf.Refresh()
|
||||
}
|
||||
|
||||
// delLine deletes the line the csbi cursor is positioned on.
|
||||
// TODO: Possible refresh jittering reason, instead we should copy the Unix
|
||||
// code and write over contents and then remove everything to the right.
|
||||
func (buf *Buffer) delLine(csbi *consoleScreenBufferInfo) error {
|
||||
var written uint32
|
||||
coords := &coord{y: csbi.cursorPosition.y}
|
||||
|
||||
ret, _, err := fillConsoleOutputCharacter.Call(buf.Out.Fd(), uintptr(' '),
|
||||
uintptr(csbi.size.x), uintptr(*(*int32)(unsafe.Pointer(coords))),
|
||||
uintptr(unsafe.Pointer(&written)))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// mvLeftEdge moves the cursor to the beginning of the line the csbi cursor
|
||||
// is positioned on.
|
||||
func (buf *Buffer) mvLeftEdge(csbi *consoleScreenBufferInfo) error {
|
||||
coords := &coord{y: csbi.cursorPosition.y}
|
||||
|
||||
ret, _, err := setConsoleCursorPosition.Call(buf.Out.Fd(),
|
||||
uintptr(*(*int32)(unsafe.Pointer(coords))))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// mvTolCol moves the cursor to the col on the line the csbi cursor is
|
||||
// positioned on.
|
||||
func (buf *Buffer) mvToCol(csbi *consoleScreenBufferInfo, x int) error {
|
||||
coords := &coord{x: int16(x), y: csbi.cursorPosition.y}
|
||||
|
||||
ret, _, err := setConsoleCursorPosition.Call(buf.Out.Fd(),
|
||||
uintptr(*(*int32)(unsafe.Pointer(coords))))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
15
tools/vendor/github.com/Bowery/prompt/ioctl_bsd.go
generated
vendored
15
tools/vendor/github.com/Bowery/prompt/ioctl_bsd.go
generated
vendored
@ -1,15 +0,0 @@
|
||||
// +build darwin freebsd openbsd netbsd dragonfly
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tcgets = unix.TIOCGETA
|
||||
tcsets = unix.TIOCSETA
|
||||
tcsetsf = unix.TIOCSETAF
|
||||
)
|
13
tools/vendor/github.com/Bowery/prompt/ioctl_linux.go
generated
vendored
13
tools/vendor/github.com/Bowery/prompt/ioctl_linux.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tcgets = unix.TCGETS
|
||||
tcsets = unix.TCSETS
|
||||
tcsetsf = unix.TCSETSF
|
||||
)
|
41
tools/vendor/github.com/Bowery/prompt/ioctl_solaris.go
generated
vendored
41
tools/vendor/github.com/Bowery/prompt/ioctl_solaris.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
tcgets = unix.TCGETS
|
||||
tcsetsf = unix.TCSETSF
|
||||
tcsets = unix.TCSETS
|
||||
)
|
||||
|
||||
// terminalSize retrieves the cols/rows for the terminal connected to out.
|
||||
func terminalSize(out *os.File) (int, int, error) {
|
||||
ws, err := unix.IoctlGetWinsize(int(out.Fd()), unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return int(ws.Col), int(ws.Row), nil
|
||||
}
|
||||
|
||||
// getTermios retrieves the termios settings for the terminal descriptor.
|
||||
func getTermios(fd uintptr) (*unix.Termios, error) {
|
||||
return unix.IoctlGetTermios(int(fd), tcgets)
|
||||
}
|
||||
|
||||
// setTermios sets the termios settings for the terminal descriptor,
|
||||
// optionally flushing the buffer before setting.
|
||||
func setTermios(fd uintptr, flush bool, mode *unix.Termios) error {
|
||||
req := tcsets
|
||||
if flush {
|
||||
req = tcsetsf
|
||||
}
|
||||
|
||||
return unix.IoctlSetTermios(int(fd), req, mode)
|
||||
}
|
62
tools/vendor/github.com/Bowery/prompt/ioctl_unix.go
generated
vendored
62
tools/vendor/github.com/Bowery/prompt/ioctl_unix.go
generated
vendored
@ -1,62 +0,0 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// winsize contains the size for the terminal.
|
||||
type winsize struct {
|
||||
rows uint16
|
||||
cols uint16
|
||||
_ uint32
|
||||
}
|
||||
|
||||
// terminalSize retrieves the cols/rows for the terminal connected to out.
|
||||
func terminalSize(out *os.File) (int, int, error) {
|
||||
ws := new(winsize)
|
||||
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, out.Fd(),
|
||||
uintptr(unix.TIOCGWINSZ), uintptr(unsafe.Pointer(ws)))
|
||||
if err != 0 {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return int(ws.cols), int(ws.rows), nil
|
||||
}
|
||||
|
||||
// getTermios retrieves the termios settings for the terminal descriptor.
|
||||
func getTermios(fd uintptr) (*unix.Termios, error) {
|
||||
termios := new(unix.Termios)
|
||||
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, tcgets,
|
||||
uintptr(unsafe.Pointer(termios)))
|
||||
if err != 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return termios, nil
|
||||
}
|
||||
|
||||
// setTermios sets the termios settings for the terminal descriptor,
|
||||
// optionally flushing the buffer before setting.
|
||||
func setTermios(fd uintptr, flush bool, mode *unix.Termios) error {
|
||||
req := tcsets
|
||||
if flush {
|
||||
req = tcsetsf
|
||||
}
|
||||
|
||||
_, _, err := unix.Syscall(unix.SYS_IOCTL, fd, uintptr(req),
|
||||
uintptr(unsafe.Pointer(mode)))
|
||||
if err != 0 {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
41
tools/vendor/github.com/Bowery/prompt/keys.go
generated
vendored
41
tools/vendor/github.com/Bowery/prompt/keys.go
generated
vendored
@ -1,41 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
// Line ending in raw mode.
|
||||
var crlf = []byte("\r\n")
|
||||
|
||||
const (
|
||||
backKey = '\u007f'
|
||||
escKey = '\u001B'
|
||||
spaceKey = '\u0020'
|
||||
)
|
||||
|
||||
const (
|
||||
ctrlA = iota + 1
|
||||
ctrlB
|
||||
ctrlC
|
||||
ctrlD
|
||||
ctrlE
|
||||
ctrlF
|
||||
ctrlG
|
||||
ctrlH
|
||||
tabKey
|
||||
ctrlJ
|
||||
ctrlK
|
||||
ctrlL
|
||||
returnKey
|
||||
ctrlN
|
||||
ctrlO
|
||||
ctrlP
|
||||
ctrlQ
|
||||
ctrlR
|
||||
ctrlS
|
||||
ctrlT
|
||||
ctrlU
|
||||
ctrlV
|
||||
ctrlW
|
||||
ctrlX
|
||||
ctrlY
|
||||
ctrlZ
|
||||
)
|
13
tools/vendor/github.com/Bowery/prompt/keys_unix.go
generated
vendored
13
tools/vendor/github.com/Bowery/prompt/keys_unix.go
generated
vendored
@ -1,13 +0,0 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
const mvToCol = "\u001b[0G\u001b[%dC"
|
||||
|
||||
var (
|
||||
mvLeftEdge = []byte("\u001b[0G")
|
||||
clsScreen = []byte("\u001b[H\u001b[2J")
|
||||
delRight = []byte("\u001b[0K")
|
||||
)
|
34
tools/vendor/github.com/Bowery/prompt/keys_windows.go
generated
vendored
34
tools/vendor/github.com/Bowery/prompt/keys_windows.go
generated
vendored
@ -1,34 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
const (
|
||||
f1Key = 0x70 + iota
|
||||
f2Key
|
||||
f3Key
|
||||
f4Key
|
||||
f5Key
|
||||
f6Key
|
||||
f7Key
|
||||
f8Key
|
||||
f9Key
|
||||
f10Key
|
||||
f11Key
|
||||
f12Key
|
||||
|
||||
homeKey = 0x24
|
||||
endKey = 0x23
|
||||
upKey = 0x26
|
||||
downKey = 0x28
|
||||
rightKey = 0x27
|
||||
leftKey = 0x25
|
||||
insertKey = 0x2d
|
||||
pgupKey = 0x21
|
||||
pgdownKey = 0x22
|
||||
deleteKey = 0x2e
|
||||
leftAltKey = 0x2
|
||||
rightAltKey = 0x1
|
||||
leftCtrlKey = 0x8
|
||||
rightCtrlKey = 0x4
|
||||
shiftKey = 0x10
|
||||
)
|
85
tools/vendor/github.com/Bowery/prompt/prompt.go
generated
vendored
85
tools/vendor/github.com/Bowery/prompt/prompt.go
generated
vendored
@ -1,85 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
// Package prompt implements a cross platform line-editing prompt. It also
|
||||
// provides routines to use ANSI escape sequences across platforms for
|
||||
// terminal connected io.Readers/io.Writers.
|
||||
//
|
||||
// If os.Stdin isn't connected to a terminal or (on Unix)if the terminal
|
||||
// doesn't support the ANSI escape sequences needed a fallback prompt is
|
||||
// provided that doesn't do line-editing. Unix terminals that are not supported
|
||||
// will have the TERM environment variable set to either "dumb" or "cons25".
|
||||
//
|
||||
// The keyboard shortcuts are similar to those found in the Readline library:
|
||||
//
|
||||
// - Enter / CTRL+D
|
||||
// - End the line.
|
||||
// - CTRL+C
|
||||
// - End the line, return error `ErrCTRLC`.
|
||||
// - Backspace
|
||||
// - Remove the character to the left.
|
||||
// - CTRL+L
|
||||
// - Clear the screen(keeping the current lines content).
|
||||
// - Home / End
|
||||
// - Jump to the beginning/end of the line.
|
||||
// - Up arrow / Down arrow
|
||||
// - Go back and forward in the history.
|
||||
// - Left arrow / Right arrow
|
||||
// - Move left/right one character.
|
||||
// - Delete
|
||||
// - Remove the character to the right.
|
||||
package prompt
|
||||
|
||||
// Basic is a wrapper around Terminal.Basic.
|
||||
func Basic(prefix string, required bool) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Basic(prefix, required)
|
||||
}
|
||||
|
||||
// BasicDefault is a wrapper around Terminal.BasicDefault.
|
||||
func BasicDefault(prefix, def string) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.BasicDefault(prefix, def)
|
||||
}
|
||||
|
||||
// Ask is a wrapper around Terminal.Ask.
|
||||
func Ask(question string) (bool, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Ask(question)
|
||||
}
|
||||
|
||||
// Custom is a wrapper around Terminal.Custom.
|
||||
func Custom(prefix string, test func(string) (string, bool)) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Custom(prefix, test)
|
||||
}
|
||||
|
||||
// Password is a wrapper around Terminal.Password.
|
||||
func Password(prefix string) (string, error) {
|
||||
term, err := NewTerminal()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer term.Close()
|
||||
|
||||
return term.Password(prefix)
|
||||
}
|
471
tools/vendor/github.com/Bowery/prompt/term.go
generated
vendored
471
tools/vendor/github.com/Bowery/prompt/term.go
generated
vendored
@ -1,471 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrCTRLC is returned when CTRL+C is pressed stopping the prompt.
|
||||
ErrCTRLC = errors.New("Interrupted (CTRL+C)")
|
||||
// ErrEOF is returned when CTRL+D is pressed stopping the prompt.
|
||||
ErrEOF = errors.New("EOF (CTRL+D)")
|
||||
)
|
||||
|
||||
// Possible events that may occur when reading from input.
|
||||
const (
|
||||
evChar = iota
|
||||
evSkip
|
||||
evReturn
|
||||
evEOF
|
||||
evCtrlC
|
||||
evBack
|
||||
evClear
|
||||
evHome
|
||||
evEnd
|
||||
evUp
|
||||
evDown
|
||||
evRight
|
||||
evLeft
|
||||
evDel
|
||||
)
|
||||
|
||||
// IsNotTerminal checks if an error is related to the input not being a terminal.
|
||||
func IsNotTerminal(err error) bool {
|
||||
return isNotTerminal(err)
|
||||
}
|
||||
|
||||
// TerminalSize retrieves the columns/rows for the terminal connected to out.
|
||||
func TerminalSize(out *os.File) (int, int, error) {
|
||||
return terminalSize(out)
|
||||
}
|
||||
|
||||
// Terminal contains the state for raw terminal input.
|
||||
type Terminal struct {
|
||||
In *os.File
|
||||
Out *os.File
|
||||
History []string
|
||||
histIdx int
|
||||
simpleReader *bufio.Reader
|
||||
t *terminal
|
||||
}
|
||||
|
||||
// NewTerminal creates a terminal and sets it to raw input mode.
|
||||
func NewTerminal() (*Terminal, error) {
|
||||
in := os.Stdin
|
||||
|
||||
term, err := newTerminal(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Terminal{
|
||||
In: in,
|
||||
Out: os.Stdout,
|
||||
History: make([]string, 0, 10),
|
||||
histIdx: -1,
|
||||
t: term,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Basic gets input and if required tests to ensure input was given.
|
||||
func (term *Terminal) Basic(prefix string, required bool) (string, error) {
|
||||
return term.Custom(prefix, func(input string) (string, bool) {
|
||||
if required && input == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return input, true
|
||||
})
|
||||
}
|
||||
|
||||
// BasicDefault gets input and if empty uses the given default.
|
||||
func (term *Terminal) BasicDefault(prefix, def string) (string, error) {
|
||||
return term.Custom(prefix+"(Default: "+def+")", func(input string) (string, bool) {
|
||||
if input == "" {
|
||||
input = def
|
||||
}
|
||||
|
||||
return input, true
|
||||
})
|
||||
}
|
||||
|
||||
// Ask gets input and checks if it's truthy or not, and returns that
|
||||
// in a boolean fashion.
|
||||
func (term *Terminal) Ask(question string) (bool, error) {
|
||||
input, err := term.Custom(question+"?(y/n)", func(input string) (string, bool) {
|
||||
if input == "" {
|
||||
return "", false
|
||||
}
|
||||
input = strings.ToLower(input)
|
||||
|
||||
if input == "y" || input == "yes" {
|
||||
return "yes", true
|
||||
}
|
||||
|
||||
return "", true
|
||||
})
|
||||
|
||||
var ok bool
|
||||
if input != "" {
|
||||
ok = true
|
||||
}
|
||||
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// Custom gets input and calls the given test function with the input to
|
||||
// check if the input is valid, a true return will return the string.
|
||||
func (term *Terminal) Custom(prefix string, test func(string) (string, bool)) (string, error) {
|
||||
var err error
|
||||
var input string
|
||||
var ok bool
|
||||
|
||||
for !ok {
|
||||
input, err = term.GetPrompt(prefix)
|
||||
if err != nil && err != io.EOF {
|
||||
return "", err
|
||||
}
|
||||
|
||||
input, ok = test(input)
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// Password retrieves a password from stdin without echoing it.
|
||||
func (term *Terminal) Password(prefix string) (string, error) {
|
||||
var err error
|
||||
var input string
|
||||
|
||||
for input == "" {
|
||||
input, err = term.GetPassword(prefix)
|
||||
if err != nil && err != io.EOF {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// GetPrompt gets a line with the prefix and echos input.
|
||||
func (term *Terminal) GetPrompt(prefix string) (string, error) {
|
||||
if !term.t.supportsEditing {
|
||||
return term.simplePrompt(prefix)
|
||||
}
|
||||
|
||||
buf := NewBuffer(prefix, term.Out, true)
|
||||
return term.prompt(buf, NewAnsiReader(term.In))
|
||||
}
|
||||
|
||||
// GetPassword gets a line with the prefix and doesn't echo input.
|
||||
func (term *Terminal) GetPassword(prefix string) (string, error) {
|
||||
if !term.t.supportsEditing {
|
||||
return term.simplePrompt(prefix)
|
||||
}
|
||||
|
||||
buf := NewBuffer(prefix, term.Out, false)
|
||||
return term.password(buf, NewAnsiReader(term.In))
|
||||
}
|
||||
|
||||
func (term *Terminal) Close() error {
|
||||
return term.t.Close()
|
||||
}
|
||||
|
||||
// simplePrompt is a fallback prompt without line editing support.
|
||||
func (term *Terminal) simplePrompt(prefix string) (string, error) {
|
||||
if term.simpleReader == nil {
|
||||
term.simpleReader = bufio.NewReader(term.In)
|
||||
}
|
||||
|
||||
_, err := term.Out.Write([]byte(prefix))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
line, err := term.simpleReader.ReadString('\n')
|
||||
line = strings.TrimRight(line, "\r\n ")
|
||||
line = strings.TrimLeft(line, " ")
|
||||
|
||||
return line, err
|
||||
}
|
||||
|
||||
// setup initializes a prompt.
|
||||
func (term *Terminal) setup(buf *Buffer, in io.Reader) (*bufio.Reader, error) {
|
||||
cols, _, err := TerminalSize(buf.Out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
buf.Cols = cols
|
||||
input := bufio.NewReader(in)
|
||||
|
||||
err = buf.Refresh()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
// read reads a rune and parses ANSI escape sequences found
|
||||
func (term *Terminal) read(in *bufio.Reader) (int, rune, error) {
|
||||
char, _, err := in.ReadRune()
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
switch char {
|
||||
default:
|
||||
// Standard chars.
|
||||
return evChar, char, nil
|
||||
case tabKey, ctrlA, ctrlB, ctrlE, ctrlF, ctrlG, ctrlH, ctrlJ, ctrlK, ctrlN,
|
||||
ctrlO, ctrlP, ctrlQ, ctrlR, ctrlS, ctrlT, ctrlU, ctrlV, ctrlW, ctrlX,
|
||||
ctrlY, ctrlZ:
|
||||
// Skip.
|
||||
return evSkip, char, nil
|
||||
case returnKey:
|
||||
// End of line.
|
||||
return evReturn, char, nil
|
||||
case ctrlD:
|
||||
// End of file.
|
||||
return evEOF, char, nil
|
||||
case ctrlC:
|
||||
// End of line, interrupted.
|
||||
return evCtrlC, char, nil
|
||||
case backKey:
|
||||
// Backspace.
|
||||
return evBack, char, nil
|
||||
case ctrlL:
|
||||
// Clear screen.
|
||||
return evClear, char, nil
|
||||
case escKey:
|
||||
// Functions like arrows, home, etc.
|
||||
esc := make([]byte, 2)
|
||||
_, err = in.Read(esc)
|
||||
if err != nil {
|
||||
return -1, char, err
|
||||
}
|
||||
|
||||
// Home, end.
|
||||
if esc[0] == 'O' {
|
||||
switch esc[1] {
|
||||
case 'H':
|
||||
// Home.
|
||||
return evHome, char, nil
|
||||
case 'F':
|
||||
// End.
|
||||
return evEnd, char, nil
|
||||
}
|
||||
|
||||
return evSkip, char, nil
|
||||
}
|
||||
|
||||
// Arrows, delete, pgup, pgdown, insert.
|
||||
if esc[0] == '[' {
|
||||
switch esc[1] {
|
||||
case 'A':
|
||||
// Up.
|
||||
return evUp, char, nil
|
||||
case 'B':
|
||||
// Down.
|
||||
return evDown, char, nil
|
||||
case 'C':
|
||||
// Right.
|
||||
return evRight, char, nil
|
||||
case 'D':
|
||||
// Left.
|
||||
return evLeft, char, nil
|
||||
}
|
||||
|
||||
// Delete, pgup, pgdown, insert.
|
||||
if esc[1] > '0' && esc[1] < '7' {
|
||||
extEsc := make([]byte, 3)
|
||||
_, err = in.Read(extEsc)
|
||||
if err != nil {
|
||||
return -1, char, err
|
||||
}
|
||||
|
||||
if extEsc[0] == '~' {
|
||||
switch esc[1] {
|
||||
case '2', '5', '6':
|
||||
// Insert, pgup, pgdown.
|
||||
return evSkip, char, err
|
||||
case '3':
|
||||
// Delete.
|
||||
return evDel, char, err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return evSkip, char, nil
|
||||
}
|
||||
|
||||
// prompt reads from in and parses ANSI escapes writing to buf.
|
||||
func (term *Terminal) prompt(buf *Buffer, in io.Reader) (string, error) {
|
||||
input, err := term.setup(buf, in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
term.History = append(term.History, "")
|
||||
term.histIdx = len(term.History) - 1
|
||||
curHistIdx := term.histIdx
|
||||
|
||||
for {
|
||||
typ, char, err := term.read(input)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case evChar:
|
||||
err = buf.Insert(char)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.History[curHistIdx] = buf.String()
|
||||
case evSkip:
|
||||
continue
|
||||
case evReturn:
|
||||
err = buf.EndLine()
|
||||
return buf.String(), err
|
||||
case evEOF:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrEOF
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evCtrlC:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrCTRLC
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evBack:
|
||||
err = buf.DelLeft()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.History[curHistIdx] = buf.String()
|
||||
case evClear:
|
||||
err = buf.ClsScreen()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evHome:
|
||||
err = buf.Start()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evEnd:
|
||||
err = buf.End()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evUp:
|
||||
idx := term.histIdx
|
||||
if term.histIdx > 0 {
|
||||
idx--
|
||||
}
|
||||
|
||||
err = buf.Set([]rune(term.History[idx])...)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.histIdx = idx
|
||||
case evDown:
|
||||
idx := term.histIdx
|
||||
if term.histIdx < len(term.History)-1 {
|
||||
idx++
|
||||
}
|
||||
|
||||
err = buf.Set([]rune(term.History[idx])...)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.histIdx = idx
|
||||
case evRight:
|
||||
err = buf.Right()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evLeft:
|
||||
err = buf.Left()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evDel:
|
||||
err = buf.Del()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
term.History[curHistIdx] = buf.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// password reads from in and parses restricted ANSI escapes writing to buf.
|
||||
func (term *Terminal) password(buf *Buffer, in io.Reader) (string, error) {
|
||||
input, err := term.setup(buf, in)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for {
|
||||
typ, char, err := term.read(input)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
|
||||
switch typ {
|
||||
case evChar:
|
||||
err = buf.Insert(char)
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evSkip, evHome, evEnd, evUp, evDown, evRight, evLeft, evDel:
|
||||
continue
|
||||
case evReturn:
|
||||
err = buf.EndLine()
|
||||
return buf.String(), err
|
||||
case evEOF:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrEOF
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evCtrlC:
|
||||
err = buf.EndLine()
|
||||
if err == nil {
|
||||
err = ErrCTRLC
|
||||
}
|
||||
|
||||
return buf.String(), err
|
||||
case evBack:
|
||||
err = buf.DelLeft()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
case evClear:
|
||||
err = buf.ClsScreen()
|
||||
if err != nil {
|
||||
return buf.String(), err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
96
tools/vendor/github.com/Bowery/prompt/term_unix.go
generated
vendored
96
tools/vendor/github.com/Bowery/prompt/term_unix.go
generated
vendored
@ -1,96 +0,0 @@
|
||||
// +build linux darwin freebsd openbsd netbsd dragonfly solaris
|
||||
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// List of unsupported $TERM values.
|
||||
var unsupported = []string{"", "dumb", "cons25"}
|
||||
|
||||
// supportsEditing checks if the terminal supports ansi escapes.
|
||||
func supportsEditing() bool {
|
||||
term := os.Getenv("TERM")
|
||||
|
||||
for _, t := range unsupported {
|
||||
if t == term {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// isNotTerminal checks if an error is related to the input not being a terminal.
|
||||
func isNotTerminal(err error) bool {
|
||||
return err == unix.ENOTTY
|
||||
}
|
||||
|
||||
// terminal contains the private fields for a Unix terminal.
|
||||
type terminal struct {
|
||||
supportsEditing bool
|
||||
fd uintptr
|
||||
origMode unix.Termios
|
||||
}
|
||||
|
||||
// newTerminal creates a terminal and sets it to raw input mode.
|
||||
func newTerminal(in *os.File) (*terminal, error) {
|
||||
term := &terminal{fd: in.Fd()}
|
||||
|
||||
if !supportsEditing() {
|
||||
return term, nil
|
||||
}
|
||||
|
||||
t, err := getTermios(term.fd)
|
||||
if err != nil {
|
||||
if IsNotTerminal(err) {
|
||||
return term, nil
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
term.origMode = *t
|
||||
mode := term.origMode
|
||||
term.supportsEditing = true
|
||||
|
||||
// Set new mode flags, for reference see cfmakeraw(3).
|
||||
mode.Iflag &^= (unix.BRKINT | unix.IGNBRK | unix.ICRNL |
|
||||
unix.INLCR | unix.IGNCR | unix.ISTRIP | unix.IXON |
|
||||
unix.PARMRK)
|
||||
|
||||
mode.Oflag &^= unix.OPOST
|
||||
|
||||
mode.Lflag &^= (unix.ECHO | unix.ECHONL | unix.ICANON |
|
||||
unix.ISIG | unix.IEXTEN)
|
||||
|
||||
mode.Cflag &^= (unix.CSIZE | unix.PARENB)
|
||||
mode.Cflag |= unix.CS8
|
||||
|
||||
// Set controls; min num of bytes, and timeouts.
|
||||
mode.Cc[unix.VMIN] = 1
|
||||
mode.Cc[unix.VTIME] = 0
|
||||
|
||||
err = setTermios(term.fd, true, &mode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return term, nil
|
||||
}
|
||||
|
||||
// Close disables the terminals raw input.
|
||||
func (term *terminal) Close() error {
|
||||
if term.supportsEditing {
|
||||
err := setTermios(term.fd, false, &term.origMode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
116
tools/vendor/github.com/Bowery/prompt/term_windows.go
generated
vendored
116
tools/vendor/github.com/Bowery/prompt/term_windows.go
generated
vendored
@ -1,116 +0,0 @@
|
||||
// Copyright 2013-2015 Bowery, Inc.
|
||||
|
||||
package prompt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Flags to control the terminals mode.
|
||||
const (
|
||||
echoInputFlag = 0x0004
|
||||
insertModeFlag = 0x0020
|
||||
lineInputFlag = 0x0002
|
||||
mouseInputFlag = 0x0010
|
||||
processedInputFlag = 0x0001
|
||||
windowInputFlag = 0x0008
|
||||
)
|
||||
|
||||
// Error number returned for an invalid handle.
|
||||
const errnoInvalidHandle = 0x6
|
||||
|
||||
var (
|
||||
kernel = syscall.NewLazyDLL("kernel32.dll")
|
||||
getConsoleScreenBufferInfo = kernel.NewProc("GetConsoleScreenBufferInfo")
|
||||
setConsoleMode = kernel.NewProc("SetConsoleMode")
|
||||
)
|
||||
|
||||
// consoleScreenBufferInfo contains various fields for the terminal.
|
||||
type consoleScreenBufferInfo struct {
|
||||
size coord
|
||||
cursorPosition coord
|
||||
attributes uint16
|
||||
window smallRect
|
||||
maximumWindowSize coord
|
||||
}
|
||||
|
||||
// coord contains coords for positioning.
|
||||
type coord struct {
|
||||
x int16
|
||||
y int16
|
||||
}
|
||||
|
||||
// smallRect contains positions for the window edges.
|
||||
type smallRect struct {
|
||||
left int16
|
||||
top int16
|
||||
right int16
|
||||
bottom int16
|
||||
}
|
||||
|
||||
// terminalSize retrieves the cols/rows for the terminal connected to out.
|
||||
func terminalSize(out *os.File) (int, int, error) {
|
||||
csbi := new(consoleScreenBufferInfo)
|
||||
|
||||
ret, _, err := getConsoleScreenBufferInfo.Call(out.Fd(), uintptr(unsafe.Pointer(csbi)))
|
||||
if ret == 0 {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
// Results are always off by one.
|
||||
cols := csbi.window.right - csbi.window.left + 1
|
||||
rows := csbi.window.bottom - csbi.window.top + 1
|
||||
|
||||
return int(cols), int(rows), nil
|
||||
}
|
||||
|
||||
// isNotTerminal checks if an error is related to the input not being a terminal.
|
||||
func isNotTerminal(err error) bool {
|
||||
errno, ok := err.(syscall.Errno)
|
||||
|
||||
return ok && errno == errnoInvalidHandle
|
||||
}
|
||||
|
||||
// terminal contains the private fields for a Windows terminal.
|
||||
type terminal struct {
|
||||
supportsEditing bool
|
||||
fd uintptr
|
||||
origMode uint32
|
||||
}
|
||||
|
||||
// newTerminal creates a terminal and sets it to raw input mode.
|
||||
func newTerminal(in *os.File) (*terminal, error) {
|
||||
term := &terminal{fd: in.Fd()}
|
||||
|
||||
err := syscall.GetConsoleMode(syscall.Handle(term.fd), &term.origMode)
|
||||
if err != nil {
|
||||
return term, nil
|
||||
}
|
||||
mode := term.origMode
|
||||
term.supportsEditing = true
|
||||
|
||||
// Set new mode flags.
|
||||
mode &^= (echoInputFlag | insertModeFlag | lineInputFlag | mouseInputFlag |
|
||||
processedInputFlag | windowInputFlag)
|
||||
|
||||
ret, _, err := setConsoleMode.Call(term.fd, uintptr(mode))
|
||||
if ret == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return term, nil
|
||||
}
|
||||
|
||||
// Close disables the terminals raw input.
|
||||
func (term *terminal) Close() error {
|
||||
if term.supportsEditing {
|
||||
ret, _, err := setConsoleMode.Call(term.fd, uintptr(term.origMode))
|
||||
if ret == 0 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
23
tools/vendor/github.com/GoASTScanner/gas/Dockerfile
generated
vendored
23
tools/vendor/github.com/GoASTScanner/gas/Dockerfile
generated
vendored
@ -1,23 +0,0 @@
|
||||
# Docker version must be 17.05 or higher to allow multistage build
|
||||
# See build and run instructions in README.md
|
||||
|
||||
# Builds Gas for utilization
|
||||
FROM golang:1.8.1-alpine as builder
|
||||
ENV workspace /go/src/github.com/GoASTScanner/gas
|
||||
ENV GOPATH /go
|
||||
COPY . $workspace
|
||||
WORKDIR $workspace
|
||||
|
||||
RUN go vet $(go list ./... | grep -v /vendor/)
|
||||
RUN CGO_ENABLED=0 go build -o gas .
|
||||
|
||||
########################################################
|
||||
|
||||
# Runs Gas on all Go files in the current directory when
|
||||
# 'docker run' command in README is given
|
||||
FROM alpine:3.6
|
||||
|
||||
COPY --from=builder /go/src/github.com/GoASTScanner/gas/gas /
|
||||
|
||||
# Mounted directory should be placed into the workdir
|
||||
CMD /gas $(find . -path ./vendor -prune -o -type f -name "*.go")
|
154
tools/vendor/github.com/GoASTScanner/gas/LICENSE.txt
generated
vendored
154
tools/vendor/github.com/GoASTScanner/gas/LICENSE.txt
generated
vendored
@ -1,154 +0,0 @@
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this
|
||||
License, each Contributor hereby grants to You a perpetual, worldwide,
|
||||
non-exclusive, no-charge, royalty-free, irrevocable copyright license to
|
||||
reproduce, prepare Derivative Works of, publicly display, publicly perform,
|
||||
sublicense, and distribute the Work and such Derivative Works in Source or
|
||||
Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License,
|
||||
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive,
|
||||
no-charge, royalty-free, irrevocable (except as stated in this section) patent
|
||||
license to make, have made, use, offer to sell, sell, import, and otherwise
|
||||
transfer the Work, where such license applies only to those patent claims
|
||||
licensable by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s) with the Work
|
||||
to which such Contribution(s) was submitted. If You institute patent litigation
|
||||
against any entity (including a cross-claim or counterclaim in a lawsuit)
|
||||
alleging that the Work or a Contribution incorporated within the Work
|
||||
constitutes direct or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate as of the date
|
||||
such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or
|
||||
Derivative Works thereof in any medium, with or without modifications, and in
|
||||
Source or Object form, provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and You must retain, in the Source form of
|
||||
any Derivative Works that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works; and If the Work
|
||||
includes a "NOTICE" text file as part of its distribution, then any Derivative
|
||||
Works that You distribute must include a readable copy of the attribution
|
||||
notices contained within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one of the following
|
||||
places: within a NOTICE text file distributed as part of the Derivative Works;
|
||||
within the Source form or documentation, if provided along with the Derivative
|
||||
Works; or, within a display generated by the Derivative Works, if and wherever
|
||||
such third-party notices normally appear. The contents of the NOTICE file are
|
||||
for informational purposes only and do not modify the License. You may add Your
|
||||
own attribution notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided that such
|
||||
additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License. 5. Submission of Contributions.
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade names,
|
||||
trademarks, service marks, or product names of the Licensor, except as required
|
||||
for reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in
|
||||
writing, Licensor provides the Work (and each Contributor provides its
|
||||
Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied, including, without limitation, any warranties
|
||||
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any risks
|
||||
associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in
|
||||
tort (including negligence), contract, or otherwise, unless required by
|
||||
applicable law (such as deliberate and grossly negligent acts) or agreed to in
|
||||
writing, shall any Contributor be liable to You for damages, including any
|
||||
direct, indirect, special, incidental, or consequential damages of any character
|
||||
arising as a result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill, work stoppage,
|
||||
computer failure or malfunction, or any and all other commercial damages or
|
||||
losses), even if such Contributor has been advised of the possibility of such
|
||||
damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or
|
||||
Derivative Works thereof, You may choose to offer, and charge a fee for,
|
||||
acceptance of support, warranty, indemnity, or other liability obligations
|
||||
and/or rights consistent with this License. However, in accepting such
|
||||
obligations, You may act only on Your own behalf and on Your sole
|
||||
responsibility, not on behalf of any other Contributor, and only if You agree to
|
||||
indemnify, defend, and hold each Contributor harmless for any liability incurred
|
||||
by, or claims asserted against, such Contributor by reason of your accepting any
|
||||
such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
134
tools/vendor/github.com/GoASTScanner/gas/README.md
generated
vendored
134
tools/vendor/github.com/GoASTScanner/gas/README.md
generated
vendored
@ -1,134 +0,0 @@
|
||||
|
||||
|
||||
## GAS - Go AST Scanner
|
||||
|
||||
Inspects source code for security problems by scanning the Go AST.
|
||||
|
||||
### License
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License [here](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
### Project status
|
||||
|
||||
[](https://travis-ci.org/GoASTScanner/gas)
|
||||
[](https://godoc.org/github.com/GoASTScanner/gas)
|
||||
|
||||
Gas is still in alpha and accepting feedback from early adopters. We do
|
||||
not consider it production ready at this time.
|
||||
|
||||
### Install
|
||||
|
||||
`$ go get github.com/GoASTScanner/gas/cmd/gas/...`
|
||||
|
||||
### Usage
|
||||
|
||||
Gas can be configured to only run a subset of rules, to exclude certain file
|
||||
paths, and produce reports in different formats. By default all rules will be
|
||||
run against the supplied input files. To recursively scan from the current
|
||||
directory you can supply './...' as the input argument.
|
||||
|
||||
#### Selecting rules
|
||||
|
||||
By default Gas will run all rules against the supplied file paths. It is however possible to select a subset of rules to run via the '-include=' flag,
|
||||
or to specify a set of rules to explicitly exclude using the '-exclude=' flag.
|
||||
|
||||
##### Available rules
|
||||
|
||||
- G101: Look for hardcoded credentials
|
||||
- G102: Bind to all interfaces
|
||||
- G103: Audit the use of unsafe block
|
||||
- G104: Audit errors not checked
|
||||
- G105: Audit the use of math/big.Int.Exp
|
||||
- G106: Audit the use of ssh.InsecureIgnoreHostKey
|
||||
- G201: SQL query construction using format string
|
||||
- G202: SQL query construction using string concatenation
|
||||
- G203: Use of unescaped data in HTML templates
|
||||
- G204: Audit use of command execution
|
||||
- G301: Poor file permissions used when creating a directory
|
||||
- G302: Poor file permisions used with chmod
|
||||
- G303: Creating tempfile using a predictable path
|
||||
- G401: Detect the usage of DES, RC4, or MD5
|
||||
- G402: Look for bad TLS connection settings
|
||||
- G403: Ensure minimum RSA key length of 2048 bits
|
||||
- G404: Insecure random number source (rand)
|
||||
- G501: Import blacklist: crypto/md5
|
||||
- G502: Import blacklist: crypto/des
|
||||
- G503: Import blacklist: crypto/rc4
|
||||
- G504: Import blacklist: net/http/cgi
|
||||
|
||||
|
||||
```
|
||||
# Run a specific set of rules
|
||||
$ gas -include=G101,G203,G401 ./...
|
||||
|
||||
# Run everything except for rule G303
|
||||
$ gas -exclude=G303 ./...
|
||||
```
|
||||
|
||||
#### Excluding files:
|
||||
|
||||
Gas will ignore dependencies in your vendor directory any files
|
||||
that are not considered build artifacts by the compiler (so test files).
|
||||
|
||||
#### Annotating code
|
||||
|
||||
As with all automated detection tools there will be cases of false positives. In cases where Gas reports a failure that has been manually verified as being safe it is possible to annotate the code with a '#nosec' comment.
|
||||
|
||||
The annotation causes Gas to stop processing any further nodes within the
|
||||
AST so can apply to a whole block or more granularly to a single expression.
|
||||
|
||||
```go
|
||||
|
||||
import "md5" // #nosec
|
||||
|
||||
|
||||
func main(){
|
||||
|
||||
/* #nosec */
|
||||
if x > y {
|
||||
h := md5.New() // this will also be ignored
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
In some cases you may also want to revisit places where #nosec annotations
|
||||
have been used. To run the scanner and ignore any #nosec annotations you
|
||||
can do the following:
|
||||
|
||||
```
|
||||
$ gas -nosec=true ./...
|
||||
```
|
||||
|
||||
### Output formats
|
||||
|
||||
Gas currently supports text, json, yaml, csv and JUnit XML output formats. By default
|
||||
results will be reported to stdout, but can also be written to an output
|
||||
file. The output format is controlled by the '-fmt' flag, and the output file is controlled by the '-out' flag as follows:
|
||||
|
||||
```
|
||||
# Write output in json format to results.json
|
||||
$ gas -fmt=json -out=results.json *.go
|
||||
```
|
||||
|
||||
### Generate TLS rule
|
||||
|
||||
The configuration of TLS rule can be generated from [Mozilla's TLS ciphers recommendation](https://statics.tls.security.mozilla.org/server-side-tls-conf.json).
|
||||
|
||||
|
||||
First you need to install the generator tool:
|
||||
|
||||
```
|
||||
go get github.com/GoASTScanner/gas/cmd/tlsconfig/...
|
||||
```
|
||||
|
||||
You can invoke now the `go generate` in the root of the project:
|
||||
|
||||
```
|
||||
go generate ./...
|
||||
```
|
||||
|
||||
This will generate the `rules/tls_config.go` file with will contain the current ciphers recommendation from Mozilla.
|
197
tools/vendor/github.com/GoASTScanner/gas/analyzer.go
generated
vendored
197
tools/vendor/github.com/GoASTScanner/gas/analyzer.go
generated
vendored
@ -1,197 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package gas holds the central scanning logic used by GAS
|
||||
package gas
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
)
|
||||
|
||||
// The Context is populated with data parsed from the source code as it is scanned.
|
||||
// It is passed through to all rule functions as they are called. Rules may use
|
||||
// this data in conjunction withe the encoutered AST node.
|
||||
type Context struct {
|
||||
FileSet *token.FileSet
|
||||
Comments ast.CommentMap
|
||||
Info *types.Info
|
||||
Pkg *types.Package
|
||||
Root *ast.File
|
||||
Config map[string]interface{}
|
||||
Imports *ImportTracker
|
||||
}
|
||||
|
||||
// Metrics used when reporting information about a scanning run.
|
||||
type Metrics struct {
|
||||
NumFiles int `json:"files"`
|
||||
NumLines int `json:"lines"`
|
||||
NumNosec int `json:"nosec"`
|
||||
NumFound int `json:"found"`
|
||||
}
|
||||
|
||||
// Analyzer object is the main object of GAS. It has methods traverse an AST
|
||||
// and invoke the correct checking rules as on each node as required.
|
||||
type Analyzer struct {
|
||||
ignoreNosec bool
|
||||
ruleset RuleSet
|
||||
context *Context
|
||||
config Config
|
||||
logger *log.Logger
|
||||
issues []*Issue
|
||||
stats *Metrics
|
||||
}
|
||||
|
||||
// NewAnalyzer builds a new anaylzer.
|
||||
func NewAnalyzer(conf Config, logger *log.Logger) *Analyzer {
|
||||
ignoreNoSec := false
|
||||
if setting, err := conf.GetGlobal("nosec"); err == nil {
|
||||
ignoreNoSec = setting == "true" || setting == "enabled"
|
||||
}
|
||||
if logger == nil {
|
||||
logger = log.New(os.Stderr, "[gas]", log.LstdFlags)
|
||||
}
|
||||
return &Analyzer{
|
||||
ignoreNosec: ignoreNoSec,
|
||||
ruleset: make(RuleSet),
|
||||
context: &Context{},
|
||||
config: conf,
|
||||
logger: logger,
|
||||
issues: make([]*Issue, 0, 16),
|
||||
stats: &Metrics{},
|
||||
}
|
||||
}
|
||||
|
||||
// LoadRules instantiates all the rules to be used when analyzing source
|
||||
// packages
|
||||
func (gas *Analyzer) LoadRules(ruleDefinitions ...RuleBuilder) {
|
||||
for _, builder := range ruleDefinitions {
|
||||
r, nodes := builder(gas.config)
|
||||
gas.ruleset.Register(r, nodes...)
|
||||
}
|
||||
}
|
||||
|
||||
// Process kicks off the analysis process for a given package
|
||||
func (gas *Analyzer) Process(packagePaths ...string) error {
|
||||
packageConfig := loader.Config{
|
||||
Build: &build.Default,
|
||||
ParserMode: parser.ParseComments,
|
||||
AllowErrors: true,
|
||||
}
|
||||
for _, packagePath := range packagePaths {
|
||||
abspath, err := filepath.Abs(packagePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
gas.logger.Println("Searching directory:", abspath)
|
||||
|
||||
basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var packageFiles []string
|
||||
for _, filename := range basePackage.GoFiles {
|
||||
packageFiles = append(packageFiles, path.Join(packagePath, filename))
|
||||
}
|
||||
|
||||
packageConfig.CreateFromFilenames(basePackage.Name, packageFiles...)
|
||||
}
|
||||
|
||||
builtPackage, err := packageConfig.Load()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pkg := range builtPackage.Created {
|
||||
gas.logger.Println("Checking package:", pkg.String())
|
||||
for _, file := range pkg.Files {
|
||||
gas.logger.Println("Checking file:", builtPackage.Fset.File(file.Pos()).Name())
|
||||
gas.context.FileSet = builtPackage.Fset
|
||||
gas.context.Config = gas.config
|
||||
gas.context.Comments = ast.NewCommentMap(gas.context.FileSet, file, file.Comments)
|
||||
gas.context.Root = file
|
||||
gas.context.Info = &pkg.Info
|
||||
gas.context.Pkg = pkg.Pkg
|
||||
gas.context.Imports = NewImportTracker()
|
||||
gas.context.Imports.TrackPackages(gas.context.Pkg.Imports()...)
|
||||
ast.Walk(gas, file)
|
||||
gas.stats.NumFiles++
|
||||
gas.stats.NumLines += builtPackage.Fset.File(file.Pos()).LineCount()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ignore a node (and sub-tree) if it is tagged with a "#nosec" comment
|
||||
func (gas *Analyzer) ignore(n ast.Node) bool {
|
||||
if groups, ok := gas.context.Comments[n]; ok && !gas.ignoreNosec {
|
||||
for _, group := range groups {
|
||||
if strings.Contains(group.Text(), "#nosec") {
|
||||
gas.stats.NumNosec++
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Visit runs the GAS visitor logic over an AST created by parsing go code.
|
||||
// Rule methods added with AddRule will be invoked as necessary.
|
||||
func (gas *Analyzer) Visit(n ast.Node) ast.Visitor {
|
||||
if !gas.ignore(n) {
|
||||
|
||||
// Track aliased and initialization imports
|
||||
gas.context.Imports.TrackImport(n)
|
||||
|
||||
for _, rule := range gas.ruleset.RegisteredFor(n) {
|
||||
issue, err := rule.Match(n, gas.context)
|
||||
if err != nil {
|
||||
file, line := GetLocation(n, gas.context)
|
||||
file = path.Base(file)
|
||||
gas.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line)
|
||||
}
|
||||
if issue != nil {
|
||||
gas.issues = append(gas.issues, issue)
|
||||
gas.stats.NumFound++
|
||||
}
|
||||
}
|
||||
return gas
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Report returns the current issues discovered and the metrics about the scan
|
||||
func (gas *Analyzer) Report() ([]*Issue, *Metrics) {
|
||||
return gas.issues, gas.stats
|
||||
}
|
||||
|
||||
// Reset clears state such as context, issues and metrics from the configured analyzer
|
||||
func (gas *Analyzer) Reset() {
|
||||
gas.context = &Context{}
|
||||
gas.issues = make([]*Issue, 0, 16)
|
||||
gas.stats = &Metrics{}
|
||||
}
|
78
tools/vendor/github.com/GoASTScanner/gas/call_list.go
generated
vendored
78
tools/vendor/github.com/GoASTScanner/gas/call_list.go
generated
vendored
@ -1,78 +0,0 @@
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
type set map[string]bool
|
||||
|
||||
// CallList is used to check for usage of specific packages
|
||||
// and functions.
|
||||
type CallList map[string]set
|
||||
|
||||
// NewCallList creates a new empty CallList
|
||||
func NewCallList() CallList {
|
||||
return make(CallList)
|
||||
}
|
||||
|
||||
// AddAll will add several calls to the call list at once
|
||||
func (c CallList) AddAll(selector string, idents ...string) {
|
||||
for _, ident := range idents {
|
||||
c.Add(selector, ident)
|
||||
}
|
||||
}
|
||||
|
||||
// Add a selector and call to the call list
|
||||
func (c CallList) Add(selector, ident string) {
|
||||
if _, ok := c[selector]; !ok {
|
||||
c[selector] = make(set)
|
||||
}
|
||||
c[selector][ident] = true
|
||||
}
|
||||
|
||||
// Contains returns true if the package and function are
|
||||
/// members of this call list.
|
||||
func (c CallList) Contains(selector, ident string) bool {
|
||||
if idents, ok := c[selector]; ok {
|
||||
_, found := idents[ident]
|
||||
return found
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsCallExpr resolves the call expression name and type
|
||||
/// or package and determines if it exists within the CallList
|
||||
func (c CallList) ContainsCallExpr(n ast.Node, ctx *Context) *ast.CallExpr {
|
||||
selector, ident, err := GetCallInfo(n, ctx)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Use only explicit path to reduce conflicts
|
||||
if path, ok := GetImportPath(selector, ctx); ok && c.Contains(path, ident) {
|
||||
return n.(*ast.CallExpr)
|
||||
}
|
||||
|
||||
/*
|
||||
// Try direct resolution
|
||||
if c.Contains(selector, ident) {
|
||||
log.Printf("c.Contains == true, %s, %s.", selector, ident)
|
||||
return n.(*ast.CallExpr)
|
||||
}
|
||||
*/
|
||||
|
||||
return nil
|
||||
}
|
87
tools/vendor/github.com/GoASTScanner/gas/cmd/gas/filelist.go
generated
vendored
87
tools/vendor/github.com/GoASTScanner/gas/cmd/gas/filelist.go
generated
vendored
@ -1,87 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/ryanuber/go-glob"
|
||||
)
|
||||
|
||||
// fileList uses a map for patterns to ensure each pattern only
|
||||
// appears once
|
||||
type fileList struct {
|
||||
patterns map[string]struct{}
|
||||
}
|
||||
|
||||
func newFileList(paths ...string) *fileList {
|
||||
f := &fileList{
|
||||
patterns: make(map[string]struct{}),
|
||||
}
|
||||
for _, p := range paths {
|
||||
f.patterns[p] = struct{}{}
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *fileList) String() string {
|
||||
ps := make([]string, 0, len(f.patterns))
|
||||
for p := range f.patterns {
|
||||
ps = append(ps, p)
|
||||
}
|
||||
sort.Strings(ps)
|
||||
return strings.Join(ps, ", ")
|
||||
}
|
||||
|
||||
func (f *fileList) Set(path string) error {
|
||||
if path == "" {
|
||||
// don't bother adding the empty path
|
||||
return nil
|
||||
}
|
||||
f.patterns[path] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f fileList) Contains(path string) bool {
|
||||
for p := range f.patterns {
|
||||
if strings.Contains(p, glob.GLOB) {
|
||||
if glob.Glob(p, path) {
|
||||
if logger != nil {
|
||||
logger.Printf("skipping: %s\n", path)
|
||||
}
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
// check if only a sub-folder of the path is excluded
|
||||
if strings.Contains(path, p) {
|
||||
if logger != nil {
|
||||
logger.Printf("skipping: %s\n", path)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
func (f fileList) Dump() {
|
||||
for k, _ := range f.paths {
|
||||
println(k)
|
||||
}
|
||||
}
|
||||
*/
|
254
tools/vendor/github.com/GoASTScanner/gas/cmd/gas/main.go
generated
vendored
254
tools/vendor/github.com/GoASTScanner/gas/cmd/gas/main.go
generated
vendored
@ -1,254 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
"github.com/GoASTScanner/gas/output"
|
||||
"github.com/GoASTScanner/gas/rules"
|
||||
"github.com/kisielk/gotool"
|
||||
)
|
||||
|
||||
const (
|
||||
usageText = `
|
||||
GAS - Go AST Scanner
|
||||
|
||||
Gas analyzes Go source code to look for common programming mistakes that
|
||||
can lead to security problems.
|
||||
|
||||
USAGE:
|
||||
|
||||
# Check a single package
|
||||
$ gas $GOPATH/src/github.com/example/project
|
||||
|
||||
# Check all packages under the current directory and save results in
|
||||
# json format.
|
||||
$ gas -fmt=json -out=results.json ./...
|
||||
|
||||
# Run a specific set of rules (by default all rules will be run):
|
||||
$ gas -include=G101,G203,G401 ./...
|
||||
|
||||
# Run all rules except the provided
|
||||
$ gas -exclude=G101 $GOPATH/src/github.com/example/project/...
|
||||
|
||||
`
|
||||
)
|
||||
|
||||
var (
|
||||
// #nosec flag
|
||||
flagIgnoreNoSec = flag.Bool("nosec", false, "Ignores #nosec comments when set")
|
||||
|
||||
// format output
|
||||
flagFormat = flag.String("fmt", "text", "Set output format. Valid options are: json, yaml, csv, junit-xml, html, or text")
|
||||
|
||||
// output file
|
||||
flagOutput = flag.String("out", "", "Set output file for results")
|
||||
|
||||
// config file
|
||||
flagConfig = flag.String("conf", "", "Path to optional config file")
|
||||
|
||||
// quiet
|
||||
flagQuiet = flag.Bool("quiet", false, "Only show output when errors are found")
|
||||
|
||||
// rules to explicitly include
|
||||
flagRulesInclude = flag.String("include", "", "Comma separated list of rules IDs to include. (see rule list)")
|
||||
|
||||
// rules to explicitly exclude
|
||||
flagRulesExclude = flag.String("exclude", "", "Comma separated list of rules IDs to exclude. (see rule list)")
|
||||
|
||||
// log to file or stderr
|
||||
flagLogfile = flag.String("log", "", "Log messages to file rather than stderr")
|
||||
|
||||
// sort the issues by severity
|
||||
flagSortIssues = flag.Bool("sort", true, "Sort issues by severity")
|
||||
|
||||
logger *log.Logger
|
||||
)
|
||||
|
||||
// #nosec
|
||||
func usage() {
|
||||
|
||||
fmt.Fprintln(os.Stderr, usageText)
|
||||
fmt.Fprint(os.Stderr, "OPTIONS:\n\n")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprint(os.Stderr, "\n\nRULES:\n\n")
|
||||
|
||||
// sorted rule list for ease of reading
|
||||
rl := rules.Generate()
|
||||
keys := make([]string, 0, len(rl))
|
||||
for key := range rl {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
for _, k := range keys {
|
||||
v := rl[k]
|
||||
fmt.Fprintf(os.Stderr, "\t%s: %s\n", k, v.Description)
|
||||
}
|
||||
fmt.Fprint(os.Stderr, "\n")
|
||||
}
|
||||
|
||||
func loadConfig(configFile string) (gas.Config, error) {
|
||||
config := gas.NewConfig()
|
||||
if configFile != "" {
|
||||
file, err := os.Open(configFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
if _, err := config.ReadFrom(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if *flagIgnoreNoSec {
|
||||
config.SetGlobal("nosec", "true")
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func loadRules(include, exclude string) rules.RuleList {
|
||||
var filters []rules.RuleFilter
|
||||
if include != "" {
|
||||
logger.Printf("including rules: %s", include)
|
||||
including := strings.Split(include, ",")
|
||||
filters = append(filters, rules.NewRuleFilter(false, including...))
|
||||
} else {
|
||||
logger.Println("including rules: default")
|
||||
}
|
||||
|
||||
if exclude != "" {
|
||||
logger.Printf("excluding rules: %s", exclude)
|
||||
excluding := strings.Split(exclude, ",")
|
||||
filters = append(filters, rules.NewRuleFilter(true, excluding...))
|
||||
} else {
|
||||
logger.Println("excluding rules: default")
|
||||
}
|
||||
return rules.Generate(filters...)
|
||||
}
|
||||
|
||||
func saveOutput(filename, format string, issues []*gas.Issue, metrics *gas.Metrics) error {
|
||||
if filename != "" {
|
||||
outfile, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outfile.Close()
|
||||
err = output.CreateReport(outfile, format, issues, metrics)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
err := output.CreateReport(os.Stdout, format, issues, metrics)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
// Setup usage description
|
||||
flag.Usage = usage
|
||||
|
||||
// Parse command line arguments
|
||||
flag.Parse()
|
||||
|
||||
// Ensure at least one file was specified
|
||||
if flag.NArg() == 0 {
|
||||
fmt.Fprintf(os.Stderr, "\nError: FILE [FILE...] or './...' expected\n") // #nosec
|
||||
flag.Usage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Setup logging
|
||||
logWriter := os.Stderr
|
||||
if *flagLogfile != "" {
|
||||
var e error
|
||||
logWriter, e = os.Create(*flagLogfile)
|
||||
if e != nil {
|
||||
flag.Usage()
|
||||
log.Fatal(e)
|
||||
}
|
||||
}
|
||||
logger = log.New(logWriter, "[gas] ", log.LstdFlags)
|
||||
|
||||
// Load config
|
||||
config, err := loadConfig(*flagConfig)
|
||||
if err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
// Load enabled rule definitions
|
||||
ruleDefinitions := loadRules(*flagRulesInclude, *flagRulesExclude)
|
||||
if len(ruleDefinitions) <= 0 {
|
||||
logger.Fatal("cannot continue: no rules are configured.")
|
||||
}
|
||||
|
||||
// Create the analyzer
|
||||
analyzer := gas.NewAnalyzer(config, logger)
|
||||
analyzer.LoadRules(ruleDefinitions.Builders()...)
|
||||
|
||||
vendor := regexp.MustCompile(`[\\/]vendor([\\/]|$)`)
|
||||
|
||||
var packages []string
|
||||
// Iterate over packages on the import paths
|
||||
for _, pkg := range gotool.ImportPaths(flag.Args()) {
|
||||
|
||||
// Skip vendor directory
|
||||
if vendor.MatchString(pkg) {
|
||||
continue
|
||||
}
|
||||
packages = append(packages, pkg)
|
||||
}
|
||||
|
||||
if err := analyzer.Process(packages...); err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
// Collect the results
|
||||
issues, metrics := analyzer.Report()
|
||||
|
||||
issuesFound := len(issues) > 0
|
||||
// Exit quietly if nothing was found
|
||||
if !issuesFound && *flagQuiet {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// Sort the issue by severity
|
||||
if *flagSortIssues {
|
||||
sortIssues(issues)
|
||||
}
|
||||
|
||||
// Create output report
|
||||
if err := saveOutput(*flagOutput, *flagFormat, issues, metrics); err != nil {
|
||||
logger.Fatal(err)
|
||||
}
|
||||
|
||||
// Finialize logging
|
||||
logWriter.Close() // #nosec
|
||||
|
||||
// Do we have an issue? If so exit 1
|
||||
if issuesFound {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
20
tools/vendor/github.com/GoASTScanner/gas/cmd/gas/sort_issues.go
generated
vendored
20
tools/vendor/github.com/GoASTScanner/gas/cmd/gas/sort_issues.go
generated
vendored
@ -1,20 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type sortBySeverity []*gas.Issue
|
||||
|
||||
func (s sortBySeverity) Len() int { return len(s) }
|
||||
|
||||
func (s sortBySeverity) Less(i, j int) bool { return s[i].Severity > s[i].Severity }
|
||||
|
||||
func (s sortBySeverity) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// sortIssues sorts the issues by severity in descending order
|
||||
func sortIssues(issues []*gas.Issue) {
|
||||
sort.Sort(sortBySeverity(issues))
|
||||
}
|
88
tools/vendor/github.com/GoASTScanner/gas/config.go
generated
vendored
88
tools/vendor/github.com/GoASTScanner/gas/config.go
generated
vendored
@ -1,88 +0,0 @@
|
||||
package gas
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
const (
|
||||
// Globals are applicable to all rules and used for general
|
||||
// configuration settings for gas.
|
||||
Globals = "global"
|
||||
)
|
||||
|
||||
// Config is used to provide configuration and customization to each of the rules.
|
||||
type Config map[string]interface{}
|
||||
|
||||
// NewConfig initializes a new configuration instance. The configuration data then
|
||||
// needs to be loaded via c.ReadFrom(strings.NewReader("config data"))
|
||||
// or from a *os.File.
|
||||
func NewConfig() Config {
|
||||
cfg := make(Config)
|
||||
cfg[Globals] = make(map[string]string)
|
||||
return cfg
|
||||
}
|
||||
|
||||
// ReadFrom implements the io.ReaderFrom interface. This
|
||||
// should be used with io.Reader to load configuration from
|
||||
//file or from string etc.
|
||||
func (c Config) ReadFrom(r io.Reader) (int64, error) {
|
||||
data, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return int64(len(data)), err
|
||||
}
|
||||
if err = json.Unmarshal(data, &c); err != nil {
|
||||
return int64(len(data)), err
|
||||
}
|
||||
return int64(len(data)), nil
|
||||
}
|
||||
|
||||
// WriteTo implements the io.WriteTo interface. This should
|
||||
// be used to save or print out the configuration information.
|
||||
func (c Config) WriteTo(w io.Writer) (int64, error) {
|
||||
data, err := json.Marshal(c)
|
||||
if err != nil {
|
||||
return int64(len(data)), err
|
||||
}
|
||||
return io.Copy(w, bytes.NewReader(data))
|
||||
}
|
||||
|
||||
// Get returns the configuration section for the supplied key
|
||||
func (c Config) Get(section string) (interface{}, error) {
|
||||
settings, found := c[section]
|
||||
if !found {
|
||||
return nil, fmt.Errorf("Section %s not in configuration", section)
|
||||
}
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// Set section in the configuration to specified value
|
||||
func (c Config) Set(section string, value interface{}) {
|
||||
c[section] = value
|
||||
}
|
||||
|
||||
// GetGlobal returns value associated with global configuration option
|
||||
func (c Config) GetGlobal(option string) (string, error) {
|
||||
if globals, ok := c[Globals]; ok {
|
||||
if settings, ok := globals.(map[string]string); ok {
|
||||
if value, ok := settings[option]; ok {
|
||||
return value, nil
|
||||
}
|
||||
return "", fmt.Errorf("global setting for %s not found", option)
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no global config options found")
|
||||
|
||||
}
|
||||
|
||||
// SetGlobal associates a value with a global configuration ooption
|
||||
func (c Config) SetGlobal(option, value string) {
|
||||
if globals, ok := c[Globals]; ok {
|
||||
if settings, ok := globals.(map[string]string); ok {
|
||||
settings[option] = value
|
||||
}
|
||||
}
|
||||
}
|
195
tools/vendor/github.com/GoASTScanner/gas/helpers.go
generated
vendored
195
tools/vendor/github.com/GoASTScanner/gas/helpers.go
generated
vendored
@ -1,195 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// MatchCallByPackage ensures that the specified package is imported,
|
||||
// adjusts the name for any aliases and ignores cases that are
|
||||
// initialization only imports.
|
||||
//
|
||||
// Usage:
|
||||
// node, matched := MatchCallByPackage(n, ctx, "math/rand", "Read")
|
||||
//
|
||||
func MatchCallByPackage(n ast.Node, c *Context, pkg string, names ...string) (*ast.CallExpr, bool) {
|
||||
|
||||
importedName, found := GetImportedName(pkg, c)
|
||||
if !found {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if callExpr, ok := n.(*ast.CallExpr); ok {
|
||||
packageName, callName, err := GetCallInfo(callExpr, c)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
if packageName == importedName {
|
||||
for _, name := range names {
|
||||
if callName == name {
|
||||
return callExpr, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// MatchCallByType ensures that the node is a call expression to a
|
||||
// specific object type.
|
||||
//
|
||||
// Usage:
|
||||
// node, matched := MatchCallByType(n, ctx, "bytes.Buffer", "WriteTo", "Write")
|
||||
//
|
||||
func MatchCallByType(n ast.Node, ctx *Context, requiredType string, calls ...string) (*ast.CallExpr, bool) {
|
||||
if callExpr, ok := n.(*ast.CallExpr); ok {
|
||||
typeName, callName, err := GetCallInfo(callExpr, ctx)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
if typeName == requiredType {
|
||||
for _, call := range calls {
|
||||
if call == callName {
|
||||
return callExpr, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// MatchCompLit will match an ast.CompositeLit based on the supplied type
|
||||
func MatchCompLit(n ast.Node, ctx *Context, required string) *ast.CompositeLit {
|
||||
if complit, ok := n.(*ast.CompositeLit); ok {
|
||||
typeOf := ctx.Info.TypeOf(complit)
|
||||
if typeOf.String() == required {
|
||||
return complit
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInt will read and return an integer value from an ast.BasicLit
|
||||
func GetInt(n ast.Node) (int64, error) {
|
||||
if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.INT {
|
||||
return strconv.ParseInt(node.Value, 0, 64)
|
||||
}
|
||||
return 0, fmt.Errorf("Unexpected AST node type: %T", n)
|
||||
}
|
||||
|
||||
// GetFloat will read and return a float value from an ast.BasicLit
|
||||
func GetFloat(n ast.Node) (float64, error) {
|
||||
if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.FLOAT {
|
||||
return strconv.ParseFloat(node.Value, 64)
|
||||
}
|
||||
return 0.0, fmt.Errorf("Unexpected AST node type: %T", n)
|
||||
}
|
||||
|
||||
// GetChar will read and return a char value from an ast.BasicLit
|
||||
func GetChar(n ast.Node) (byte, error) {
|
||||
if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.CHAR {
|
||||
return node.Value[0], nil
|
||||
}
|
||||
return 0, fmt.Errorf("Unexpected AST node type: %T", n)
|
||||
}
|
||||
|
||||
// GetString will read and return a string value from an ast.BasicLit
|
||||
func GetString(n ast.Node) (string, error) {
|
||||
if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.STRING {
|
||||
return strconv.Unquote(node.Value)
|
||||
}
|
||||
return "", fmt.Errorf("Unexpected AST node type: %T", n)
|
||||
}
|
||||
|
||||
// GetCallObject returns the object and call expression and associated
|
||||
// object for a given AST node. nil, nil will be returned if the
|
||||
// object cannot be resolved.
|
||||
func GetCallObject(n ast.Node, ctx *Context) (*ast.CallExpr, types.Object) {
|
||||
switch node := n.(type) {
|
||||
case *ast.CallExpr:
|
||||
switch fn := node.Fun.(type) {
|
||||
case *ast.Ident:
|
||||
return node, ctx.Info.Uses[fn]
|
||||
case *ast.SelectorExpr:
|
||||
return node, ctx.Info.Uses[fn.Sel]
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetCallInfo returns the package or type and name associated with a
|
||||
// call expression.
|
||||
func GetCallInfo(n ast.Node, ctx *Context) (string, string, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.CallExpr:
|
||||
switch fn := node.Fun.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
switch expr := fn.X.(type) {
|
||||
case *ast.Ident:
|
||||
if expr.Obj != nil && expr.Obj.Kind == ast.Var {
|
||||
t := ctx.Info.TypeOf(expr)
|
||||
if t != nil {
|
||||
return t.String(), fn.Sel.Name, nil
|
||||
}
|
||||
return "undefined", fn.Sel.Name, fmt.Errorf("missing type info")
|
||||
}
|
||||
return expr.Name, fn.Sel.Name, nil
|
||||
}
|
||||
case *ast.Ident:
|
||||
return ctx.Pkg.Name(), fn.Name, nil
|
||||
}
|
||||
}
|
||||
return "", "", fmt.Errorf("unable to determine call info")
|
||||
}
|
||||
|
||||
// GetImportedName returns the name used for the package within the
|
||||
// code. It will resolve aliases and ignores initalization only imports.
|
||||
func GetImportedName(path string, ctx *Context) (string, bool) {
|
||||
importName, imported := ctx.Imports.Imported[path]
|
||||
if !imported {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if _, initonly := ctx.Imports.InitOnly[path]; initonly {
|
||||
return "", false
|
||||
}
|
||||
|
||||
if alias, ok := ctx.Imports.Aliased[path]; ok {
|
||||
importName = alias
|
||||
}
|
||||
return importName, true
|
||||
}
|
||||
|
||||
// GetImportPath resolves the full import path of an identifer based on
|
||||
// the imports in the current context.
|
||||
func GetImportPath(name string, ctx *Context) (string, bool) {
|
||||
for path := range ctx.Imports.Imported {
|
||||
if imported, ok := GetImportedName(path, ctx); ok && imported == name {
|
||||
return path, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// GetLocation returns the filename and line number of an ast.Node
|
||||
func GetLocation(n ast.Node, ctx *Context) (string, int) {
|
||||
fobj := ctx.FileSet.File(n.Pos())
|
||||
return fobj.Name(), fobj.Line(n.Pos())
|
||||
}
|
67
tools/vendor/github.com/GoASTScanner/gas/import_tracker.go
generated
vendored
67
tools/vendor/github.com/GoASTScanner/gas/import_tracker.go
generated
vendored
@ -1,67 +0,0 @@
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ImportTracker is used to normalize the packages that have been imported
|
||||
// by a source file. It is able to differentiate between plain imports, aliased
|
||||
// imports and init only imports.
|
||||
type ImportTracker struct {
|
||||
Imported map[string]string
|
||||
Aliased map[string]string
|
||||
InitOnly map[string]bool
|
||||
}
|
||||
|
||||
// NewImportTracker creates an empty Import tracker instance
|
||||
func NewImportTracker() *ImportTracker {
|
||||
return &ImportTracker{
|
||||
make(map[string]string),
|
||||
make(map[string]string),
|
||||
make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// TrackPackages tracks all the imports used by the supplied packages
|
||||
func (t *ImportTracker) TrackPackages(pkgs ...*types.Package) {
|
||||
for _, pkg := range pkgs {
|
||||
t.Imported[pkg.Path()] = pkg.Name()
|
||||
// Transient imports
|
||||
//for _, imp := range pkg.Imports() {
|
||||
// t.Imported[imp.Path()] = imp.Name()
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
// TrackImport tracks imports and handles the 'unsafe' import
|
||||
func (t *ImportTracker) TrackImport(n ast.Node) {
|
||||
if imported, ok := n.(*ast.ImportSpec); ok {
|
||||
path := strings.Trim(imported.Path.Value, `"`)
|
||||
if imported.Name != nil {
|
||||
if imported.Name.Name == "_" {
|
||||
// Initialization only import
|
||||
t.InitOnly[path] = true
|
||||
} else {
|
||||
// Aliased import
|
||||
t.Aliased[path] = imported.Name.Name
|
||||
}
|
||||
}
|
||||
if path == "unsafe" {
|
||||
t.Imported[path] = path
|
||||
}
|
||||
}
|
||||
}
|
118
tools/vendor/github.com/GoASTScanner/gas/issue.go
generated
vendored
118
tools/vendor/github.com/GoASTScanner/gas/issue.go
generated
vendored
@ -1,118 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Score type used by severity and confidence values
|
||||
type Score int
|
||||
|
||||
const (
|
||||
// Low severity or confidence
|
||||
Low Score = iota
|
||||
// Medium severity or confidence
|
||||
Medium
|
||||
// High severity or confidence
|
||||
High
|
||||
)
|
||||
|
||||
// Issue is returnd by a GAS rule if it discovers an issue with the scanned code.
|
||||
type Issue struct {
|
||||
Severity Score `json:"severity"` // issue severity (how problematic it is)
|
||||
Confidence Score `json:"confidence"` // issue confidence (how sure we are we found it)
|
||||
What string `json:"details"` // Human readable explanation
|
||||
File string `json:"file"` // File name we found it in
|
||||
Code string `json:"code"` // Impacted code line
|
||||
Line string `json:"line"` // Line number in file
|
||||
}
|
||||
|
||||
// MetaData is embedded in all GAS rules. The Severity, Confidence and What message
|
||||
// will be passed tbhrough to reported issues.
|
||||
type MetaData struct {
|
||||
Severity Score
|
||||
Confidence Score
|
||||
What string
|
||||
}
|
||||
|
||||
// MarshalJSON is used convert a Score object into a JSON representation
|
||||
func (c Score) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(c.String())
|
||||
}
|
||||
|
||||
// String converts a Score into a string
|
||||
func (c Score) String() string {
|
||||
switch c {
|
||||
case High:
|
||||
return "HIGH"
|
||||
case Medium:
|
||||
return "MEDIUM"
|
||||
case Low:
|
||||
return "LOW"
|
||||
}
|
||||
return "UNDEFINED"
|
||||
}
|
||||
|
||||
func codeSnippet(file *os.File, start int64, end int64, n ast.Node) (string, error) {
|
||||
if n == nil {
|
||||
return "", fmt.Errorf("Invalid AST node provided")
|
||||
}
|
||||
|
||||
size := (int)(end - start) // Go bug, os.File.Read should return int64 ...
|
||||
file.Seek(start, 0) // #nosec
|
||||
|
||||
buf := make([]byte, size)
|
||||
if nread, err := file.Read(buf); err != nil || nread != size {
|
||||
return "", fmt.Errorf("Unable to read code")
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
// NewIssue creates a new Issue
|
||||
func NewIssue(ctx *Context, node ast.Node, desc string, severity Score, confidence Score) *Issue {
|
||||
var code string
|
||||
fobj := ctx.FileSet.File(node.Pos())
|
||||
name := fobj.Name()
|
||||
|
||||
start, end := fobj.Line(node.Pos()), fobj.Line(node.End())
|
||||
line := strconv.Itoa(start)
|
||||
if start != end {
|
||||
line = fmt.Sprintf("%d-%d", start, end)
|
||||
}
|
||||
|
||||
if file, err := os.Open(fobj.Name()); err == nil {
|
||||
defer file.Close()
|
||||
s := (int64)(fobj.Position(node.Pos()).Offset) // Go bug, should be int64
|
||||
e := (int64)(fobj.Position(node.End()).Offset) // Go bug, should be int64
|
||||
code, err = codeSnippet(file, s, e, node)
|
||||
if err != nil {
|
||||
code = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return &Issue{
|
||||
File: name,
|
||||
Line: line,
|
||||
What: desc,
|
||||
Confidence: confidence,
|
||||
Severity: severity,
|
||||
Code: code,
|
||||
}
|
||||
}
|
168
tools/vendor/github.com/GoASTScanner/gas/output/formatter.go
generated
vendored
168
tools/vendor/github.com/GoASTScanner/gas/output/formatter.go
generated
vendored
@ -1,168 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package output
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
htmlTemplate "html/template"
|
||||
"io"
|
||||
plainTemplate "text/template"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// ReportFormat enumrates the output format for reported issues
|
||||
type ReportFormat int
|
||||
|
||||
const (
|
||||
// ReportText is the default format that writes to stdout
|
||||
ReportText ReportFormat = iota // Plain text format
|
||||
|
||||
// ReportJSON set the output format to json
|
||||
ReportJSON // Json format
|
||||
|
||||
// ReportCSV set the output format to csv
|
||||
ReportCSV // CSV format
|
||||
|
||||
// ReportJUnitXML set the output format to junit xml
|
||||
ReportJUnitXML // JUnit XML format
|
||||
)
|
||||
|
||||
var text = `Results:
|
||||
{{ range $index, $issue := .Issues }}
|
||||
[{{ $issue.File }}:{{ $issue.Line }}] - {{ $issue.What }} (Confidence: {{ $issue.Confidence}}, Severity: {{ $issue.Severity }})
|
||||
> {{ $issue.Code }}
|
||||
|
||||
{{ end }}
|
||||
Summary:
|
||||
Files: {{.Stats.NumFiles}}
|
||||
Lines: {{.Stats.NumLines}}
|
||||
Nosec: {{.Stats.NumNosec}}
|
||||
Issues: {{.Stats.NumFound}}
|
||||
|
||||
`
|
||||
|
||||
type reportInfo struct {
|
||||
Issues []*gas.Issue
|
||||
Stats *gas.Metrics
|
||||
}
|
||||
|
||||
// CreateReport generates a report based for the supplied issues and metrics given
|
||||
// the specified format. The formats currently accepted are: json, csv, html and text.
|
||||
func CreateReport(w io.Writer, format string, issues []*gas.Issue, metrics *gas.Metrics) error {
|
||||
data := &reportInfo{
|
||||
Issues: issues,
|
||||
Stats: metrics,
|
||||
}
|
||||
var err error
|
||||
switch format {
|
||||
case "json":
|
||||
err = reportJSON(w, data)
|
||||
case "yaml":
|
||||
err = reportYAML(w, data)
|
||||
case "csv":
|
||||
err = reportCSV(w, data)
|
||||
case "junit-xml":
|
||||
err = reportJUnitXML(w, data)
|
||||
case "html":
|
||||
err = reportFromHTMLTemplate(w, html, data)
|
||||
case "text":
|
||||
err = reportFromPlaintextTemplate(w, text, data)
|
||||
default:
|
||||
err = reportFromPlaintextTemplate(w, text, data)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func reportJSON(w io.Writer, data *reportInfo) error {
|
||||
raw, err := json.MarshalIndent(data, "", "\t")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = w.Write(raw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func reportYAML(w io.Writer, data *reportInfo) error {
|
||||
raw, err := yaml.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = w.Write(raw)
|
||||
return err
|
||||
}
|
||||
|
||||
func reportCSV(w io.Writer, data *reportInfo) error {
|
||||
out := csv.NewWriter(w)
|
||||
defer out.Flush()
|
||||
for _, issue := range data.Issues {
|
||||
err := out.Write([]string{
|
||||
issue.File,
|
||||
issue.Line,
|
||||
issue.What,
|
||||
issue.Severity.String(),
|
||||
issue.Confidence.String(),
|
||||
issue.Code,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func reportJUnitXML(w io.Writer, data *reportInfo) error {
|
||||
groupedData := groupDataByRules(data)
|
||||
junitXMLStruct := createJUnitXMLStruct(groupedData)
|
||||
|
||||
raw, err := xml.MarshalIndent(junitXMLStruct, "", "\t")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
xmlHeader := []byte("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
|
||||
raw = append(xmlHeader, raw...)
|
||||
_, err = w.Write(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func reportFromPlaintextTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
|
||||
t, e := plainTemplate.New("gas").Parse(reportTemplate)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
return t.Execute(w, data)
|
||||
}
|
||||
|
||||
func reportFromHTMLTemplate(w io.Writer, reportTemplate string, data *reportInfo) error {
|
||||
t, e := htmlTemplate.New("gas").Parse(reportTemplate)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
return t.Execute(w, data)
|
||||
}
|
74
tools/vendor/github.com/GoASTScanner/gas/output/junit_xml_format.go
generated
vendored
74
tools/vendor/github.com/GoASTScanner/gas/output/junit_xml_format.go
generated
vendored
@ -1,74 +0,0 @@
|
||||
package output
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
htmlLib "html"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type junitXMLReport struct {
|
||||
XMLName xml.Name `xml:"testsuites"`
|
||||
Testsuites []testsuite `xml:"testsuite"`
|
||||
}
|
||||
|
||||
type testsuite struct {
|
||||
XMLName xml.Name `xml:"testsuite"`
|
||||
Name string `xml:"name,attr"`
|
||||
Tests int `xml:"tests,attr"`
|
||||
Testcases []testcase `xml:"testcase"`
|
||||
}
|
||||
|
||||
type testcase struct {
|
||||
XMLName xml.Name `xml:"testcase"`
|
||||
Name string `xml:"name,attr"`
|
||||
Failure failure `xml:"failure"`
|
||||
}
|
||||
|
||||
type failure struct {
|
||||
XMLName xml.Name `xml:"failure"`
|
||||
Message string `xml:"message,attr"`
|
||||
Text string `xml:",innerxml"`
|
||||
}
|
||||
|
||||
func generatePlaintext(issue *gas.Issue) string {
|
||||
return "Results:\n" +
|
||||
"[" + issue.File + ":" + issue.Line + "] - " +
|
||||
issue.What + " (Confidence: " + strconv.Itoa(int(issue.Confidence)) +
|
||||
", Severity: " + strconv.Itoa(int(issue.Severity)) + ")\n" + "> " + htmlLib.EscapeString(issue.Code)
|
||||
}
|
||||
|
||||
func groupDataByRules(data *reportInfo) map[string][]*gas.Issue {
|
||||
groupedData := make(map[string][]*gas.Issue)
|
||||
for _, issue := range data.Issues {
|
||||
if _, ok := groupedData[issue.What]; ok {
|
||||
groupedData[issue.What] = append(groupedData[issue.What], issue)
|
||||
} else {
|
||||
groupedData[issue.What] = []*gas.Issue{issue}
|
||||
}
|
||||
}
|
||||
return groupedData
|
||||
}
|
||||
|
||||
func createJUnitXMLStruct(groupedData map[string][]*gas.Issue) junitXMLReport {
|
||||
var xmlReport junitXMLReport
|
||||
for what, issues := range groupedData {
|
||||
testsuite := testsuite{
|
||||
Name: what,
|
||||
Tests: len(issues),
|
||||
}
|
||||
for _, issue := range issues {
|
||||
testcase := testcase{
|
||||
Name: issue.File,
|
||||
Failure: failure{
|
||||
Message: "Found 1 vulnerability. See stacktrace for details.",
|
||||
Text: generatePlaintext(issue),
|
||||
},
|
||||
}
|
||||
testsuite.Testcases = append(testsuite.Testcases, testcase)
|
||||
}
|
||||
xmlReport.Testsuites = append(xmlReport.Testsuites, testsuite)
|
||||
}
|
||||
return xmlReport
|
||||
}
|
401
tools/vendor/github.com/GoASTScanner/gas/output/template.go
generated
vendored
401
tools/vendor/github.com/GoASTScanner/gas/output/template.go
generated
vendored
@ -1,401 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package output
|
||||
|
||||
const html = `
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Go AST Scanner</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.1/css/bulma.min.css" integrity="sha256-DRcOKg8NK1KkSkcymcGmxOtS/lAn0lHWJXRa15gMHHk=" crossorigin="anonymous"/>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.min.js" integrity="sha256-cLWs9L+cjZg8CjGHMpJqUgKKouPlmoMP/0wIdPtaPGs=" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.min.js" integrity="sha256-JIW8lNqN2EtqC6ggNZYnAdKMJXRQfkPMvdRt+b0/Jxc=" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.17.0/babel.min.js" integrity="sha256-1IWWLlCKFGFj/cjryvC7GDF5wRYnf9tSvNVVEj8Bm+o=" crossorigin="anonymous"></script>
|
||||
<style>
|
||||
div.issue div.tag, div.panel-block input[type="checkbox"] {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
label.disabled {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
nav.panel select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.break-word {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div id="content"></div>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
var data = {{ . }};
|
||||
</script>
|
||||
<script type="text/babel">
|
||||
var IssueTag = React.createClass({
|
||||
render: function() {
|
||||
var level = ""
|
||||
if (this.props.level === "HIGH") {
|
||||
level = "is-danger";
|
||||
}
|
||||
if (this.props.level === "MEDIUM") {
|
||||
level = "is-warning";
|
||||
}
|
||||
return (
|
||||
<div className={ "tag " + level }>
|
||||
{ this.props.label }: { this.props.level }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Issue = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="issue box">
|
||||
<div className="is-pulled-right">
|
||||
<IssueTag label="Severity" level={ this.props.data.severity }/>
|
||||
<IssueTag label="Confidence" level={ this.props.data.confidence }/>
|
||||
</div>
|
||||
<p>
|
||||
<strong className="break-word">
|
||||
{ this.props.data.file } (line { this.props.data.line })
|
||||
</strong>
|
||||
<br/>
|
||||
{ this.props.data.details }
|
||||
</p>
|
||||
<figure className="highlight">
|
||||
<pre>
|
||||
<code className="golang hljs">
|
||||
{ this.props.data.code }
|
||||
</code>
|
||||
</pre>
|
||||
</figure>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Stats = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<p className="help">
|
||||
Scanned { this.props.data.metrics.files.toLocaleString() } files
|
||||
with { this.props.data.metrics.lines.toLocaleString() } lines of code.
|
||||
</p>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Issues = React.createClass({
|
||||
render: function() {
|
||||
if (this.props.data.metrics.files === 0) {
|
||||
return (
|
||||
<div className="notification">
|
||||
No source files found. Do you even Go?
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.data.issues.length === 0) {
|
||||
return (
|
||||
<div>
|
||||
<div className="notification">
|
||||
Awesome! No issues found!
|
||||
</div>
|
||||
<Stats data={ this.props.data } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
var issues = this.props.data.issues
|
||||
.filter(function(issue) {
|
||||
return this.props.severity.includes(issue.severity);
|
||||
}.bind(this))
|
||||
.filter(function(issue) {
|
||||
return this.props.confidence.includes(issue.confidence);
|
||||
}.bind(this))
|
||||
.filter(function(issue) {
|
||||
if (this.props.issueType) {
|
||||
return issue.details.toLowerCase().startsWith(this.props.issueType.toLowerCase());
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}.bind(this))
|
||||
.map(function(issue) {
|
||||
return (<Issue data={issue} />);
|
||||
}.bind(this));
|
||||
|
||||
if (issues.length === 0) {
|
||||
return (
|
||||
<div>
|
||||
<div className="notification">
|
||||
No issues matched given filters
|
||||
(of total { this.props.data.issues.length } issues).
|
||||
</div>
|
||||
<Stats data={ this.props.data } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="issues">
|
||||
{ issues }
|
||||
<Stats data={ this.props.data } />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var LevelSelector = React.createClass({
|
||||
handleChange: function(level) {
|
||||
return function(e) {
|
||||
var updated = this.props.selected
|
||||
.filter(function(item) { return item != level; });
|
||||
if (e.target.checked) {
|
||||
updated.push(level);
|
||||
}
|
||||
this.props.onChange(updated);
|
||||
}.bind(this);
|
||||
},
|
||||
render: function() {
|
||||
var highDisabled = !this.props.available.includes("HIGH");
|
||||
var mediumDisabled = !this.props.available.includes("MEDIUM");
|
||||
var lowDisabled = !this.props.available.includes("LOW");
|
||||
|
||||
return (
|
||||
<span>
|
||||
<label className={"label checkbox " + (highDisabled ? "disabled" : "") }>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={ this.props.selected.includes("HIGH") }
|
||||
disabled={ highDisabled }
|
||||
onChange={ this.handleChange("HIGH") }/>
|
||||
High
|
||||
</label>
|
||||
<label className={"label checkbox " + (mediumDisabled ? "disabled" : "") }>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={ this.props.selected.includes("MEDIUM") }
|
||||
disabled={ mediumDisabled }
|
||||
onChange={ this.handleChange("MEDIUM") }/>
|
||||
Medium
|
||||
</label>
|
||||
<label className={"label checkbox " + (lowDisabled ? "disabled" : "") }>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={ this.props.selected.includes("LOW") }
|
||||
disabled={ lowDisabled }
|
||||
onChange={ this.handleChange("LOW") }/>
|
||||
Low
|
||||
</label>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var Navigation = React.createClass({
|
||||
updateSeverity: function(vals) {
|
||||
this.props.onSeverity(vals);
|
||||
},
|
||||
updateConfidence: function(vals) {
|
||||
this.props.onConfidence(vals);
|
||||
},
|
||||
updateIssueType: function(e) {
|
||||
if (e.target.value == "all") {
|
||||
this.props.onIssueType(null);
|
||||
} else {
|
||||
this.props.onIssueType(e.target.value);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var issueTypes = this.props.allIssueTypes
|
||||
.map(function(it) {
|
||||
return (
|
||||
<option value={ it } selected={ this.props.issueType == it }>
|
||||
{ it }
|
||||
</option>
|
||||
);
|
||||
}.bind(this));
|
||||
|
||||
return (
|
||||
<nav className="panel">
|
||||
<div className="panel-heading">
|
||||
Filters
|
||||
</div>
|
||||
<div className="panel-block">
|
||||
<strong>
|
||||
Severity
|
||||
</strong>
|
||||
</div>
|
||||
<div className="panel-block">
|
||||
<LevelSelector
|
||||
selected={ this.props.severity }
|
||||
available={ this.props.allSeverities }
|
||||
onChange={ this.updateSeverity } />
|
||||
</div>
|
||||
<div className="panel-block">
|
||||
<strong>
|
||||
Confidence
|
||||
</strong>
|
||||
</div>
|
||||
<div className="panel-block">
|
||||
<LevelSelector
|
||||
selected={ this.props.confidence }
|
||||
available={ this.props.allConfidences }
|
||||
onChange={ this.updateConfidence } />
|
||||
</div>
|
||||
<div className="panel-block">
|
||||
<strong>
|
||||
Issue Type
|
||||
</strong>
|
||||
</div>
|
||||
<div className="panel-block">
|
||||
<select onChange={ this.updateIssueType }>
|
||||
<option value="all" selected={ !this.props.issueType }>
|
||||
(all)
|
||||
</option>
|
||||
{ issueTypes }
|
||||
</select>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var IssueBrowser = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.updateIssues(this.props.data);
|
||||
},
|
||||
handleSeverity: function(val) {
|
||||
this.updateIssueTypes(this.props.data.issues, val, this.state.confidence);
|
||||
this.setState({severity: val});
|
||||
},
|
||||
handleConfidence: function(val) {
|
||||
this.updateIssueTypes(this.props.data.issues, this.state.severity, val);
|
||||
this.setState({confidence: val});
|
||||
},
|
||||
handleIssueType: function(val) {
|
||||
this.setState({issueType: val});
|
||||
},
|
||||
updateIssues: function(data) {
|
||||
if (!data) {
|
||||
this.setState({data: data});
|
||||
return;
|
||||
}
|
||||
|
||||
var allSeverities = data.issues
|
||||
.map(function(issue) {
|
||||
return issue.severity
|
||||
})
|
||||
.sort()
|
||||
.filter(function(item, pos, ary) {
|
||||
return !pos || item != ary[pos - 1];
|
||||
});
|
||||
|
||||
var allConfidences = data.issues
|
||||
.map(function(issue) {
|
||||
return issue.confidence
|
||||
})
|
||||
.sort()
|
||||
.filter(function(item, pos, ary) {
|
||||
return !pos || item != ary[pos - 1];
|
||||
});
|
||||
|
||||
var selectedSeverities = allSeverities;
|
||||
var selectedConfidences = allConfidences;
|
||||
|
||||
this.updateIssueTypes(data.issues, selectedSeverities, selectedConfidences);
|
||||
|
||||
this.setState({
|
||||
data: data,
|
||||
severity: selectedSeverities,
|
||||
allSeverities: allSeverities,
|
||||
confidence: selectedConfidences,
|
||||
allConfidences: allConfidences,
|
||||
issueType: null
|
||||
});
|
||||
},
|
||||
updateIssueTypes: function(issues, severities, confidences) {
|
||||
var allTypes = issues
|
||||
.filter(function(issue) {
|
||||
return severities.includes(issue.severity);
|
||||
})
|
||||
.filter(function(issue) {
|
||||
return confidences.includes(issue.confidence);
|
||||
})
|
||||
.map(function(issue) {
|
||||
return issue.details;
|
||||
})
|
||||
.sort()
|
||||
.filter(function(item, pos, ary) {
|
||||
return !pos || item != ary[pos - 1];
|
||||
});
|
||||
|
||||
if (this.state.issueType && !allTypes.includes(this.state.issueType)) {
|
||||
this.setState({issueType: null});
|
||||
}
|
||||
|
||||
this.setState({allIssueTypes: allTypes});
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div className="content">
|
||||
<div className="columns">
|
||||
<div className="column is-one-quarter">
|
||||
<Navigation
|
||||
severity={ this.state.severity }
|
||||
confidence={ this.state.confidence }
|
||||
issueType={ this.state.issueType }
|
||||
allSeverities={ this.state.allSeverities }
|
||||
allConfidences={ this.state.allConfidences }
|
||||
allIssueTypes={ this.state.allIssueTypes }
|
||||
onSeverity={ this.handleSeverity }
|
||||
onConfidence={ this.handleConfidence }
|
||||
onIssueType={ this.handleIssueType }
|
||||
/>
|
||||
</div>
|
||||
<div className="column is-three-quarters">
|
||||
<Issues
|
||||
data={ this.props.data }
|
||||
severity={ this.state.severity }
|
||||
confidence={ this.state.confidence }
|
||||
issueType={ this.state.issueType }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<IssueBrowser data={ data } />,
|
||||
document.getElementById("content")
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>`
|
82
tools/vendor/github.com/GoASTScanner/gas/resolve.go
generated
vendored
82
tools/vendor/github.com/GoASTScanner/gas/resolve.go
generated
vendored
@ -1,82 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
|
||||
import "go/ast"
|
||||
|
||||
func resolveIdent(n *ast.Ident, c *Context) bool {
|
||||
|
||||
if n.Obj == nil || n.Obj.Kind != ast.Var {
|
||||
return true
|
||||
}
|
||||
if node, ok := n.Obj.Decl.(ast.Node); ok {
|
||||
return TryResolve(node, c)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func resolveAssign(n *ast.AssignStmt, c *Context) bool {
|
||||
for _, arg := range n.Rhs {
|
||||
if !TryResolve(arg, c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func resolveCompLit(n *ast.CompositeLit, c *Context) bool {
|
||||
for _, arg := range n.Elts {
|
||||
if !TryResolve(arg, c) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func resolveBinExpr(n *ast.BinaryExpr, c *Context) bool {
|
||||
return (TryResolve(n.X, c) && TryResolve(n.Y, c))
|
||||
}
|
||||
|
||||
func resolveCallExpr(n *ast.CallExpr, c *Context) bool {
|
||||
// TODO(tkelsey): next step, full function resolution
|
||||
return false
|
||||
}
|
||||
|
||||
// TryResolve will attempt, given a subtree starting at some ATS node, to resolve
|
||||
// all values contained within to a known constant. It is used to check for any
|
||||
// unkown values in compound expressions.
|
||||
func TryResolve(n ast.Node, c *Context) bool {
|
||||
switch node := n.(type) {
|
||||
case *ast.BasicLit:
|
||||
return true
|
||||
|
||||
case *ast.CompositeLit:
|
||||
return resolveCompLit(node, c)
|
||||
|
||||
case *ast.Ident:
|
||||
return resolveIdent(node, c)
|
||||
|
||||
case *ast.AssignStmt:
|
||||
return resolveAssign(node, c)
|
||||
|
||||
case *ast.CallExpr:
|
||||
return resolveCallExpr(node, c)
|
||||
|
||||
case *ast.BinaryExpr:
|
||||
return resolveBinExpr(node, c)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
58
tools/vendor/github.com/GoASTScanner/gas/rule.go
generated
vendored
58
tools/vendor/github.com/GoASTScanner/gas/rule.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gas
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// The Rule interface used by all rules supported by GAS.
|
||||
type Rule interface {
|
||||
Match(ast.Node, *Context) (*Issue, error)
|
||||
}
|
||||
|
||||
// RuleBuilder is used to register a rule definition with the analyzer
|
||||
type RuleBuilder func(c Config) (Rule, []ast.Node)
|
||||
|
||||
// A RuleSet maps lists of rules to the type of AST node they should be run on.
|
||||
// The anaylzer will only invoke rules contained in the list associated with the
|
||||
// type of AST node it is currently visiting.
|
||||
type RuleSet map[reflect.Type][]Rule
|
||||
|
||||
// NewRuleSet constructs a new RuleSet
|
||||
func NewRuleSet() RuleSet {
|
||||
return make(RuleSet)
|
||||
}
|
||||
|
||||
// Register adds a trigger for the supplied rule for the the
|
||||
// specified ast nodes.
|
||||
func (r RuleSet) Register(rule Rule, nodes ...ast.Node) {
|
||||
for _, n := range nodes {
|
||||
t := reflect.TypeOf(n)
|
||||
if rules, ok := r[t]; ok {
|
||||
r[t] = append(rules, rule)
|
||||
} else {
|
||||
r[t] = []Rule{rule}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RegisteredFor will return all rules that are registered for a
|
||||
// specified ast node.
|
||||
func (r RuleSet) RegisteredFor(n ast.Node) []Rule {
|
||||
if rules, found := r[reflect.TypeOf(n)]; found {
|
||||
return rules
|
||||
}
|
||||
return []Rule{}
|
||||
}
|
47
tools/vendor/github.com/GoASTScanner/gas/rules/big.go
generated
vendored
47
tools/vendor/github.com/GoASTScanner/gas/rules/big.go
generated
vendored
@ -1,47 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type usingBigExp struct {
|
||||
gas.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (r *usingBigExp) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if _, matched := gas.MatchCallByType(n, c, r.pkg, r.calls...); matched {
|
||||
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsingBigExp detects issues with modulus == 0 for Bignum
|
||||
func NewUsingBigExp(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &usingBigExp{
|
||||
pkg: "*math/big.Int",
|
||||
calls: []string{"Exp"},
|
||||
MetaData: gas.MetaData{
|
||||
What: "Use of math/big.Int.Exp function should be audited for modulus == 0",
|
||||
Severity: gas.Low,
|
||||
Confidence: gas.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
59
tools/vendor/github.com/GoASTScanner/gas/rules/bind.go
generated
vendored
59
tools/vendor/github.com/GoASTScanner/gas/rules/bind.go
generated
vendored
@ -1,59 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
// Looks for net.Listen("0.0.0.0") or net.Listen(":8080")
|
||||
type bindsToAllNetworkInterfaces struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
|
||||
func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
callExpr := r.calls.ContainsCallExpr(n, c)
|
||||
if callExpr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if arg, err := gas.GetString(callExpr.Args[1]); err == nil {
|
||||
if r.pattern.MatchString(arg) {
|
||||
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewBindsToAllNetworkInterfaces detects socket connections that are setup to
|
||||
// listen on all network interfaces.
|
||||
func NewBindsToAllNetworkInterfaces(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
calls.Add("net", "Listen")
|
||||
calls.Add("crypto/tls", "Listen")
|
||||
return &bindsToAllNetworkInterfaces{
|
||||
calls: calls,
|
||||
pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`),
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: "Binds to all network interfaces",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
82
tools/vendor/github.com/GoASTScanner/gas/rules/blacklist.go
generated
vendored
82
tools/vendor/github.com/GoASTScanner/gas/rules/blacklist.go
generated
vendored
@ -1,82 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strings"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type blacklistedImport struct {
|
||||
gas.MetaData
|
||||
Blacklisted map[string]string
|
||||
}
|
||||
|
||||
func unquote(original string) string {
|
||||
copy := strings.TrimSpace(original)
|
||||
copy = strings.TrimLeft(copy, `"`)
|
||||
return strings.TrimRight(copy, `"`)
|
||||
}
|
||||
|
||||
func (r *blacklistedImport) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if node, ok := n.(*ast.ImportSpec); ok {
|
||||
if description, ok := r.Blacklisted[unquote(node.Path.Value)]; ok {
|
||||
return gas.NewIssue(c, node, description, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewBlacklistedImports reports when a blacklisted import is being used.
|
||||
// Typically when a deprecated technology is being used.
|
||||
func NewBlacklistedImports(conf gas.Config, blacklist map[string]string) (gas.Rule, []ast.Node) {
|
||||
return &blacklistedImport{
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
},
|
||||
Blacklisted: blacklist,
|
||||
}, []ast.Node{(*ast.ImportSpec)(nil)}
|
||||
}
|
||||
|
||||
// NewBlacklistedImportMD5 fails if MD5 is imported
|
||||
func NewBlacklistedImportMD5(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(conf, map[string]string{
|
||||
"crypto/md5": "Blacklisted import crypto/md5: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlacklistedImportDES fails if DES is imported
|
||||
func NewBlacklistedImportDES(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(conf, map[string]string{
|
||||
"crypto/des": "Blacklisted import crypto/des: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlacklistedImportRC4 fails if DES is imported
|
||||
func NewBlacklistedImportRC4(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(conf, map[string]string{
|
||||
"crypto/rc4": "Blacklisted import crypto/rc4: weak cryptographic primitive",
|
||||
})
|
||||
}
|
||||
|
||||
// NewBlacklistedImportCGI fails if CGI is imported
|
||||
func NewBlacklistedImportCGI(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return NewBlacklistedImports(conf, map[string]string{
|
||||
"net/http/cgi": "Blacklisted import net/http/cgi: Go versions < 1.6.3 are vulnerable to Httpoxy attack: (CVE-2016-5386)",
|
||||
})
|
||||
}
|
98
tools/vendor/github.com/GoASTScanner/gas/rules/errors.go
generated
vendored
98
tools/vendor/github.com/GoASTScanner/gas/rules/errors.go
generated
vendored
@ -1,98 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type noErrorCheck struct {
|
||||
gas.MetaData
|
||||
whitelist gas.CallList
|
||||
}
|
||||
|
||||
func returnsError(callExpr *ast.CallExpr, ctx *gas.Context) int {
|
||||
if tv := ctx.Info.TypeOf(callExpr); tv != nil {
|
||||
switch t := tv.(type) {
|
||||
case *types.Tuple:
|
||||
for pos := 0; pos < t.Len(); pos++ {
|
||||
variable := t.At(pos)
|
||||
if variable != nil && variable.Type().String() == "error" {
|
||||
return pos
|
||||
}
|
||||
}
|
||||
case *types.Named:
|
||||
if t.String() == "error" {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (r *noErrorCheck) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
||||
switch stmt := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, expr := range stmt.Rhs {
|
||||
if callExpr, ok := expr.(*ast.CallExpr); ok && r.whitelist.ContainsCallExpr(expr, ctx) == nil {
|
||||
pos := returnsError(callExpr, ctx)
|
||||
if pos < 0 || pos >= len(stmt.Lhs) {
|
||||
return nil, nil
|
||||
}
|
||||
if id, ok := stmt.Lhs[pos].(*ast.Ident); ok && id.Name == "_" {
|
||||
return gas.NewIssue(ctx, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
case *ast.ExprStmt:
|
||||
if callExpr, ok := stmt.X.(*ast.CallExpr); ok && r.whitelist.ContainsCallExpr(stmt.X, ctx) == nil {
|
||||
pos := returnsError(callExpr, ctx)
|
||||
if pos >= 0 {
|
||||
return gas.NewIssue(ctx, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewNoErrorCheck detects if the returned error is unchecked
|
||||
func NewNoErrorCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
|
||||
// TODO(gm) Come up with sensible defaults here. Or flip it to use a
|
||||
// black list instead.
|
||||
whitelist := gas.NewCallList()
|
||||
whitelist.AddAll("bytes.Buffer", "Write", "WriteByte", "WriteRune", "WriteString")
|
||||
whitelist.AddAll("fmt", "Print", "Printf", "Println", "Fprint", "Fprintf", "Fprintln")
|
||||
whitelist.Add("io.PipeWriter", "CloseWithError")
|
||||
|
||||
if configured, ok := conf["G104"]; ok {
|
||||
if whitelisted, ok := configured.(map[string][]string); ok {
|
||||
for key, val := range whitelisted {
|
||||
whitelist.AddAll(key, val...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &noErrorCheck{
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Low,
|
||||
Confidence: gas.High,
|
||||
What: "Errors unhandled.",
|
||||
},
|
||||
whitelist: whitelist,
|
||||
}, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ExprStmt)(nil)}
|
||||
}
|
89
tools/vendor/github.com/GoASTScanner/gas/rules/fileperms.go
generated
vendored
89
tools/vendor/github.com/GoASTScanner/gas/rules/fileperms.go
generated
vendored
@ -1,89 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type filePermissions struct {
|
||||
gas.MetaData
|
||||
mode int64
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
||||
func getConfiguredMode(conf map[string]interface{}, configKey string, defaultMode int64) int64 {
|
||||
var mode = defaultMode
|
||||
if value, ok := conf[configKey]; ok {
|
||||
switch value.(type) {
|
||||
case int64:
|
||||
mode = value.(int64)
|
||||
case string:
|
||||
if m, e := strconv.ParseInt(value.(string), 0, 64); e != nil {
|
||||
mode = defaultMode
|
||||
} else {
|
||||
mode = m
|
||||
}
|
||||
}
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
func (r *filePermissions) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if callexpr, matched := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matched {
|
||||
modeArg := callexpr.Args[len(callexpr.Args)-1]
|
||||
if mode, err := gas.GetInt(modeArg); err == nil && mode > r.mode {
|
||||
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewFilePerms creates a rule to detect file creation with a more permissive than configured
|
||||
// permission mask.
|
||||
func NewFilePerms(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
mode := getConfiguredMode(conf, "G302", 0600)
|
||||
return &filePermissions{
|
||||
mode: mode,
|
||||
pkg: "os",
|
||||
calls: []string{"OpenFile", "Chmod"},
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: fmt.Sprintf("Expect file permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
||||
// NewMkdirPerms creates a rule to detect directory creation with more permissive than
|
||||
// configured permission mask.
|
||||
func NewMkdirPerms(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
mode := getConfiguredMode(conf, "G301", 0750)
|
||||
return &filePermissions{
|
||||
mode: mode,
|
||||
pkg: "os",
|
||||
calls: []string{"Mkdir", "MkdirAll"},
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: fmt.Sprintf("Expect directory permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
150
tools/vendor/github.com/GoASTScanner/gas/rules/hardcoded_credentials.go
generated
vendored
150
tools/vendor/github.com/GoASTScanner/gas/rules/hardcoded_credentials.go
generated
vendored
@ -1,150 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
"github.com/nbutton23/zxcvbn-go"
|
||||
)
|
||||
|
||||
type credentials struct {
|
||||
gas.MetaData
|
||||
pattern *regexp.Regexp
|
||||
entropyThreshold float64
|
||||
perCharThreshold float64
|
||||
truncate int
|
||||
ignoreEntropy bool
|
||||
}
|
||||
|
||||
func truncate(s string, n int) string {
|
||||
if n > len(s) {
|
||||
return s
|
||||
}
|
||||
return s[:n]
|
||||
}
|
||||
|
||||
func (r *credentials) isHighEntropyString(str string) bool {
|
||||
s := truncate(str, r.truncate)
|
||||
info := zxcvbn.PasswordStrength(s, []string{})
|
||||
entropyPerChar := info.Entropy / float64(len(s))
|
||||
return (info.Entropy >= r.entropyThreshold ||
|
||||
(info.Entropy >= (r.entropyThreshold/2) &&
|
||||
entropyPerChar >= r.perCharThreshold))
|
||||
}
|
||||
|
||||
func (r *credentials) Match(n ast.Node, ctx *gas.Context) (*gas.Issue, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
return r.matchAssign(node, ctx)
|
||||
case *ast.GenDecl:
|
||||
return r.matchGenDecl(node, ctx)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gas.Context) (*gas.Issue, error) {
|
||||
for _, i := range assign.Lhs {
|
||||
if ident, ok := i.(*ast.Ident); ok {
|
||||
if r.pattern.MatchString(ident.Name) {
|
||||
for _, e := range assign.Rhs {
|
||||
if val, err := gas.GetString(e); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gas.NewIssue(ctx, assign, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchGenDecl(decl *ast.GenDecl, ctx *gas.Context) (*gas.Issue, error) {
|
||||
if decl.Tok != token.CONST && decl.Tok != token.VAR {
|
||||
return nil, nil
|
||||
}
|
||||
for _, spec := range decl.Specs {
|
||||
if valueSpec, ok := spec.(*ast.ValueSpec); ok {
|
||||
for index, ident := range valueSpec.Names {
|
||||
if r.pattern.MatchString(ident.Name) && valueSpec.Values != nil {
|
||||
// const foo, bar = "same value"
|
||||
if len(valueSpec.Values) <= index {
|
||||
index = len(valueSpec.Values) - 1
|
||||
}
|
||||
if val, err := gas.GetString(valueSpec.Values[index]); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gas.NewIssue(ctx, valueSpec, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewHardcodedCredentials attempts to find high entropy string constants being
|
||||
// assigned to variables that appear to be related to credentials.
|
||||
func NewHardcodedCredentials(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
pattern := `(?i)passwd|pass|password|pwd|secret|token`
|
||||
entropyThreshold := 80.0
|
||||
perCharThreshold := 3.0
|
||||
ignoreEntropy := false
|
||||
var truncateString = 16
|
||||
if val, ok := conf["G101"]; ok {
|
||||
conf := val.(map[string]string)
|
||||
if configPattern, ok := conf["pattern"]; ok {
|
||||
pattern = configPattern
|
||||
}
|
||||
if configIgnoreEntropy, ok := conf["ignore_entropy"]; ok {
|
||||
if parsedBool, err := strconv.ParseBool(configIgnoreEntropy); err == nil {
|
||||
ignoreEntropy = parsedBool
|
||||
}
|
||||
}
|
||||
if configEntropyThreshold, ok := conf["entropy_threshold"]; ok {
|
||||
if parsedNum, err := strconv.ParseFloat(configEntropyThreshold, 64); err == nil {
|
||||
entropyThreshold = parsedNum
|
||||
}
|
||||
}
|
||||
if configCharThreshold, ok := conf["per_char_threshold"]; ok {
|
||||
if parsedNum, err := strconv.ParseFloat(configCharThreshold, 64); err == nil {
|
||||
perCharThreshold = parsedNum
|
||||
}
|
||||
}
|
||||
if configTruncate, ok := conf["truncate"]; ok {
|
||||
if parsedInt, err := strconv.Atoi(configTruncate); err == nil {
|
||||
truncateString = parsedInt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &credentials{
|
||||
pattern: regexp.MustCompile(pattern),
|
||||
entropyThreshold: entropyThreshold,
|
||||
perCharThreshold: perCharThreshold,
|
||||
ignoreEntropy: ignoreEntropy,
|
||||
truncate: truncateString,
|
||||
MetaData: gas.MetaData{
|
||||
What: "Potential hardcoded credentials",
|
||||
Confidence: gas.Low,
|
||||
Severity: gas.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.AssignStmt)(nil), (*ast.GenDecl)(nil)}
|
||||
}
|
50
tools/vendor/github.com/GoASTScanner/gas/rules/rand.go
generated
vendored
50
tools/vendor/github.com/GoASTScanner/gas/rules/rand.go
generated
vendored
@ -1,50 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type weakRand struct {
|
||||
gas.MetaData
|
||||
funcNames []string
|
||||
packagePath string
|
||||
}
|
||||
|
||||
func (w *weakRand) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
for _, funcName := range w.funcNames {
|
||||
if _, matched := gas.MatchCallByPackage(n, c, w.packagePath, funcName); matched {
|
||||
return gas.NewIssue(c, n, w.What, w.Severity, w.Confidence), nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure
|
||||
func NewWeakRandCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &weakRand{
|
||||
funcNames: []string{"Read", "Int"},
|
||||
packagePath: "math/rand",
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.High,
|
||||
Confidence: gas.Medium,
|
||||
What: "Use of weak random number generator (math/rand instead of crypto/rand)",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
53
tools/vendor/github.com/GoASTScanner/gas/rules/rsa.go
generated
vendored
53
tools/vendor/github.com/GoASTScanner/gas/rules/rsa.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type weakKeyStrength struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
bits int
|
||||
}
|
||||
|
||||
func (w *weakKeyStrength) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if callExpr := w.calls.ContainsCallExpr(n, c); callExpr != nil {
|
||||
if bits, err := gas.GetInt(callExpr.Args[1]); err == nil && bits < (int64)(w.bits) {
|
||||
return gas.NewIssue(c, n, w.What, w.Severity, w.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewWeakKeyStrength builds a rule that detects RSA keys < 2048 bits
|
||||
func NewWeakKeyStrength(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
calls.Add("crypto/rsa", "GenerateKey")
|
||||
bits := 2048
|
||||
return &weakKeyStrength{
|
||||
calls: calls,
|
||||
bits: bits,
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: fmt.Sprintf("RSA keys should be at least %d bits", bits),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
102
tools/vendor/github.com/GoASTScanner/gas/rules/rulelist.go
generated
vendored
102
tools/vendor/github.com/GoASTScanner/gas/rules/rulelist.go
generated
vendored
@ -1,102 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
// RuleDefinition contains the description of a rule and a mechanism to
|
||||
// create it.
|
||||
type RuleDefinition struct {
|
||||
Description string
|
||||
Create gas.RuleBuilder
|
||||
}
|
||||
|
||||
// RuleList is a mapping of rule ID's to rule definitions
|
||||
type RuleList map[string]RuleDefinition
|
||||
|
||||
// Builders returns all the create methods for a given rule list
|
||||
func (rl RuleList) Builders() []gas.RuleBuilder {
|
||||
builders := make([]gas.RuleBuilder, 0, len(rl))
|
||||
for _, def := range rl {
|
||||
builders = append(builders, def.Create)
|
||||
}
|
||||
return builders
|
||||
}
|
||||
|
||||
// RuleFilter can be used to include or exclude a rule depending on the return
|
||||
// value of the function
|
||||
type RuleFilter func(string) bool
|
||||
|
||||
// NewRuleFilter is a closure that will include/exclude the rule ID's based on
|
||||
// the supplied boolean value.
|
||||
func NewRuleFilter(action bool, ruleIDs ...string) RuleFilter {
|
||||
rulelist := make(map[string]bool)
|
||||
for _, rule := range ruleIDs {
|
||||
rulelist[rule] = true
|
||||
}
|
||||
return func(rule string) bool {
|
||||
if _, found := rulelist[rule]; found {
|
||||
return action
|
||||
}
|
||||
return !action
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the list of rules to use
|
||||
func Generate(filters ...RuleFilter) RuleList {
|
||||
rules := map[string]RuleDefinition{
|
||||
// misc
|
||||
"G101": {"Look for hardcoded credentials", NewHardcodedCredentials},
|
||||
"G102": {"Bind to all interfaces", NewBindsToAllNetworkInterfaces},
|
||||
"G103": {"Audit the use of unsafe block", NewUsingUnsafe},
|
||||
"G104": {"Audit errors not checked", NewNoErrorCheck},
|
||||
"G105": {"Audit the use of big.Exp function", NewUsingBigExp},
|
||||
"G106": {"Audit the use of ssh.InsecureIgnoreHostKey function", NewSSHHostKey},
|
||||
|
||||
// injection
|
||||
"G201": {"SQL query construction using format string", NewSQLStrFormat},
|
||||
"G202": {"SQL query construction using string concatenation", NewSQLStrConcat},
|
||||
"G203": {"Use of unescaped data in HTML templates", NewTemplateCheck},
|
||||
"G204": {"Audit use of command execution", NewSubproc},
|
||||
|
||||
// filesystem
|
||||
"G301": {"Poor file permissions used when creating a directory", NewMkdirPerms},
|
||||
"G302": {"Poor file permisions used when creation file or using chmod", NewFilePerms},
|
||||
"G303": {"Creating tempfile using a predictable path", NewBadTempFile},
|
||||
|
||||
// crypto
|
||||
"G401": {"Detect the usage of DES, RC4, or MD5", NewUsesWeakCryptography},
|
||||
"G402": {"Look for bad TLS connection settings", NewIntermediateTLSCheck},
|
||||
"G403": {"Ensure minimum RSA key length of 2048 bits", NewWeakKeyStrength},
|
||||
"G404": {"Insecure random number source (rand)", NewWeakRandCheck},
|
||||
|
||||
// blacklist
|
||||
"G501": {"Import blacklist: crypto/md5", NewBlacklistedImportMD5},
|
||||
"G502": {"Import blacklist: crypto/des", NewBlacklistedImportDES},
|
||||
"G503": {"Import blacklist: crypto/rc4", NewBlacklistedImportRC4},
|
||||
"G504": {"Import blacklist: net/http/cgi", NewBlacklistedImportCGI},
|
||||
}
|
||||
|
||||
for rule := range rules {
|
||||
for _, filter := range filters {
|
||||
if filter(rule) {
|
||||
delete(rules, rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
return rules
|
||||
}
|
125
tools/vendor/github.com/GoASTScanner/gas/rules/sql.go
generated
vendored
125
tools/vendor/github.com/GoASTScanner/gas/rules/sql.go
generated
vendored
@ -1,125 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type sqlStatement struct {
|
||||
gas.MetaData
|
||||
|
||||
// Contains a list of patterns which must all match for the rule to match.
|
||||
patterns []*regexp.Regexp
|
||||
}
|
||||
|
||||
// See if the string matches the patterns for the statement.
|
||||
func (s sqlStatement) MatchPatterns(str string) bool {
|
||||
for _, pattern := range s.patterns {
|
||||
if !pattern.MatchString(str) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type sqlStrConcat struct {
|
||||
sqlStatement
|
||||
}
|
||||
|
||||
// see if we can figure out what it is
|
||||
func (s *sqlStrConcat) checkObject(n *ast.Ident) bool {
|
||||
if n.Obj != nil {
|
||||
return n.Obj.Kind != ast.Var && n.Obj.Kind != ast.Fun
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Look for "SELECT * FROM table WHERE " + " ' OR 1=1"
|
||||
func (s *sqlStrConcat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if node, ok := n.(*ast.BinaryExpr); ok {
|
||||
if start, ok := node.X.(*ast.BasicLit); ok {
|
||||
if str, e := gas.GetString(start); e == nil {
|
||||
if !s.MatchPatterns(str) {
|
||||
return nil, nil
|
||||
}
|
||||
if _, ok := node.Y.(*ast.BasicLit); ok {
|
||||
return nil, nil // string cat OK
|
||||
}
|
||||
if second, ok := node.Y.(*ast.Ident); ok && s.checkObject(second) {
|
||||
return nil, nil
|
||||
}
|
||||
return gas.NewIssue(c, n, s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSQLStrConcat looks for cases where we are building SQL strings via concatenation
|
||||
func NewSQLStrConcat(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &sqlStrConcat{
|
||||
sqlStatement: sqlStatement{
|
||||
patterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `),
|
||||
},
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: "SQL string concatenation",
|
||||
},
|
||||
},
|
||||
}, []ast.Node{(*ast.BinaryExpr)(nil)}
|
||||
}
|
||||
|
||||
type sqlStrFormat struct {
|
||||
sqlStatement
|
||||
calls gas.CallList
|
||||
}
|
||||
|
||||
// Looks for "fmt.Sprintf("SELECT * FROM foo where '%s', userInput)"
|
||||
func (s *sqlStrFormat) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
|
||||
// TODO(gm) improve confidence if database/sql is being used
|
||||
if node := s.calls.ContainsCallExpr(n, c); node != nil {
|
||||
if arg, e := gas.GetString(node.Args[0]); s.MatchPatterns(arg) && e == nil {
|
||||
return gas.NewIssue(c, n, s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSQLStrFormat looks for cases where we're building SQL query strings using format strings
|
||||
func NewSQLStrFormat(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
rule := &sqlStrFormat{
|
||||
calls: gas.NewCallList(),
|
||||
sqlStatement: sqlStatement{
|
||||
patterns: []*regexp.Regexp{
|
||||
regexp.MustCompile("(?)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) "),
|
||||
regexp.MustCompile("%[^bdoxXfFp]"),
|
||||
},
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: "SQL string formatting",
|
||||
},
|
||||
},
|
||||
}
|
||||
rule.calls.AddAll("fmt", "Sprint", "Sprintf", "Sprintln")
|
||||
return rule, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
33
tools/vendor/github.com/GoASTScanner/gas/rules/ssh.go
generated
vendored
33
tools/vendor/github.com/GoASTScanner/gas/rules/ssh.go
generated
vendored
@ -1,33 +0,0 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type sshHostKey struct {
|
||||
gas.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (r *sshHostKey) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if _, matches := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSSHHostKey rule detects the use of insecure ssh HostKeyCallback.
|
||||
func NewSSHHostKey(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &sshHostKey{
|
||||
pkg: "golang.org/x/crypto/ssh",
|
||||
calls: []string{"InsecureIgnoreHostKey"},
|
||||
MetaData: gas.MetaData{
|
||||
What: "Use of ssh InsecureIgnoreHostKey should be audited",
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
58
tools/vendor/github.com/GoASTScanner/gas/rules/subproc.go
generated
vendored
58
tools/vendor/github.com/GoASTScanner/gas/rules/subproc.go
generated
vendored
@ -1,58 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type subprocess struct {
|
||||
gas.CallList
|
||||
}
|
||||
|
||||
// TODO(gm) The only real potential for command injection with a Go project
|
||||
// is something like this:
|
||||
//
|
||||
// syscall.Exec("/bin/sh", []string{"-c", tainted})
|
||||
//
|
||||
// E.g. Input is correctly escaped but the execution context being used
|
||||
// is unsafe. For example:
|
||||
//
|
||||
// syscall.Exec("echo", "foobar" + tainted)
|
||||
func (r *subprocess) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if node := r.ContainsCallExpr(n, c); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
if ident, ok := arg.(*ast.Ident); ok {
|
||||
obj := c.Info.ObjectOf(ident)
|
||||
if _, ok := obj.(*types.Var); ok && !gas.TryResolve(ident, c) {
|
||||
return gas.NewIssue(c, n, "Subprocess launched with variable", gas.Medium, gas.High), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return gas.NewIssue(c, n, "Subprocess launching should be audited", gas.Low, gas.High), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSubproc detects cases where we are forking out to an external process
|
||||
func NewSubproc(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
rule := &subprocess{gas.NewCallList()}
|
||||
rule.Add("os/exec", "Command")
|
||||
rule.Add("syscall", "Exec")
|
||||
return rule, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
53
tools/vendor/github.com/GoASTScanner/gas/rules/tempfiles.go
generated
vendored
53
tools/vendor/github.com/GoASTScanner/gas/rules/tempfiles.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"regexp"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type badTempFile struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
args *regexp.Regexp
|
||||
}
|
||||
|
||||
func (t *badTempFile) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if node := t.calls.ContainsCallExpr(n, c); node != nil {
|
||||
if arg, e := gas.GetString(node.Args[0]); t.args.MatchString(arg) && e == nil {
|
||||
return gas.NewIssue(c, n, t.What, t.Severity, t.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewBadTempFile detects direct writes to predictable path in temporary directory
|
||||
func NewBadTempFile(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := gas.NewCallList()
|
||||
calls.Add("io/ioutil", "WriteFile")
|
||||
calls.Add("os", "Create")
|
||||
return &badTempFile{
|
||||
calls: calls,
|
||||
args: regexp.MustCompile(`^/tmp/.*$|^/var/tmp/.*$`),
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: "File creation in shared tmp directory without using ioutil.Tempfile",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
56
tools/vendor/github.com/GoASTScanner/gas/rules/templates.go
generated
vendored
56
tools/vendor/github.com/GoASTScanner/gas/rules/templates.go
generated
vendored
@ -1,56 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type templateCheck struct {
|
||||
gas.MetaData
|
||||
calls gas.CallList
|
||||
}
|
||||
|
||||
func (t *templateCheck) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if node := t.calls.ContainsCallExpr(n, c); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
if _, ok := arg.(*ast.BasicLit); !ok { // basic lits are safe
|
||||
return gas.NewIssue(c, n, t.What, t.Severity, t.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewTemplateCheck constructs the template check rule. This rule is used to
|
||||
// find use of tempaltes where HTML/JS escaping is not being used
|
||||
func NewTemplateCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
|
||||
calls := gas.NewCallList()
|
||||
calls.Add("html/template", "HTML")
|
||||
calls.Add("html/template", "HTMLAttr")
|
||||
calls.Add("html/template", "JS")
|
||||
calls.Add("html/template", "URL")
|
||||
return &templateCheck{
|
||||
calls: calls,
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.Low,
|
||||
What: "this method will not auto-escape HTML. Verify data is well formed.",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
125
tools/vendor/github.com/GoASTScanner/gas/rules/tls.go
generated
vendored
125
tools/vendor/github.com/GoASTScanner/gas/rules/tls.go
generated
vendored
@ -1,125 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:generate tlsconfig
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type insecureConfigTLS struct {
|
||||
MinVersion int16
|
||||
MaxVersion int16
|
||||
requiredType string
|
||||
goodCiphers []string
|
||||
}
|
||||
|
||||
func stringInSlice(a string, list []string) bool {
|
||||
for _, b := range list {
|
||||
if b == a {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gas.Context) *gas.Issue {
|
||||
|
||||
if ciphers, ok := n.(*ast.CompositeLit); ok {
|
||||
for _, cipher := range ciphers.Elts {
|
||||
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
||||
if !stringInSlice(ident.Sel.Name, t.goodCiphers) {
|
||||
err := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name)
|
||||
return gas.NewIssue(c, ident, err, gas.High, gas.High)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gas.Context) *gas.Issue {
|
||||
if ident, ok := n.Key.(*ast.Ident); ok {
|
||||
switch ident.Name {
|
||||
|
||||
case "InsecureSkipVerify":
|
||||
if node, ok := n.Value.(*ast.Ident); ok {
|
||||
if node.Name != "false" {
|
||||
return gas.NewIssue(c, n, "TLS InsecureSkipVerify set true.", gas.High, gas.High)
|
||||
}
|
||||
} else {
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, "TLS InsecureSkipVerify may be true.", gas.High, gas.Low)
|
||||
}
|
||||
|
||||
case "PreferServerCipherSuites":
|
||||
if node, ok := n.Value.(*ast.Ident); ok {
|
||||
if node.Name == "false" {
|
||||
return gas.NewIssue(c, n, "TLS PreferServerCipherSuites set false.", gas.Medium, gas.High)
|
||||
}
|
||||
} else {
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, "TLS PreferServerCipherSuites may be false.", gas.Medium, gas.Low)
|
||||
}
|
||||
|
||||
case "MinVersion":
|
||||
if ival, ierr := gas.GetInt(n.Value); ierr == nil {
|
||||
if (int16)(ival) < t.MinVersion {
|
||||
return gas.NewIssue(c, n, "TLS MinVersion too low.", gas.High, gas.High)
|
||||
}
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, "TLS MinVersion may be too low.", gas.High, gas.Low)
|
||||
}
|
||||
|
||||
case "MaxVersion":
|
||||
if ival, ierr := gas.GetInt(n.Value); ierr == nil {
|
||||
if (int16)(ival) < t.MaxVersion {
|
||||
return gas.NewIssue(c, n, "TLS MaxVersion too low.", gas.High, gas.High)
|
||||
}
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gas.NewIssue(c, n, "TLS MaxVersion may be too low.", gas.High, gas.Low)
|
||||
}
|
||||
|
||||
case "CipherSuites":
|
||||
if ret := t.processTLSCipherSuites(n.Value, c); ret != nil {
|
||||
return ret
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
|
||||
actualType := c.Info.TypeOf(complit.Type)
|
||||
if actualType != nil && actualType.String() == t.requiredType {
|
||||
for _, elt := range complit.Elts {
|
||||
if kve, ok := elt.(*ast.KeyValueExpr); ok {
|
||||
issue := t.processTLSConfVal(kve, c)
|
||||
if issue != nil {
|
||||
return issue, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
132
tools/vendor/github.com/GoASTScanner/gas/rules/tls_config.go
generated
vendored
132
tools/vendor/github.com/GoASTScanner/gas/rules/tls_config.go
generated
vendored
@ -1,132 +0,0 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
// NewModernTLSCheck creates a check for Modern TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewModernTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0303,
|
||||
MaxVersion: 0x0303,
|
||||
goodCiphers: []string{
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
},
|
||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||
}
|
||||
|
||||
// NewIntermediateTLSCheck creates a check for Intermediate TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewIntermediateTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0301,
|
||||
MaxVersion: 0x0303,
|
||||
goodCiphers: []string{
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
},
|
||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||
}
|
||||
|
||||
// NewOldTLSCheck creates a check for Old TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewOldTLSCheck(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0300,
|
||||
MaxVersion: 0x0303,
|
||||
goodCiphers: []string{
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384",
|
||||
"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
||||
"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",
|
||||
"TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
"TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA",
|
||||
"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_SEED_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_SEED_CBC_SHA",
|
||||
"TLS_RSA_WITH_SEED_CBC_SHA",
|
||||
},
|
||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||
}
|
48
tools/vendor/github.com/GoASTScanner/gas/rules/unsafe.go
generated
vendored
48
tools/vendor/github.com/GoASTScanner/gas/rules/unsafe.go
generated
vendored
@ -1,48 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type usingUnsafe struct {
|
||||
gas.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
|
||||
func (r *usingUnsafe) Match(n ast.Node, c *gas.Context) (gi *gas.Issue, err error) {
|
||||
if _, matches := gas.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsingUnsafe rule detects the use of the unsafe package. This is only
|
||||
// really useful for auditing purposes.
|
||||
func NewUsingUnsafe(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
return &usingUnsafe{
|
||||
pkg: "unsafe",
|
||||
calls: []string{"Alignof", "Offsetof", "Sizeof", "Pointer"},
|
||||
MetaData: gas.MetaData{
|
||||
What: "Use of unsafe calls should be audited",
|
||||
Severity: gas.Low,
|
||||
Confidence: gas.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
53
tools/vendor/github.com/GoASTScanner/gas/rules/weakcrypto.go
generated
vendored
53
tools/vendor/github.com/GoASTScanner/gas/rules/weakcrypto.go
generated
vendored
@ -1,53 +0,0 @@
|
||||
// (c) Copyright 2016 Hewlett Packard Enterprise Development LP
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package rules
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/GoASTScanner/gas"
|
||||
)
|
||||
|
||||
type usesWeakCryptography struct {
|
||||
gas.MetaData
|
||||
blacklist map[string][]string
|
||||
}
|
||||
|
||||
func (r *usesWeakCryptography) Match(n ast.Node, c *gas.Context) (*gas.Issue, error) {
|
||||
|
||||
for pkg, funcs := range r.blacklist {
|
||||
if _, matched := gas.MatchCallByPackage(n, c, pkg, funcs...); matched {
|
||||
return gas.NewIssue(c, n, r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsesWeakCryptography detects uses of des.* md5.* or rc4.*
|
||||
func NewUsesWeakCryptography(conf gas.Config) (gas.Rule, []ast.Node) {
|
||||
calls := make(map[string][]string)
|
||||
calls["crypto/des"] = []string{"NewCipher", "NewTripleDESCipher"}
|
||||
calls["crypto/md5"] = []string{"New", "Sum"}
|
||||
calls["crypto/rc4"] = []string{"NewCipher"}
|
||||
rule := &usesWeakCryptography{
|
||||
blacklist: calls,
|
||||
MetaData: gas.MetaData{
|
||||
Severity: gas.Medium,
|
||||
Confidence: gas.High,
|
||||
What: "Use of weak cryptographic primitive",
|
||||
},
|
||||
}
|
||||
return rule, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
27
tools/vendor/github.com/alecthomas/gocyclo/LICENSE
generated
vendored
27
tools/vendor/github.com/alecthomas/gocyclo/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
||||
Copyright (c) 2013 Frederik Zipp. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright owner nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
31
tools/vendor/github.com/alecthomas/gocyclo/README.md
generated
vendored
31
tools/vendor/github.com/alecthomas/gocyclo/README.md
generated
vendored
@ -1,31 +0,0 @@
|
||||
Gocyclo calculates cyclomatic complexities of functions in Go source code.
|
||||
|
||||
The cyclomatic complexity of a function is calculated according to the
|
||||
following rules:
|
||||
|
||||
1 is the base complexity of a function
|
||||
+1 for each 'if', 'for', 'case', '&&' or '||'
|
||||
|
||||
To install, run
|
||||
|
||||
$ go get github.com/fzipp/gocyclo
|
||||
|
||||
and put the resulting binary in one of your PATH directories if
|
||||
`$GOPATH/bin` isn't already in your PATH.
|
||||
|
||||
Usage:
|
||||
|
||||
$ gocyclo [<flag> ...] <Go file or directory> ...
|
||||
|
||||
Examples:
|
||||
|
||||
$ gocyclo .
|
||||
$ gocyclo main.go
|
||||
$ gocyclo -top 10 src/
|
||||
$ gocyclo -over 25 docker
|
||||
$ gocyclo -avg .
|
||||
|
||||
The output fields for each line are:
|
||||
|
||||
<complexity> <package> <function> <file:row:column>
|
||||
|
222
tools/vendor/github.com/alecthomas/gocyclo/gocyclo.go
generated
vendored
222
tools/vendor/github.com/alecthomas/gocyclo/gocyclo.go
generated
vendored
@ -1,222 +0,0 @@
|
||||
// Copyright 2013 Frederik Zipp. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Gocyclo calculates the cyclomatic complexities of functions and
|
||||
// methods in Go source code.
|
||||
//
|
||||
// Usage:
|
||||
// gocyclo [<flag> ...] <Go file or directory> ...
|
||||
//
|
||||
// Flags
|
||||
// -over N show functions with complexity > N only and
|
||||
// return exit code 1 if the output is non-empty
|
||||
// -top N show the top N most complex functions only
|
||||
// -avg show the average complexity
|
||||
//
|
||||
// The output fields for each line are:
|
||||
// <complexity> <package> <function> <file:row:column>
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const usageDoc = `Calculate cyclomatic complexities of Go functions.
|
||||
usage:
|
||||
gocyclo [<flag> ...] <Go file or directory> ...
|
||||
|
||||
Flags
|
||||
-over N show functions with complexity > N only and
|
||||
return exit code 1 if the set is non-empty
|
||||
-top N show the top N most complex functions only
|
||||
-avg show the average complexity over all functions,
|
||||
not depending on whether -over or -top are set
|
||||
|
||||
The output fields for each line are:
|
||||
<complexity> <package> <function> <file:row:column>
|
||||
`
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, usageDoc)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
var (
|
||||
over = flag.Int("over", 0, "show functions with complexity > N only")
|
||||
top = flag.Int("top", -1, "show the top N most complex functions only")
|
||||
avg = flag.Bool("avg", false, "show the average complexity")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
if len(args) == 0 {
|
||||
usage()
|
||||
}
|
||||
|
||||
stats := analyze(args)
|
||||
sort.Sort(byComplexity(stats))
|
||||
written := writeStats(os.Stdout, stats)
|
||||
|
||||
if *avg {
|
||||
showAverage(stats)
|
||||
}
|
||||
|
||||
if *over > 0 && written > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func analyze(paths []string) []stat {
|
||||
stats := make([]stat, 0)
|
||||
for _, path := range paths {
|
||||
if isDir(path) {
|
||||
stats = analyzeDir(path, stats)
|
||||
} else {
|
||||
stats = analyzeFile(path, stats)
|
||||
}
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
func isDir(filename string) bool {
|
||||
fi, err := os.Stat(filename)
|
||||
return err == nil && fi.IsDir()
|
||||
}
|
||||
|
||||
func analyzeFile(fname string, stats []stat) []stat {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, fname, nil, 0)
|
||||
if err != nil {
|
||||
exitError(err)
|
||||
}
|
||||
return buildStats(f, fset, stats)
|
||||
}
|
||||
|
||||
func analyzeDir(dirname string, stats []stat) []stat {
|
||||
files, _ := filepath.Glob(filepath.Join(dirname, "*.go"))
|
||||
for _, file := range files {
|
||||
stats = analyzeFile(file, stats)
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
func exitError(err error) {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func writeStats(w io.Writer, sortedStats []stat) int {
|
||||
for i, stat := range sortedStats {
|
||||
if i == *top {
|
||||
return i
|
||||
}
|
||||
if stat.Complexity <= *over {
|
||||
return i
|
||||
}
|
||||
fmt.Fprintln(w, stat)
|
||||
}
|
||||
return len(sortedStats)
|
||||
}
|
||||
|
||||
func showAverage(stats []stat) {
|
||||
fmt.Printf("Average: %.3g\n", average(stats))
|
||||
}
|
||||
|
||||
func average(stats []stat) float64 {
|
||||
total := 0
|
||||
for _, s := range stats {
|
||||
total += s.Complexity
|
||||
}
|
||||
return float64(total) / float64(len(stats))
|
||||
}
|
||||
|
||||
type stat struct {
|
||||
PkgName string
|
||||
FuncName string
|
||||
Complexity int
|
||||
Pos token.Position
|
||||
}
|
||||