commit 4e76f510b34c4d81aac2f86cc9a8078355939284 Author: Vincent Batts Date: Mon Jun 3 10:42:48 2019 +0200 initial commit from IBM Cloud example Signed-off-by: Vincent Batts diff --git a/.bluemix/deploy.json b/.bluemix/deploy.json new file mode 100644 index 0000000..14d0b30 --- /dev/null +++ b/.bluemix/deploy.json @@ -0,0 +1,68 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Sample Deploy Stage", + "longDescription": "The Delivery Pipeline automates continuous deployment.", + "type": "object", + "properties": { + "api-key": { + "description": "IBM Cloud API keys contain permissions that grant access to organizations, spaces, and Kubernetes clusters. You can obtain your API key with 'ibmcloud iam api-key-create' or via the console at https://cloud.ibm.com/iam/#/apikeys by clicking **Create API key** (Each API key only can be viewed once).", + "type": "string" + }, + "dev-region": { + "description": "The IBM Cloud region", + "type": "string" + }, + "dev-organization": { + "description": "The IBM Cloud org", + "type": "string" + }, + "dev-space": { + "description": "The IBM Cloud space", + "type": "string" + }, + "app-name": { + "description": "app name", + "type": "string" + } + }, + "required": ["dev-region", "dev-organization", "dev-space", "app-name"], "form": [{ + "type": "validator", + "url": "/devops/setup/bm-helper/helper.html" + }, + { + "type": "password", + "readonly": false, + "title": "IBM Cloud API Key", + "key": "api-key" + }, + { + "type": "text", + "readonly": false, + "title": "App Name", + "key": "app-name" + }, { + "type": "table", + "columnCount": 3, + "widths": ["28%", "28%", "28%"], + "items": [{ + "type": "label", + "title": "Region" + }, { + "type": "label", + "title": "Organization" + }, { + "type": "label", + "title": "Space" + }, { + "type": "select", + "key": "dev-region" + }, { + "type": "select", + "key": "dev-organization" + }, { + "type": "select", + "key": "dev-space", + "readonly": false + }] + }] +} diff --git a/.bluemix/pipeline.yml b/.bluemix/pipeline.yml new file mode 100644 index 0000000..e547313 --- /dev/null +++ b/.bluemix/pipeline.yml @@ -0,0 +1,88 @@ +--- +stages: +- name: Build Stage + inputs: + - type: git + branch: master + service: ${REPO} + properties: + - name: CF_HOSTNAME + value: "${CF_HOSTNAME}" + type: text + - name: CF_DOMAIN + value: "${CF_DOMAIN}" + type: text + triggers: + - type: commit + jobs: + - name: Build + type: builder + artifact_dir: '' + build_type: shell + script: |- + #!/bin/bash + if [[ -f post_build.sh ]]; then + chmod +x post_build.sh; + echo "executing the post_build script"; + sh post_build.sh; + else + echo "the post_build script does not exist"; + fi +- name: Deploy Stage + inputs: + - type: job + stage: Build Stage + job: Build + properties: + - name: CF_HOSTNAME + value: "${CF_HOSTNAME}" + type: text + - name: CF_DOMAIN + value: "${CF_DOMAIN}" + type: text + triggers: + - type: stage + jobs: + - name: Deploy + type: deployer + target: + region_id: ${REGION_ID} + organization: ${CF_ORGANIZATION} + space: ${CF_SPACE} + application: ${CF_APP} + api_key: ${API_KEY} + script: |- + #!/bin/bash + cf push "${CF_APP}" --hostname "${CF_HOSTNAME}" -d "${CF_DOMAIN}" + # cf logs "${CF_APP}" --recent +- name: Health Stage + inputs: + - type: job + stage: Build Stage + job: Build + triggers: + - type: stage + permission: + execute: TOOLCHAIN_ADMINS + properties: + - name: CF_HOSTNAME + value: "${CF_HOSTNAME}" + type: text + - name: CF_DOMAIN + value: "${CF_DOMAIN}" + type: text + jobs: + - name: Test + type: tester + script: |- + #!/bin/sh + apk add --no-cache curl + if [ "$(curl -is http://not-used.not-used.net/health --connect-timeout 3 --max-time 5 --retry 3 --retry-max-time 30 | head -n 1 | grep 200)" != "" ]; then + echo "Successfully reached health endpoint" + echo "=====================================================================" + else + echo "Could not reach health endpoint: http://not-used.not-used.net/health" + exit 1; + fi; + test_type: customimage + docker_image: alpine diff --git a/.bluemix/scripts/container_build.sh b/.bluemix/scripts/container_build.sh new file mode 100644 index 0000000..ff5fb85 --- /dev/null +++ b/.bluemix/scripts/container_build.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# set -x + +echo "Build environment variables:" +echo "REGISTRY_URL=${REGISTRY_URL}" +echo "REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}" +echo "IMAGE_NAME=${IMAGE_NAME}" +echo "BUILD_NUMBER=${BUILD_NUMBER}" +echo "ARCHIVE_DIR=${ARCHIVE_DIR}" + +# also run 'env' command to find all available env variables +# or learn more about the available environment variables at: +# https://cloud.ibm.com/docs/services/ContinuousDelivery/pipeline_deploy_var.html#deliverypipeline_environment + +# To review or change build options use: +# ibmcloud cr build --help + +echo "Checking registry namespace: ${REGISTRY_NAMESPACE}" +NS=$( ibmcloud cr namespaces | grep ${REGISTRY_NAMESPACE} ||: ) +if [ -z "${NS}" ]; then + echo -e "Registry namespace ${REGISTRY_NAMESPACE} not found, creating it." + ibmcloud cr namespace-add ${REGISTRY_NAMESPACE} + echo -e "Registry namespace ${REGISTRY_NAMESPACE} created." +else + echo -e "Registry namespace ${REGISTRY_NAMESPACE} found." +fi + +echo -e "Existing images in registry" +ibmcloud cr images + +echo "==========================================================" +echo -e "BUILDING CONTAINER IMAGE: ${IMAGE_NAME}:${BUILD_NUMBER}" +set -x +ibmcloud cr build -t ${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}:${BUILD_NUMBER} . +set +x +ibmcloud cr image-inspect ${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME}:${BUILD_NUMBER} + +export PIPELINE_IMAGE_URL="$REGISTRY_URL/$REGISTRY_NAMESPACE/$IMAGE_NAME:$BUILD_NUMBER" + +ibmcloud cr images + +echo "==========================================================" +echo "COPYING ARTIFACTS needed for deployment and testing (in particular build.properties)" + +echo "Checking archive dir presence" +mkdir -p $ARCHIVE_DIR + +# Persist env variables into a properties file (build.properties) so that all pipeline stages consuming this +# build as input and configured with an environment properties file valued 'build.properties' +# will be able to reuse the env variables in their job shell scripts. + +# CHART information from build.properties is used in Helm Chart deployment to set the release name +CHART_NAME=$(find chart/. -maxdepth 2 -type d -name '[^.]?*' -printf %f -quit) +echo "CHART_NAME=${CHART_NAME}" >> $ARCHIVE_DIR/build.properties +# IMAGE information from build.properties is used in Helm Chart deployment to set the release name +echo "IMAGE_NAME=${IMAGE_NAME}" >> $ARCHIVE_DIR/build.properties +echo "BUILD_NUMBER=${BUILD_NUMBER}" >> $ARCHIVE_DIR/build.properties +# REGISTRY information from build.properties is used in Helm Chart deployment to generate cluster secret +echo "REGISTRY_URL=${REGISTRY_URL}" >> $ARCHIVE_DIR/build.properties +echo "REGISTRY_NAMESPACE=${REGISTRY_NAMESPACE}" >> $ARCHIVE_DIR/build.properties +echo "File 'build.properties' created for passing env variables to subsequent pipeline jobs:" +cat $ARCHIVE_DIR/build.properties + +echo "Copy pipeline scripts along with the build" +# Copy scripts (incl. deploy scripts) +if [ -d ./scripts/ ]; then + if [ ! -d $ARCHIVE_DIR/scripts/ ]; then # no need to copy if working in ./ already + cp -r ./scripts/ $ARCHIVE_DIR/ + fi +fi + +echo "Copy Helm chart along with the build" +if [ ! -d $ARCHIVE_DIR/chart/ ]; then # no need to copy if working in ./ already + cp -r ./chart/ $ARCHIVE_DIR/ +fi diff --git a/.bluemix/scripts/kube_deploy.sh b/.bluemix/scripts/kube_deploy.sh new file mode 100644 index 0000000..42319aa --- /dev/null +++ b/.bluemix/scripts/kube_deploy.sh @@ -0,0 +1,136 @@ +#!/bin/bash +#set -x + +#View build properties +cat build.properties + +echo "Check cluster availability" +IP_ADDR=$(ibmcloud cs workers ${PIPELINE_KUBERNETES_CLUSTER_NAME} | grep normal | head -n 1 | awk '{ print $2 }') +if [ -z $IP_ADDR ]; then + echo "$PIPELINE_KUBERNETES_CLUSTER_NAME not created or workers not ready" + exit 1 +fi + +echo "Configuring cluster namespace" +if kubectl get namespace ${CLUSTER_NAMESPACE}; then + echo -e "Namespace ${CLUSTER_NAMESPACE} found." +else + kubectl create namespace ${CLUSTER_NAMESPACE} + echo -e "Namespace ${CLUSTER_NAMESPACE} created." +fi + +echo "Configuring cluster role binding" +if kubectl get clusterrolebinding kube-system:default; then + echo -e "Cluster role binding found." +else + kubectl create clusterrolebinding kube-system:default --clusterrole=cluster-admin --serviceaccount=kube-system:default + echo -e "Cluster role binding created." +fi + +echo "Configuring Tiller (Helm's server component)" +helm init --upgrade +kubectl rollout status -w deployment/tiller-deploy --namespace=kube-system +while [ "$(helm version | grep "Tiller")" != "" ]; do + echo "Waiting for server..." + sleep 10 +done +helm version + +echo "CHART_NAME: $CHART_NAME" + +echo "DEFINE RELEASE by prefixing image (app) name with namespace if not 'default' as Helm needs unique release names across namespaces" +if [[ "${CLUSTER_NAMESPACE}" != "default" ]]; then + RELEASE_NAME="${CLUSTER_NAMESPACE}-${IMAGE_NAME}" +else + RELEASE_NAME=${IMAGE_NAME} +fi +echo "RELEASE_NAME: $RELEASE_NAME" + +echo "CHECKING CHART (lint)" +helm lint chart/${CHART_NAME} + +IMAGE_REPOSITORY=${REGISTRY_URL}/${REGISTRY_NAMESPACE}/${IMAGE_NAME} + +# Using 'upgrade --install" for rolling updates. Note that subsequent updates will occur in the same namespace the release is currently deployed in, ignoring the explicit--namespace argument". +echo -e "Dry run into: ${PIPELINE_KUBERNETES_CLUSTER_NAME}/${CLUSTER_NAMESPACE}." +helm upgrade --install --debug --dry-run ${RELEASE_NAME} ./chart/${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} --set image.repository=${IMAGE_REPOSITORY},image.tag=${BUILD_NUMBER} + +echo -e "Deploying into: ${PIPELINE_KUBERNETES_CLUSTER_NAME}/${CLUSTER_NAMESPACE}." +helm upgrade --install ${RELEASE_NAME} ./chart/${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} --set image.repository=${IMAGE_REPOSITORY},image.tag=${BUILD_NUMBER} + +echo -e "CHECKING deployment status of release ${RELEASE_NAME} with image tag: ${BUILD_NUMBER}" +echo "" +for ITERATION in {1..30} +do + DATA=$( kubectl get pods --namespace ${CLUSTER_NAMESPACE} -a -l release=${RELEASE_NAME} -o json ) + NOT_READY=$( echo $DATA | jq '.items[].status.containerStatuses[] | select(.image=="'"${IMAGE_REPOSITORY}:${BUILD_NUMBER}"'") | select(.ready==false) ' ) + if [[ -z "$NOT_READY" ]]; then + echo -e "All pods are ready:" + echo $DATA | jq '.items[].status.containerStatuses[] | select(.image=="'"${IMAGE_REPOSITORY}:${BUILD_NUMBER}"'") | select(.ready==true) ' + break # deployment succeeded + fi + REASON=$(echo $DATA | jq '.items[].status.containerStatuses[] | select(.image=="'"${IMAGE_REPOSITORY}:${BUILD_NUMBER}"'") | .state.waiting.reason') + echo -e "${ITERATION} : Deployment still pending..." + echo -e "NOT_READY:${NOT_READY}" + echo -e "REASON: ${REASON}" + if [[ ${REASON} == *ErrImagePull* ]] || [[ ${REASON} == *ImagePullBackOff* ]]; then + echo "Detected ErrImagePull or ImagePullBackOff failure. " + echo "Please check proper authenticating to from cluster to image registry (e.g. image pull secret)" + break; # no need to wait longer, error is fatal + elif [[ ${REASON} == *CrashLoopBackOff* ]]; then + echo "Detected CrashLoopBackOff failure. " + echo "Application is unable to start, check the application startup logs" + break; # no need to wait longer, error is fatal + fi + sleep 5 +done + +if [[ ! -z "$NOT_READY" ]]; then + echo "" + echo "==========================================================" + echo "DEPLOYMENT FAILED" + echo "Deployed Services:" + kubectl describe services ${RELEASE_NAME}-${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} + echo "" + echo "Deployed Pods:" + kubectl describe pods --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} + echo "" + echo "Application Logs" + kubectl logs --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} + echo "==========================================================" + PREVIOUS_RELEASE=$( helm history ${RELEASE_NAME} | grep SUPERSEDED | sort -r -n | awk '{print $1}' | head -n 1 ) + echo -e "Could rollback to previous release: ${PREVIOUS_RELEASE} using command:" + echo -e "helm rollback ${RELEASE_NAME} ${PREVIOUS_RELEASE}" + # helm rollback ${RELEASE_NAME} ${PREVIOUS_RELEASE} + # echo -e "History for release:${RELEASE_NAME}" + # helm history ${RELEASE_NAME} + # echo "Deployed Services:" + # kubectl describe services ${RELEASE_NAME}-${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} + # echo "" + # echo "Deployed Pods:" + # kubectl describe pods --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} + exit 1 +fi + +echo "" +echo "==========================================================" +echo "DEPLOYMENT SUCCEEDED" +echo "" +echo -e "Status for release:${RELEASE_NAME}" +helm status ${RELEASE_NAME} + +echo "" +echo -e "History for release:${RELEASE_NAME}" +helm history ${RELEASE_NAME} + +# echo "" +# echo "Deployed Services:" +# kubectl describe services ${RELEASE_NAME}-${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} +# echo "" +# echo "Deployed Pods:" +# kubectl describe pods --selector app=${CHART_NAME} --namespace ${CLUSTER_NAMESPACE} + +echo "==========================================================" +IP_ADDR=$(ibmcloud cs workers ${PIPELINE_KUBERNETES_CLUSTER_NAME} | grep normal | head -n 1 | awk '{ print $2 }') +PORT=$(kubectl get services --namespace ${CLUSTER_NAMESPACE} | grep ${RELEASE_NAME} | sed 's/[^:]*:\([0-9]*\).*/\1/g') +echo -e "View the application health at: http://${IP_ADDR}:${PORT}/health" diff --git a/.bluemix/toolchain.yml b/.bluemix/toolchain.yml new file mode 100644 index 0000000..6a7c87a --- /dev/null +++ b/.bluemix/toolchain.yml @@ -0,0 +1,62 @@ +version: '2' +template: + name: Continuous Delivery Toolchain + description: "This toolchain includes tools to develop and deploy your app. Depending on your app, when you create the toolchain, the GitHub repository will either be empty or will contain source code from your app.\n\nThis toolchain uses tools that are part of the Continuous Delivery service. If an instance of that service isn't already in your organization, when you click **Create**, it is automatically added at no cost to you. For more information and terms, see the [IBM Cloud catalog](/catalog/services/continuous-delivery/).\n\nTo get started, click **Create**." + required: + - repo + - build + +toolchain: + name: "{{form.pipeline.parameters.toolchain-name}}" + +services: + # Github repos + repo: + service_id: hostedgit + parameters: + repo_url: "{{#zip_url}}{{zip_url}}{{/zip_url}}{{^zip_url}}{{repository}}{{/zip_url}}" + repo_name: "{{toolchain.name}}" + type: clone + has_issues: true + enable_traceability: true + + # Pipelines + build: + service_id: pipeline + parameters: + services: + - repo + name: "{{form.pipeline.parameters.app-name}}" + ui-pipeline: true + configuration: + content: + $text: pipeline.yml + env: + REPO: repo + CF_APP: "{{form.pipeline.parameters.app-name}}" + API_KEY: "{{form.pipeline.parameters.api-key}}" + CF_SPACE: "{{form.pipeline.parameters.dev-space}}" + CF_ORGANIZATION: "{{form.pipeline.parameters.dev-organization}}" + CF_HOSTNAME: "{{form.pipeline.parameters.cf-host}}" + CF_DOMAIN: "{{form.pipeline.parameters.cf-domain}}" + REGION_ID: "{{form.pipeline.parameters.dev-region}}" + execute: true + + #Web IDE + webide: + service_id: orion + +#Deployment +form: + pipeline: + schema: + $ref: deploy.json + parameters: + app-name: "{{app-name}}" + toolchain-name: "{{toolchain-name}}" + dev-region: "{{region}}" + api-key: "{{api-key}}" + dev-space: "{{space}}" + dev-organization: "{{organization}}" + cf-host: "{{cf-host}}" + cf-domain: "{{cf-domain}}" diff --git a/.cfignore b/.cfignore new file mode 100644 index 0000000..e0e7610 --- /dev/null +++ b/.cfignore @@ -0,0 +1,2 @@ +.git/ +vendor/ \ No newline at end of file diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e8a69a0 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +Dockerfile +Dockerfile-tools +vendor/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..af41ff8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +vendor/ +.DS_Store +server/localdev-config.json +localdev-config.json +server/localdev-config.json \ No newline at end of file diff --git a/.ibm-project b/.ibm-project new file mode 100644 index 0000000..d1eb9c9 --- /dev/null +++ b/.ibm-project @@ -0,0 +1 @@ +{"build-release-ready":true,"build-debug-ready":false,"devops":false,"deploy-image":"","chart-path":"","ibm-cluster":"","motd-access":"Mon, 03 Jun 2019 10:25:26 CEST","app-id":"","deploy-target":""} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5c204dd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM golang:1.10.3-alpine + +# Update packages and install dependency packages for services +RUN apk update && apk add --no-cache bash git + +# Change working directory +WORKDIR $GOPATH/src/myappziugv/ + +# Install dependencies +RUN go get -u github.com/golang/dep/... +RUN go get -u github.com/derekparker/delve/cmd/dlv/... +COPY . ./ +RUN dep ensure -v + +ENV PORT 8080 +ENV GIN_MODE release +EXPOSE 8080 + +CMD ["go", "run", "server.go"] diff --git a/Dockerfile-tools b/Dockerfile-tools new file mode 100644 index 0000000..c706ca2 --- /dev/null +++ b/Dockerfile-tools @@ -0,0 +1,31 @@ +FROM golang:1.10.3-alpine + +# Update packages and install dependency packages for services +RUN apk update && apk add --no-cache bash git + +EXPOSE 8080 +EXPOSE 8181 + +# Disables C compilation +ENV CGO_ENABLED=0 + +# Change working directory +WORKDIR $GOPATH/src/myappziugv/ + +# Install dependencies +RUN go get -u github.com/golang/dep/... +RUN go get -u github.com/derekparker/delve/cmd/dlv/... +COPY . ./ +RUN dep ensure -v + +COPY run-dev $GOPATH/bin +RUN chmod 777 $GOPATH/bin/run-dev +RUN chmod 777 $GOPATH/src/myappziugv/ + +CMD ["/bin/bash"] + +ARG bx_dev_user=root +ARG bx_dev_userid=1000 +RUN BX_DEV_USER=$bx_dev_user +RUN BX_DEV_USERID=$bx_dev_userid +RUN if [ "$bx_dev_user" != root ]; then adduser -D -s /bin/bash -u $bx_dev_userid $bx_dev_user; fi diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 0000000..02524b6 --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,140 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/afex/hystrix-go" + packages = [ + "hystrix", + "hystrix/metric_collector", + "hystrix/rolling" + ] + revision = "fa1af6a1f4f56e0e50d427fe901cd604d8c6fb8a" + +[[projects]] + branch = "master" + name = "github.com/beorn7/perks" + packages = ["quantile"] + revision = "3a771d992973f24aa725d07868b467d1ddfceafb" + +[[projects]] + branch = "master" + name = "github.com/gin-contrib/sse" + packages = ["."] + revision = "22d885f9ecc78bf4ee5d72b937e4bbcdc58e8cae" + +[[projects]] + branch = "master" + name = "github.com/gin-contrib/static" + packages = ["."] + revision = "73da7037e716e63aa2b0ffceb630dfa7be299086" + +[[projects]] + name = "github.com/gin-gonic/gin" + packages = [ + ".", + "binding", + "render" + ] + revision = "d459835d2b077e44f7c9b453505ee29881d5d12d" + version = "v1.2" + +[[projects]] + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" + version = "v1.1.0" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + name = "github.com/matttproud/golang_protobuf_extensions" + packages = ["pbutil"] + revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" + version = "v1.0.1" + +[[projects]] + name = "github.com/prometheus/client_golang" + packages = [ + "prometheus", + "prometheus/promhttp" + ] + revision = "c5b7fccd204277076155f10851dad72b76a49317" + version = "v0.8.0" + +[[projects]] + branch = "master" + name = "github.com/prometheus/client_model" + packages = ["go"] + revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f" + +[[projects]] + branch = "master" + name = "github.com/prometheus/common" + packages = [ + "expfmt", + "internal/bitbucket.org/ww/goautoneg", + "model" + ] + revision = "c7de2306084e37d54b8be01f3541a8464345e9a5" + +[[projects]] + branch = "master" + name = "github.com/prometheus/procfs" + packages = [ + ".", + "internal/util", + "nfs", + "xfs" + ] + revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92" + +[[projects]] + name = "github.com/sirupsen/logrus" + packages = ["."] + revision = "3e01752db0189b9157070a0e1668a620f9a85da2" + version = "v1.0.6" + +[[projects]] + name = "github.com/ugorji/go" + packages = ["codec"] + revision = "b4c50a2b199d93b13dc15e78929cfb23bfdf21ab" + version = "v1.1.1" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["ssh/terminal"] + revision = "de0752318171da717af4ce24d0a2e8626afaeb11" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows" + ] + revision = "904bdc257025c7b3f43c19360ad3ab85783fad78" + +[[projects]] + name = "gopkg.in/go-playground/validator.v8" + packages = ["."] + revision = "5f1438d3fca68893a817e4a66806cea46a9e4ebf" + version = "v8.18.2" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "cfb76a107033de6a324f07b2b42321da57969a25f09c4202008c49f9e85f489a" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 0000000..4e9bed2 --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,50 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + branch = "master" + name = "github.com/afex/hystrix-go" + +[[constraint]] + branch = "master" + name = "github.com/gin-contrib/static" + +[[constraint]] + name = "github.com/gin-gonic/gin" + version = "1.2.0" + +[[constraint]] + name = "github.com/prometheus/client_golang" + version = "0.8.0" + +[[constraint]] + name = "github.com/sirupsen/logrus" + version = "1.0.5" + +[prune] + go-tests = true + unused-packages = true diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..7d66590 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,6 @@ +#!groovy + +@Library('MicroserviceBuilder') _ +microserviceBuilderPipeline { + image = 'myappziugv' +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..890fb64 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2019 IBM Corporation + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d7d4a93 --- /dev/null +++ b/README.md @@ -0,0 +1,91 @@ +## MyAppZIUGV + +[![](https://img.shields.io/badge/IBM%20Cloud-powered-blue.svg)](https://bluemix.net) +![Platform](https://img.shields.io/badge/platform-go-lightgrey.svg?style=flat) + +## Table of Contents + +* [Summary](#summary) +* [Requirements](#requirements) +* [Configuration](#configuration) +* [Run](#run) + + +## Summary + +This application generated stubs for each route defined in the provided OpenAPI 2.0 document. It follows the microservice architecture - an architectural style that structures an application as a collection of loosely coupled services, which implement business capabilities. This application exposes a RESTful API matching a [OpenAPI 2.0](https://swagger.io/docs/specification/2-0/basic-structure/) definition that you provided. + + +All of your `dep` dependencies are stored inside of `Gopkg.toml`. + +## Requirements +#### Local Development Setup (optional) + +- Install [Go](https://golang.org/dl/) +- Install [dep](https://github.com/golang/dep) + +### IBM Cloud Developer Tools (optional) + +[IBM Cloud Developer Tools](https://cloud.ibm.com/docs/cli/index.html#overview) simplifies the building, running, and deployment of your application from you local environment to the cloud in containerized environments. + +1. Install [IBM Cloud Developer Tools](https://cloud.ibm.com/docs/cli/index.html#step1) on your machine +2. Install the dev plugin: `ibmcloud plugin install dev` + +#### cli-config.yml + +The `cli-config.yml` contains the commands that are used by IBM Cloud Developer Tools. If needed, you can update these to reflect how you want to run your project: +* `test-cmd`: The command to execute tests for the code in the tools container (i.e. `go test ./...`) + +* `build-cmd-debug`: The command to build the code and docker image for `DEBUG` mode (i.e. `go build` to ensure that the application compiles cleanly) + +* `debug-cmd`: The command to execute debug of the code in the tools container using [delve](https://github.com/derekparker/delve) (i.e. `dlv debug --headless --listen=0.0.0.0:8181`) + +### IBM Cloud DevOps (optional) + +[![Create Toolchain](https://cloud.ibm.com/devops/graphics/create_toolchain_button.png)](https://cloud.ibm.com/devops/setup/deploy/) + +[IBM Cloud DevOps](https://cloud.ibm.com/devops/getting-started) services provides toolchains as a set of tool integrations that support development, deployment, and operations tasks inside IBM Cloud. The **Create Toolchain** button creates a DevOps toolchain and acts as a single-click deploy to IBM Cloud including provisioning all required services. + +## Run + +#### Configuration + +This project contains IBM Cloud specific files that are used to deploy the application as part of an IBM Cloud DevOps flow. The `.bluemix` directory contains files used to define the IBM Cloud toolchain and pipeline for your application. + +Credentials are either taken from the VCAP_SERVICES or Kubernetes environment variablea if in IBM Cloud, or from a config file if running locally or on VSIs. + +More information about configuration best practices and abstraction of environments can be found in the IBM Cloud [Go Programming Guide](https://cloud.ibm.com/docs/go/configuration.html#configuration). + +### Using IBM Cloud Developer Tools + + IBM Cloud Developer Tools makes it easy to compile and run your application if you do not have all of the tools installed on your computer yet. Your application will be compiled with Docker containers. To compile and run your app, run: + +```bash +ibmcloud dev build +ibmcloud dev run +``` + +### Using your local environment + +In order for Go applications to run locally, they must be placed in the correct file path. The application must exist in `$GOPATH/src/myappziugv` + +To run your application locally: + +```bash +dep ensure +go run server.go +``` + +Once the Go toolchain has been installed, you can compile a Go project with: + +```bash +go install +``` + +Your sources will be compiled to your `$GOPATH/bin` directory. + +### Application Endpoints + +Your application is running at: `http://localhost:8080` in your browser. + +- Health endpoint: `/health` diff --git a/chart/myappziugv/Chart.yaml b/chart/myappziugv/Chart.yaml new file mode 100644 index 0000000..bd7e757 --- /dev/null +++ b/chart/myappziugv/Chart.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +description: A Helm chart for Kubernetes +name: myappziugv +version: 1.0.0 \ No newline at end of file diff --git a/chart/myappziugv/templates/basedeployment.yaml b/chart/myappziugv/templates/basedeployment.yaml new file mode 100644 index 0000000..65c1a85 --- /dev/null +++ b/chart/myappziugv/templates/basedeployment.yaml @@ -0,0 +1,39 @@ +{{ if .Values.base.enabled }} +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "{{ .Chart.Name }}-basedeployment" + labels: + chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' +spec: + replicas: {{ .Values.base.replicaCount }} + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + template: + metadata: + labels: + app: "{{ .Chart.Name }}-selector" + version: "base" + spec: + containers: + - name: "{{ .Chart.Name }}" + image: "{{ .Values.image.repository }}:{{ .Values.base.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + httpGet: + path: /health + port: {{ .Values.service.servicePort }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}} + periodSeconds: {{ .Values.livenessProbe.periodSeconds}} + resources: + requests: + cpu: "{{ .Values.image.resources.requests.cpu }}" + memory: "{{ .Values.image.resources.requests.memory }}" + env: + - name: PORT + value : "{{ .Values.service.servicePort }}" +{{ end }} diff --git a/chart/myappziugv/templates/deployment.yaml b/chart/myappziugv/templates/deployment.yaml new file mode 100644 index 0000000..25aaa01 --- /dev/null +++ b/chart/myappziugv/templates/deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: "{{ .Chart.Name }}-deployment" + labels: + chart: '{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}' +spec: + replicas: {{ .Values.replicaCount }} + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + revisionHistoryLimit: {{ .Values.revisionHistoryLimit }} + template: + metadata: + labels: + app: "{{ .Chart.Name }}-selector" + version: "current" + spec: + containers: + - name: "{{ .Chart.Name }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + livenessProbe: + httpGet: + path: /health + port: {{ .Values.service.servicePort }} + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds}} + periodSeconds: {{ .Values.livenessProbe.periodSeconds}} + ports: + - containerPort: {{ .Values.service.servicePort}} + resources: + requests: + cpu: "{{ .Values.image.resources.requests.cpu }}" + memory: "{{ .Values.image.resources.requests.memory }}" + env: + - name: PORT + value : "{{ .Values.service.servicePort }}" + - name: APPLICATION_NAME + value: "{{ .Release.Name }}" diff --git a/chart/myappziugv/templates/hpa.yaml b/chart/myappziugv/templates/hpa.yaml new file mode 100644 index 0000000..5fdefe9 --- /dev/null +++ b/chart/myappziugv/templates/hpa.yaml @@ -0,0 +1,27 @@ +{{ if .Values.hpa.enabled }} +{{ if and (eq .Capabilities.KubeVersion.Major "1") (ge .Capabilities.KubeVersion.Minor "8") }} +apiVersion: autoscaling/v2beta1 +{{ else }} +apiVersion: autoscaling/v2alpha1 +{{ end }} +kind: HorizontalPodAutoscaler +metadata: + name: "{{ .Chart.Name }}-hpa-policy" + namespace: default +spec: + scaleTargetRef: + apiVersion: apps/v1beta1 + kind: Deployment + name: "{{ .Chart.Name }}-deployment" + minReplicas: {{ .Values.hpa.minReplicas }} + maxReplicas: {{ .Values.hpa.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.hpa.metrics.cpu.targetAverageUtilization }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.hpa.metrics.memory.targetAverageUtilization }} +{{ end }} \ No newline at end of file diff --git a/chart/myappziugv/templates/istio.yaml b/chart/myappziugv/templates/istio.yaml new file mode 100644 index 0000000..7ee841b --- /dev/null +++ b/chart/myappziugv/templates/istio.yaml @@ -0,0 +1,19 @@ +{{ if .Values.istio.enabled }} +apiVersion: config.istio.io/v1alpha2 +kind: RouteRule +metadata: + name: "{{ .Chart.Name }}-default" +spec: + destination: + name: "{{ .Chart.Name }}-service" + precedence: 1 + route: + - labels: + version: "current" + weight: {{ .Values.istio.weight }} +{{ if .Values.base.enabled }} + - labels: + version: "base" + weight: {{ .Values.base.weight }} +{{ end }} +{{ end }} \ No newline at end of file diff --git a/chart/myappziugv/templates/service.yaml b/chart/myappziugv/templates/service.yaml new file mode 100644 index 0000000..22c89ca --- /dev/null +++ b/chart/myappziugv/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/scrape: 'true' + name: "{{ .Chart.Name }}-application-service" + labels: + chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.servicePort }} + selector: + app: "{{ .Chart.Name }}-selector" diff --git a/chart/myappziugv/values.yaml b/chart/myappziugv/values.yaml new file mode 100644 index 0000000..6781a51 --- /dev/null +++ b/chart/myappziugv/values.yaml @@ -0,0 +1,37 @@ +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. +replicaCount: 1 +revisionHistoryLimit: 1 +image: + repository: icr.io/replace-me-namespace/myappziugv + tag: v1.0.0 + pullPolicy: Always + resources: + requests: + cpu: 200m + memory: 300Mi +livenessProbe: + initialDelaySeconds: 30 + periodSeconds: 10 +service: + name: go + type: NodePort + servicePort: 8080 +hpa: + enabled: false + minReplicas: 1 + maxReplicas: 2 + metrics: + cpu: + targetAverageUtilization: 70 + memory: + targetAverageUtilization: 70 +base: + enabled: false + replicaCount: 1 + image: + tag : v0.9.9 + weight: 100 +istio: + enabled: false + weight: 100 diff --git a/cli-config.yml b/cli-config.yml new file mode 100644 index 0000000..a6b04de --- /dev/null +++ b/cli-config.yml @@ -0,0 +1,52 @@ +# The container name used for the run container +container-name-run : "myappziugv-go-run" +# The container name used for the tools container +container-name-tools : "myappziugv-go-tools" + +# The project root on the host for the run container to mount to container-path-run +host-path-run : "." +# The project root on the host for the tools container to mount to container-path-tools +host-path-tools : "." + +# The project root in the run container to mount to host-path-run +container-path-run : "/go/src/myappziugv; :" +# The project root in the tools container that will be mounted to host-path-tools +container-path-tools : "/go/src/myappziugv; :" + +# The port mappings between the host and the container in the form [host:container] +container-port-map : "8080:8080" +# The port mappings between the host and the container for the debug port in the form [host:container] +container-port-map-debug : "8181:8181" + +# The name for the dockerfile for the run container +dockerfile-run : "Dockerfile" +# The name for the dockerfile for the tools container +dockerfile-tools : "Dockerfile-tools" + +# The name of image to create from dockerfile-run +image-name-run : "myappziugv-go-run" +# The name of image to create from dockerfile-tools +image-name-tools : "myappziugv-go-tools" + +# The command to build the code and docker image for RUN +build-cmd-run : "go build" +# The command to execute tests for the code in the tools container +test-cmd : "go test ./..." +# The command to build the code and docker image for DEBUG +build-cmd-debug : "go build" + +# The command to run the code in the run container +run-cmd : "" +# The command to execute debug of the code in the tools container +debug-cmd : "dlv debug --headless --listen=0.0.0.0:8181" +# The command to stop the code +stop-cmd : "" + +# The relative path to the helm chart used for Kubernetes deployment +chart-path : "chart/myappziugv" + +# The IBM version of this configuration +version : "0.0.3" +ibm-generated-id : "0102d32e-801e-4675-9a8e-3239ae79eccb" +ibm-cloud-app-id : "942a745a-b570-4331-a922-3447b9b1fbd4" +credentials-filepath : "localdev-config.json, server/localdev-config.json" \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5e1386a --- /dev/null +++ b/go.mod @@ -0,0 +1,76 @@ +module myappziugv + +go 1.12 + +require ( + cloud.google.com/go v0.39.0 // indirect + github.com/OneOfOne/xxhash v1.2.5 // indirect + github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 + github.com/alecthomas/gometalinter v3.0.0+incompatible // indirect + github.com/coreos/etcd v3.3.13+incompatible // indirect + github.com/coreos/go-semver v0.3.0 // indirect + github.com/cosiner/argv v0.0.1 // indirect + github.com/davidrjenni/reftools v0.0.0-20190411195930-981bbac422f8 // indirect + github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b // indirect + github.com/fatih/gomodifytags v0.0.0-20190517204355-df91c5bc7551 // indirect + github.com/fatih/motion v0.0.0-20190527122956-41470362fad4 // indirect + github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 // indirect + github.com/gin-contrib/static v0.0.0-20180301030858-73da7037e716 + github.com/gin-gonic/gin v0.0.0-20170702092826-d459835d2b07 + github.com/go-delve/delve v1.2.0 // indirect + github.com/golang/mock v1.3.1 // indirect + github.com/golangci/golangci-lint v1.16.0 // indirect + github.com/google/go-cmp v0.3.0 // indirect + github.com/google/pprof v0.0.0-20190515194954-54271f7e092f // indirect + github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf // indirect + github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 // indirect + github.com/jstemmer/gotags v1.4.1 // indirect + github.com/keegancsmith/rpc v1.1.0 // indirect + github.com/kisielk/errcheck v1.2.0 // indirect + github.com/klauspost/asmfmt v1.2.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91 // indirect + github.com/kr/pty v1.1.4 // indirect + github.com/magiconair/properties v1.8.1 // indirect + github.com/mattn/go-colorable v0.1.2 // indirect + github.com/mattn/go-runewidth v0.0.4 // indirect + github.com/mdempsky/gocode v0.0.0-20190203001940-7fb65232883f // indirect + github.com/nicksnyder/go-i18n v1.10.0 // indirect + github.com/pelletier/go-toml v1.4.0 // indirect + github.com/peterh/liner v1.1.0 // indirect + github.com/pkg/errors v0.8.1 // indirect + github.com/pkg/profile v1.3.0 // indirect + github.com/prometheus/client_golang v0.9.3 + github.com/prometheus/common v0.4.1 // indirect + github.com/prometheus/procfs v0.0.0-20190528151240-3cb620ac02d0 // indirect + github.com/prometheus/tsdb v0.8.0 // indirect + github.com/rogpeppe/fastuuid v1.1.0 // indirect + github.com/rogpeppe/godef v1.1.1 // indirect + github.com/russross/blackfriday v2.0.0+incompatible // indirect + github.com/sirupsen/logrus v1.4.2 + github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/afero v1.2.2 // indirect + github.com/spf13/cobra v0.0.4 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/viper v1.4.0 // indirect + github.com/stamblerre/gocode v0.0.0-20190327203809-810592086997 // indirect + github.com/stretchr/objx v0.2.0 // indirect + github.com/ugorji/go v1.1.5-pre // indirect + github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a // indirect + golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c // indirect + golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f // indirect + golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522 // indirect + golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff // indirect + golang.org/x/lint v0.0.0-20190409202823-959b441ac422 // indirect + golang.org/x/mobile v0.0.0-20190509164839-32b2708ab171 // indirect + golang.org/x/oauth2 v0.0.0-20190523182746-aaccbc9213b0 // indirect + golang.org/x/sys v0.0.0-20190529130038-5219a1e1c5f8 // indirect + golang.org/x/text v0.3.2 // indirect + golang.org/x/tools v0.0.0-20190529010454-aa71c3f32488 // indirect + google.golang.org/appengine v1.6.0 // indirect + google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69 // indirect + gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect + gopkg.in/go-playground/validator.v8 v8.18.2 // indirect + honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2e2c2f3 --- /dev/null +++ b/go.sum @@ -0,0 +1,462 @@ +9fans.net/go v0.0.0-20181112161441-237454027057 h1:OcHlKWkAMJEF1ndWLGxp5dnJQkYM/YImUOvsBoz6h5E= +9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.39.0/go.mod h1:rVLT6fkc8chs9sfPtFc1SBH6em7n+ZoXaG+87tDISts= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= +github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2 h1:HTOmFEEYrWi4MW5ZKUx6xfeyM10Sx3kQF65xiQJMPYA= +github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/gometalinter v3.0.0+incompatible h1:e9Zfvfytsw/e6Kd/PYd75wggK+/kX5Xn8IYDUKyc5fU= +github.com/alecthomas/gometalinter v3.0.0+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosiner/argv v0.0.0-20170225145430-13bacc38a0a5/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ= +github.com/cosiner/argv v0.0.1 h1:2iAFN+sWPktbZ4tvxm33Ei8VY66FPCxdOxpncUGpAXE= +github.com/cosiner/argv v0.0.1/go.mod h1:p/NrK5tF6ICIly4qwEDsf6VDirFiWWz0FenfYBwJaKQ= +github.com/cpuguy83/go-md2man v1.0.8/go.mod h1:N6JayAiVKtlHSnuTCeuLSQVs75hb8q+dYQLjr7cDsKY= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidrjenni/reftools v0.0.0-20190411195930-981bbac422f8 h1:Eu7kPTwAOeiiot8fjH/WXIYSsoaYB7Xs7sPF8NYeKhs= +github.com/davidrjenni/reftools v0.0.0-20190411195930-981bbac422f8/go.mod h1:0qWLWApvobxwtd9/A8fS62VkRImuquIgtCv/ye+KnxA= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fatih/color v1.6.0 h1:66qjqZk8kalYAvDRtM1AdAJQI0tj4Wrue3Eq3B3pmFU= +github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/gomodifytags v0.0.0-20190517204355-df91c5bc7551 h1:/fvatMHXeYKMzBfS7ZAWJxAUVdNvorVap9/T7agWgW8= +github.com/fatih/gomodifytags v0.0.0-20190517204355-df91c5bc7551/go.mod h1:p2/x7bnOQsbq/deXsDIlj2yLiKFGPkD2nuoYqwn8R4Y= +github.com/fatih/motion v0.0.0-20190527122956-41470362fad4 h1:g4GA9iRiXHcBKOAjgZi2HsLP5zD2bSXZE5VL/+3yNN8= +github.com/fatih/motion v0.0.0-20190527122956-41470362fad4/go.mod h1:pseIrV+t9A4+po+KJ1LheSnYH8m1qs6WhKx2zFiGi9I= +github.com/fatih/structtag v1.0.0 h1:pTHj65+u3RKWYPSGaU290FpI/dXxTaHdVwVwbcPKmEc= +github.com/fatih/structtag v1.0.0/go.mod h1:IKitwq45uXL/yqi5mYghiD3w9H6eTOvI9vnk8tXMphA= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +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/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7 h1:AzN37oI0cOS+cougNAV9szl6CVoj2RYwzS3DpUQNtlY= +github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-contrib/static v0.0.0-20180301030858-73da7037e716 h1:seIQ8aTL430iQYzq6lrpYBpDe9nKH3Ea7MlwP5nhPQE= +github.com/gin-contrib/static v0.0.0-20180301030858-73da7037e716/go.mod h1:2fEScoZYr3j0CaSPS4VxkA76ygb6q7PvKW0Mha6hANQ= +github.com/gin-gonic/gin v0.0.0-20170702092826-d459835d2b07 h1:cZPJWzd2oNeoS0oJM2TlN9rl0OnCgUr10gC8Q4mH+6M= +github.com/gin-gonic/gin v0.0.0-20170702092826-d459835d2b07/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= +github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead h1:qwmAYufKDopQnFdeMw+iHJVxAd2CbF+VFKHyJJwnPKk= +github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead/go.mod h1:3MzXZKJdeXqdU9cj+rvZdNiN7SZ8V9OjybF8loZDmHU= +github.com/go-delve/delve v1.2.0 h1:uwGyfYO0WsWqbnDWvxCBKOr2qFLpii3tLxwM+fTJs70= +github.com/go-delve/delve v1.2.0/go.mod h1:yP+LD36s/ud5nm4lsQY0TwNhYu2PAwk6xItz+442j74= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= +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-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1 h1:h+1eMw+tZAlgTVclcVN0/rdPaBI/RUzG0peblT6df+Q= +github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1/go.mod h1:TEo3Ghaj7PsZawQHxT/oBvo4HK/sl1RcuUHDKTTju+o= +github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4 h1:wVs9OMjICHbAryp9hcIuWqUOi+NqEbUSZy9zMe3W//I= +github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4/go.mod h1:c9CPdq2AzM8oPomdlPniEfPAC6g1s7NqZzODt8y6ib8= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6 h1:aTBUNRTatDDU24gbOEKEoLiDwxtc98ga6K/iMTm6fvs= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086 h1:EIMuvbE9fbtQtimdLe5yeXjuC5CeKbQt8zH6GwtIrhM= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30 h1:zRJPftZJNLPDiOtvYbFRwjSbaJAcVOf80TeEmWGe2kQ= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241 h1:ZRDeQioMGTBLeJxcPxXfFifEUgYxzR7fXw7w2WR+1bo= +github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676 h1:6Qrsp0+25KEkaS2bB26UE0giFgRrIc8mYXboDL5OVMA= +github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= +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-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.1.0 h1:0iH4Ffd/meGoXqF2lSAhZHt8X+cPgkfn/cb6Cce5Vpc= +github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +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/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6 h1:i2jIkQFb8RG45DuQs+ElyROY848cSJIoIkBM+7XXypA= +github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196 h1:9rtVlONXLF1rJZzvLt4tfOXtnAFUEhxCJ64Ibzj6ECo= +github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98 h1:ir6/L2ZOJfFrJlOTsuf/hlzdPuUwXV/VzkSlgS6f1vs= +github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.16.0 h1:PcWAN9JHflZzJQaZVY1JXZE0Tgjq+jO2v4QLqJ/Azvw= +github.com/golangci/golangci-lint v1.16.0/go.mod h1:uySrAxrUmZYnxyccYSnwuAEm+3144Zg5IAUueIW8+fA= +github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547 h1:qMomh8bv+kDazm1dSLZ9S3zZ2PJZMHL4ilfBjxFOlmI= +github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU= +github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde h1:qEGp3ZF1Qw6TkbWKn6GdJ12Ssu/CpJBaBcJ4hrUjrSo= +github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20180610141402-4bf9709227d1 h1:PHK2kIh21Zt4IcG0bBRzQwEDVKF64LnkoSXnm8lfJUk= +github.com/golangci/lint-1 v0.0.0-20180610141402-4bf9709227d1/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +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/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4 h1:gmIVMdGlVf5e6Yo6+ZklxdOrvtOvyrAjJyXAbmOznyo= +github.com/josharian/impl v0.0.0-20180228163738-3d0f908298c4/go.mod h1:t4Tr0tn92eq5ISef4cS5plFAMYAqZlAXtgUcKE6y8nw= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/gotags v1.4.1 h1:aWIyXsU3lTDqhsEC49MP85p2cUUWr2ptvdGNqqGA3r4= +github.com/jstemmer/gotags v1.4.1/go.mod h1:b6J3X0bsLbR4C5SgSx3V3KjuWTtmRzcmWPbTkWZ49PA= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/keegancsmith/rpc v1.1.0 h1:bXVRk3EzbtrEegTGKxNTc+St1lR7t/Z1PAO8misBnCc= +github.com/keegancsmith/rpc v1.1.0/go.mod h1:Xow74TKX34OPPiPCdz6x1o9c0SCxRqGxDuKGk7ZOo8s= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM= +github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/asmfmt v1.2.0 h1:zwsyBYgEdabg32alMful/5pRtMTcR5C5w1LKNg9OD78= +github.com/klauspost/asmfmt v1.2.0/go.mod h1:RAoUvqkWr2rUa2I19qKMEVZQe4BVtcHGTMCUOcCU2Lg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91 h1:hunjgdb3b21ZdRmzDPXii0EcnHpjH7uCP+kODoE1JH0= +github.com/koron/iferr v0.0.0-20180615142939-bb332a3b1d91/go.mod h1:C2tFh8w3I6i4lnUJfoBx2Hwku3mgu4wPNTtUNp1i5KI= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +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/mdempsky/gocode v0.0.0-20190203001940-7fb65232883f h1:ee+twVCignaZjt7jpbMSLxAeTN/Nfq9W/nm91E7QO1A= +github.com/mdempsky/gocode v0.0.0-20190203001940-7fb65232883f/go.mod h1:hltEC42XzfMNgg0S1v6JTywwra2Mu6F6cLR03debVQ8= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= +github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663 h1:Ri1EhipkbhWsffPJ3IPlrb4SkTOPa2PfRXp3jchBczw= +github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q= +github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= +github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/peterh/liner v1.1.0 h1:f+aAedNJA6uk7+6rXsYBnhdo4Xux7ESLe+kcuVUF5os= +github.com/peterh/liner v1.1.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v0.0.0-20170413231811-06b906832ed0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/profile v1.3.0/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrOUCzh1Y3Re6aJUUWRp2M9+Oc3eVn/54= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190528151240-3cb620ac02d0/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.8.0/go.mod h1:fSI0j+IUQrDd7+ZtR9WKIGtoYAYAJUKcKhYLG25tN4g= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/godef v1.1.1 h1:NujOtt9q9vIClRTB3sCZpavac+NMRaIayzrcz1h4fSE= +github.com/rogpeppe/godef v1.1.1/go.mod h1:oEo1eMy1VUEHUzUIX4F7IqvMJRiz9UId44mvnR8oPlQ= +github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sirupsen/logrus v0.0.0-20180523074243-ea8897e79973/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.4 h1:S0tLZ3VOKl2Te0hpq8+ke0eSJPfCnNTPiDlsfwi1/NE= +github.com/spf13/cobra v0.0.4/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/stamblerre/gocode v0.0.0-20190327203809-810592086997 h1:LF81AGV63kJoxjmSgQPT8FARAMHeY46CYQ4TNoVDWHM= +github.com/stamblerre/gocode v0.0.0-20190327203809-810592086997/go.mod h1:EM2T8YDoTCvGXbEpFHxarbpv7VE26QD1++Cb1Pbh7Gs= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.1 h1:gmervu+jDMvXTbcHQ0pd2wee85nEoE0BsVyEuzkfK8w= +github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.5-pre/go.mod h1:FwP/aQVg39TXzItUBMwnWp9T9gPQnXw4Poh4/oBQZ/0= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a h1:00UFliGZl2UciXe8o/2iuEsRQ9u7z0rzDTVzuj6EYY0= +github.com/zmb3/gogetdoc v0.0.0-20190228002656-b37376c5da6a/go.mod h1:ofmGw6LrMypycsiWcyug6516EXpIxSbZ+uI9ppGypfY= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/arch v0.0.0-20171004143515-077ac972c2e4/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= +golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c h1:Rx/HTKi09myZ25t1SOlDHmHOy/mKxNAcu0hP1oPX9qM= +golang.org/x/arch v0.0.0-20190312162104-788fe5ffcd8c/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= +golang.org/x/crypto v0.0.0-20180614174826-fd5f17ee7299/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180808211826-de0752318171 h1:vYogbvSFj2YXcjQxFHu/rASSOt9sLytpCaSkiwQ135I= +golang.org/x/crypto v0.0.0-20180808211826-de0752318171/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/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-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422 h1:QzoH/1pFpZguR8NrRHLcO6jKqfv2zpuSqZLgdm7ZmjI= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190509164839-32b2708ab171/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20181114220301-adae6a3d119a/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-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-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190523182746-aaccbc9213b0/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 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180614134839-8883426083c0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180808154034-904bdc257025 h1:vE4lpaOfhRi5ci1V4lyWFx2Rg3CXZNaN09Q1e+GKioA= +golang.org/x/sys v0.0.0-20180808154034-904bdc257025/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-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-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190529130038-5219a1e1c5f8 h1:2WjIC11WRITGlVWmyLXKjzIVj1ZwoWZ//tadeUUV6/o= +golang.org/x/sys v0.0.0-20190529130038-5219a1e1c5f8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180824175216-6c1c5e93cdc1/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181120060634-fc4f04983f62/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130195746-895048a75ecf/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181205014116-22934f0fdb62/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181207195948-8634b1ecd393/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-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190314010720-f0bfdbff1f9c/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190408220357-e5b8258f4918/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190529010454-aa71c3f32488 h1:vBgi/AgEje1rNScpWGJqe+RPHHZvBqrk9UH+LOXWN6Q= +golang.org/x/tools v0.0.0-20190529010454-aa71c3f32488/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.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-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= +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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +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/yaml.v2 v2.0.0-20170407172122-cd8b52f8269e/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +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= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34 h1:B1LAOfRqg2QUyCdzfjf46quTSYUTAK5OCwbh6pljHbM= +mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +sourcegraph.com/sourcegraph/go-diff v0.5.1-0.20190210232911-dee78e514455 h1:qoQ5Kt+Zm+GXBtz49YwD3juBhr/E0U25jO6bBzxW6NI= +sourcegraph.com/sourcegraph/go-diff v0.5.1-0.20190210232911-dee78e514455/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/manifest.yml b/manifest.yml new file mode 100644 index 0000000..973fef8 --- /dev/null +++ b/manifest.yml @@ -0,0 +1,11 @@ +--- +applications: +- instances: 1 + timeout: 180 + name: MyAppZIUGV + buildpack: go_buildpack + memory: 256M + domain: not-used.net + host: not-used + env: + GOPACKAGENAME : myappziugv diff --git a/plugins/prometheus_collector.go b/plugins/prometheus_collector.go new file mode 100644 index 0000000..9ab2da7 --- /dev/null +++ b/plugins/prometheus_collector.go @@ -0,0 +1,170 @@ +package plugins + +import ( + "github.com/afex/hystrix-go/hystrix/metric_collector" + "github.com/prometheus/client_golang/prometheus" + "log" + "strings" +) + +type PrometheusCollector struct { + circuitOpenPrefix string + attemptsPrefix string + errorsPrefix string + successesPrefix string + failuresPrefix string + rejectsPrefix string + shortCircuitsPrefix string + timeoutsPrefix string + fallbackSuccessesPrefix string + fallbackFailuresPrefix string + canceledPrefix string + deadlinePrefix string + totalDurationPrefix string + runDurationPrefix string + concurrencyInUsePrefix string + gauges map[string]*prometheus.Gauge + counters map[string]*prometheus.Counter + histograms map[string]*prometheus.Histogram +} + +type PrometheusCollectorClient struct { + namespace string +} + +// PrometheusCollectorConfig provides configuration for the prometheus client +type PrometheusCollectorConfig struct { + // Namespace is the prefix that will be prepended to all metrics sent from this collector. + Namespace string +} + +func InitializePrometheusCollector(config PrometheusCollectorConfig) *PrometheusCollectorClient { + return &PrometheusCollectorClient{ + namespace: strings.Replace(config.Namespace, "-", "_", -1), + } +} + +// NewPrometheusCollector creates a collector for a specific circuit. The +// prefix given to this circuit will be {config.Prefix}_{subsystem}_{metric}. +// Circuits with "/", ":", and "." in their names will have them replaced with "_". +func (client *PrometheusCollectorClient) NewPrometheusCollector(subsystem string) metricCollector.MetricCollector { + subsystem = strings.Replace(subsystem, "/", "_", -1) + subsystem = strings.Replace(subsystem, ":", "_", -1) + subsystem = strings.Replace(subsystem, ".", "_", -1) + c := PrometheusCollector{ + circuitOpenPrefix: "circuitOpen", + attemptsPrefix: "attempts", + errorsPrefix: "errors", + successesPrefix: "successes", + failuresPrefix: "failures", + rejectsPrefix: "rejects", + shortCircuitsPrefix: "shortCircuits", + timeoutsPrefix: "timeouts", + fallbackSuccessesPrefix: "fallbackSuccesses", + fallbackFailuresPrefix: "fallbackFailures", + canceledPrefix: "contextCanceled", + deadlinePrefix: "contextDeadlineExceeded", + totalDurationPrefix: "totalDuration", + runDurationPrefix: "runDuration", + concurrencyInUsePrefix: "concurrencyInUse", + } + c.gauges = make(map[string]*prometheus.Gauge) + c.counters = make(map[string]*prometheus.Counter) + c.histograms = make(map[string]*prometheus.Histogram) + + { + gague := prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: client.namespace, + Subsystem: subsystem, + Name: c.circuitOpenPrefix, + Help: "Generated hystrix metric to track " + c.circuitOpenPrefix + " for subsystem " + subsystem + ".", + }) + c.gauges[c.circuitOpenPrefix] = &gague + prometheus.MustRegister(gague) + } + + { + counters := []string{c.attemptsPrefix, c.errorsPrefix, c.successesPrefix, + c.failuresPrefix, c.rejectsPrefix, c.shortCircuitsPrefix, + c.timeoutsPrefix, c.fallbackSuccessesPrefix, c.fallbackFailuresPrefix, + c.canceledPrefix, c.deadlinePrefix} + for _, metric := range counters { + counter := prometheus.NewCounter(prometheus.CounterOpts{ + Namespace: client.namespace, + Subsystem: subsystem, + Name: metric, + Help: "Generated hystrix metric to track " + metric + " for subsystem " + subsystem + ".", + }) + c.counters[metric] = &counter + prometheus.MustRegister(counter) + } + } + + { + histograms := []string{c.totalDurationPrefix, c.runDurationPrefix, c.concurrencyInUsePrefix} + for _, metric := range histograms { + histogram := prometheus.NewHistogram(prometheus.HistogramOpts{ + Namespace: client.namespace, + Subsystem: subsystem, + Name: metric, + Help: "Generated hystrix metric to track " + metric + " for subsystem " + subsystem + ".", + }) + c.histograms[metric] = &histogram + prometheus.MustRegister(histogram) + } + } + return c +} + +func (c *PrometheusCollector) setGauge(metric string, value float64) { + if gauge, ok := c.gauges[metric]; ok { + (*gauge).Set(value) + } else { + log.Printf("Error: '%s' is not a valid gague", metric) + } +} + +func (c *PrometheusCollector) incrementCounterMetric(metric string, i float64) { + if i == 0 { + return + } + if counter, ok := c.counters[metric]; ok { + (*counter).Add(i) + } else { + log.Printf("Error: '%s' is not a valid counter", metric) + } +} + +func (c *PrometheusCollector) updateHistogramMetric(metric string, dur float64) { + if histogram, ok := c.histograms[metric]; ok { + (*histogram).Observe(dur) + } else { + log.Printf("Error: '%s' is not a valid timer", metric) + } +} + +func (c PrometheusCollector) Update(r metricCollector.MetricResult) { + if r.Successes > 0 { + c.setGauge(c.circuitOpenPrefix, 0) + } else if r.ShortCircuits > 0 { + c.setGauge(c.circuitOpenPrefix, 1) + } + + c.incrementCounterMetric(c.attemptsPrefix, r.Attempts) + c.incrementCounterMetric(c.errorsPrefix, r.Errors) + c.incrementCounterMetric(c.successesPrefix, r.Successes) + c.incrementCounterMetric(c.failuresPrefix, r.Failures) + c.incrementCounterMetric(c.rejectsPrefix, r.Rejects) + c.incrementCounterMetric(c.shortCircuitsPrefix, r.ShortCircuits) + c.incrementCounterMetric(c.timeoutsPrefix, r.Timeouts) + c.incrementCounterMetric(c.fallbackSuccessesPrefix, r.FallbackSuccesses) + c.incrementCounterMetric(c.fallbackFailuresPrefix, r.FallbackFailures) + c.incrementCounterMetric(c.canceledPrefix, r.ContextCanceled) + c.incrementCounterMetric(c.deadlinePrefix, r.ContextDeadlineExceeded) + c.updateHistogramMetric(c.totalDurationPrefix, r.TotalDuration.Seconds()) + c.updateHistogramMetric(c.runDurationPrefix, r.RunDuration.Seconds()) + c.updateHistogramMetric(c.concurrencyInUsePrefix, r.ConcurrencyInUse) +} + +// Reset is a noop operation in this collector. +func (c PrometheusCollector) Reset() {} diff --git a/routers/health.go b/routers/health.go new file mode 100644 index 0000000..a02fb3e --- /dev/null +++ b/routers/health.go @@ -0,0 +1,11 @@ +package routers + +import ( + "github.com/gin-gonic/gin" +) + +func HealthGET(c *gin.Context) { + c.JSON(200, gin.H{ + "status": "UP", + }) +} diff --git a/routers/health_test.go b/routers/health_test.go new file mode 100644 index 0000000..ac502da --- /dev/null +++ b/routers/health_test.go @@ -0,0 +1,28 @@ +package routers + +import ( + "testing" + "net/http/httptest" + "net/http" + "github.com/gin-gonic/gin" +) + +func TestHealth(t *testing.T) { + router := gin.Default() + router.GET("/health", HealthGET) + + w := httptest.NewRecorder() + req := httptest.NewRequest("GET", "/health", nil) + router.ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("You received a %v error.", w.Code) + } + + expected := "{\"status\":\"UP\"}" + actual := w.Body.String() + + if actual != expected { + t.Errorf("Response should be %v, was %v.", expected, actual) + } +} diff --git a/run-dev b/run-dev new file mode 100644 index 0000000..2976df1 --- /dev/null +++ b/run-dev @@ -0,0 +1,3 @@ +#!/bin/bash +# Simple shell script to run application in dev mode +go run server.go diff --git a/server.go b/server.go new file mode 100644 index 0000000..0536e25 --- /dev/null +++ b/server.go @@ -0,0 +1,146 @@ +package main + +import ( + "myappziugv/routers" + "myappziugv/plugins" + "github.com/gin-gonic/gin" + "github.com/gin-contrib/static" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/afex/hystrix-go/hystrix" + "github.com/afex/hystrix-go/hystrix/metric_collector" + // "github.com/opentracing/opentracing-go" + // "github.com/opentracing/opentracing-go/ext" + // "github.com/uber/jaeger-client-go" + // jaegerprom "github.com/uber/jaeger-lib/metrics/prometheus" + log "github.com/sirupsen/logrus" + "os" + "net/http" +) + +func port() string { + port := os.Getenv("PORT") + if len(port) == 0 { + port = "8080" + } + return ":" + port +} + +func HystrixHandler(command string) gin.HandlerFunc { + return func(c *gin.Context) { + hystrix.Do(command, func() error { + c.Next() + return nil + }, func(err error) error { + c.String(http.StatusInternalServerError, "500 Internal Server Error") + return err + }) + } +} + +func RequestTracker(counter *prometheus.CounterVec) gin.HandlerFunc { + return func(c *gin.Context) { + labels := map[string]string{"Route": c.Request.URL.Path, "Method": c.Request.Method} + counter.With(labels).Inc() + c.Next() + } +} + +// func OpenTracing() gin.HandlerFunc { +// return func(c *gin.Context) { +// wireCtx, _ := opentracing.GlobalTracer().Extract( +// opentracing.HTTPHeaders, +// opentracing.HTTPHeadersCarrier(c.Request.Header)) +// serverSpan := opentracing.StartSpan(c.Request.URL.Path, +// ext.RPCServerOption(wireCtx)) +// defer serverSpan.Finish() +// c.Request = c.Request.WithContext(opentracing.ContextWithSpan(c.Request.Context(), serverSpan)) +// c.Next() +// } +// } + +// type LogrusAdapter struct{} + +// func (l LogrusAdapter) Error(msg string) { +// log.Errorf(msg) +// } + +// func (l LogrusAdapter) Infof(msg string, args ...interface{}) { +// log.Infof(msg, args) +// } + + +func main() { + + log.SetFormatter(&log.JSONFormatter{}) + log.SetOutput(os.Stdout) + + // Adding Route Counter via Prometheus Metrics + counter := prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: "counters", + Subsystem: "page_requests", + Name: "request_count", + Help: "Number of requests received", + }, []string{"Route", "Method"}) + prometheus.MustRegister(counter) + + // Hystrix configuration + hystrix.ConfigureCommand("timeout", hystrix.CommandConfig{ + Timeout: 1000, + MaxConcurrentRequests: 100, + ErrorPercentThreshold: 25, + }) + //Add Hystrix to prometheus metrics + collector := plugins.InitializePrometheusCollector(plugins.PrometheusCollectorConfig{ + Namespace: "myappziugv", + }) + metricCollector.Registry.Register(collector.NewPrometheusCollector) + + //And jaeger metrics and reporting to prometheus route + // logAdapt := LogrusAdapter{} + // factory := jaegerprom.New() + // metrics := jaeger.NewMetrics(factory, map[string]string{"lib": "jaeger"}) + + // Add tracing to application + // transport, err := jaeger.NewUDPTransport("localhost:5775", 0) + // if err != nil { + // log.Errorln(err.Error()) + // } + + // reporter := jaeger.NewCompositeReporter( + // jaeger.NewLoggingReporter(logAdapt), + // jaeger.NewRemoteReporter(transport, + // jaeger.ReporterOptions.Metrics(metrics), + // jaeger.ReporterOptions.Logger(logAdapt), + // ), + // ) + // defer reporter.Close() + + // sampler := jaeger.NewConstSampler(true) + // tracer, closer := jaeger.NewTracer("myappziugv", + // sampler, + // reporter, + // jaeger.TracerOptions.Metrics(metrics), + // ) + // defer closer.Close() + + // opentracing.SetGlobalTracer(tracer) + + router := gin.Default() + router.RedirectTrailingSlash = false + + router.Use(RequestTracker(counter)) + // router.Use(OpenTracing()) + router.Use(HystrixHandler("timeout")) + + router.GET("/metrics", gin.WrapH(promhttp.Handler())) + router.Use(static.Serve("/", static.LocalFile("./public", false))) + router.GET("/", func(c *gin.Context) { + c.String(http.StatusOK, "You are now running a blank Go application") + }) + router.GET("/health", routers.HealthGET) + + log.Info("Starting MyAppZIUGV on port " + port()) + + router.Run(port()) +} \ No newline at end of file