From a4000bf5f79122fab49beeb3f251a53f3792ce4e Mon Sep 17 00:00:00 2001 From: Vernon Keenan Date: Sun, 10 Jan 2021 10:16:20 -0800 Subject: [PATCH] v0.0.3 --- Makefile | 1 - api/auth/auth_client/auth_client.go | 116 +++++++ .../auth_client/user/get_users_parameters.go | 150 +++++++++ .../auth_client/user/get_users_responses.go | 268 +++++++++++++++ api/auth/auth_client/user/user_client.go | 79 +++++ api/auth/auth_models/address.go | 65 ++++ api/auth/auth_models/error.go | 53 +++ api/auth/auth_models/response_meta.go | 77 +++++ api/auth/auth_models/tenant_user.go | 92 ++++++ api/auth/auth_models/user.go | 306 ++++++++++++++++++ api/auth/auth_models/user_response.go | 109 +++++++ api/auth/auth_models/user_role.go | 83 +++++ app/auth0.go | 67 ++++ app/config.go | 176 ++++++++++ app/logger/logger.go | 43 +++ app/prometheus.go | 67 ++++ app/root.go | 45 +++ app/user-helpers.go | 134 ++++++++ app/user.go | 117 +++++++ go.mod | 4 + go.sum | 279 ++++++++++++++++ 21 files changed, 2330 insertions(+), 1 deletion(-) create mode 100644 api/auth/auth_client/auth_client.go create mode 100644 api/auth/auth_client/user/get_users_parameters.go create mode 100644 api/auth/auth_client/user/get_users_responses.go create mode 100644 api/auth/auth_client/user/user_client.go create mode 100644 api/auth/auth_models/address.go create mode 100644 api/auth/auth_models/error.go create mode 100644 api/auth/auth_models/response_meta.go create mode 100644 api/auth/auth_models/tenant_user.go create mode 100644 api/auth/auth_models/user.go create mode 100644 api/auth/auth_models/user_response.go create mode 100644 api/auth/auth_models/user_role.go create mode 100644 app/auth0.go create mode 100644 app/config.go create mode 100644 app/logger/logger.go create mode 100644 app/prometheus.go create mode 100644 app/root.go create mode 100644 app/user-helpers.go create mode 100644 app/user.go diff --git a/Makefile b/Makefile index 47b1680..19145fe 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,6 @@ swagger: # # generate auth0 # - rm -rf ./api mkdir -p api/auth0 swagger generate client \ --log-output=./swagger/logs/generate-auth0-client.log \ diff --git a/api/auth/auth_client/auth_client.go b/api/auth/auth_client/auth_client.go new file mode 100644 index 0000000..31dfc1e --- /dev/null +++ b/api/auth/auth_client/auth_client.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_client + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/runtime" + httptransport "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + + "code.tnxs.net/taxnexus/lib/api/auth/auth_client/user" +) + +// Default auth HTTP client. +var Default = NewHTTPClient(nil) + +const ( + // DefaultHost is the default Host + // found in Meta (info) section of spec file + DefaultHost string = "auth.fabric.tnxs.net:8080" + // DefaultBasePath is the default BasePath + // found in Meta (info) section of spec file + DefaultBasePath string = "/v1" +) + +// DefaultSchemes are the default schemes found in Meta (info) section of spec file +var DefaultSchemes = []string{"http"} + +// NewHTTPClient creates a new auth HTTP client. +func NewHTTPClient(formats strfmt.Registry) *Auth { + return NewHTTPClientWithConfig(formats, nil) +} + +// NewHTTPClientWithConfig creates a new auth HTTP client, +// using a customizable transport config. +func NewHTTPClientWithConfig(formats strfmt.Registry, cfg *TransportConfig) *Auth { + // ensure nullable parameters have default + if cfg == nil { + cfg = DefaultTransportConfig() + } + + // create transport and client + transport := httptransport.New(cfg.Host, cfg.BasePath, cfg.Schemes) + return New(transport, formats) +} + +// New creates a new auth client +func New(transport runtime.ClientTransport, formats strfmt.Registry) *Auth { + // ensure nullable parameters have default + if formats == nil { + formats = strfmt.Default + } + + cli := new(Auth) + cli.Transport = transport + cli.User = user.New(transport, formats) + return cli +} + +// DefaultTransportConfig creates a TransportConfig with the +// default settings taken from the meta section of the spec file. +func DefaultTransportConfig() *TransportConfig { + return &TransportConfig{ + Host: DefaultHost, + BasePath: DefaultBasePath, + Schemes: DefaultSchemes, + } +} + +// TransportConfig contains the transport related info, +// found in the meta section of the spec file. +type TransportConfig struct { + Host string + BasePath string + Schemes []string +} + +// WithHost overrides the default host, +// provided by the meta section of the spec file. +func (cfg *TransportConfig) WithHost(host string) *TransportConfig { + cfg.Host = host + return cfg +} + +// WithBasePath overrides the default basePath, +// provided by the meta section of the spec file. +func (cfg *TransportConfig) WithBasePath(basePath string) *TransportConfig { + cfg.BasePath = basePath + return cfg +} + +// WithSchemes overrides the default schemes, +// provided by the meta section of the spec file. +func (cfg *TransportConfig) WithSchemes(schemes []string) *TransportConfig { + cfg.Schemes = schemes + return cfg +} + +// Auth is a client for auth +type Auth struct { + User user.ClientService + + Transport runtime.ClientTransport +} + +// SetTransport changes the transport on the client and all its subresources +func (c *Auth) SetTransport(transport runtime.ClientTransport) { + c.Transport = transport + c.User.SetTransport(transport) +} diff --git a/api/auth/auth_client/user/get_users_parameters.go b/api/auth/auth_client/user/get_users_parameters.go new file mode 100644 index 0000000..0af1810 --- /dev/null +++ b/api/auth/auth_client/user/get_users_parameters.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package user + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" +) + +// NewGetUsersParams creates a new GetUsersParams object +// with the default values initialized. +func NewGetUsersParams() *GetUsersParams { + var () + return &GetUsersParams{ + + timeout: cr.DefaultTimeout, + } +} + +// NewGetUsersParamsWithTimeout creates a new GetUsersParams object +// with the default values initialized, and the ability to set a timeout on a request +func NewGetUsersParamsWithTimeout(timeout time.Duration) *GetUsersParams { + var () + return &GetUsersParams{ + + timeout: timeout, + } +} + +// NewGetUsersParamsWithContext creates a new GetUsersParams object +// with the default values initialized, and the ability to set a context for a request +func NewGetUsersParamsWithContext(ctx context.Context) *GetUsersParams { + var () + return &GetUsersParams{ + + Context: ctx, + } +} + +// NewGetUsersParamsWithHTTPClient creates a new GetUsersParams object +// with the default values initialized, and the ability to set a custom HTTPClient for a request +func NewGetUsersParamsWithHTTPClient(client *http.Client) *GetUsersParams { + var () + return &GetUsersParams{ + HTTPClient: client, + } +} + +/*GetUsersParams contains all the parameters to send to the API endpoint +for the get users operation typically these are written to a http.Request +*/ +type GetUsersParams struct { + + /*Apikey + Service account or developer API key + + */ + Apikey *string + + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithTimeout adds the timeout to the get users params +func (o *GetUsersParams) WithTimeout(timeout time.Duration) *GetUsersParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the get users params +func (o *GetUsersParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the get users params +func (o *GetUsersParams) WithContext(ctx context.Context) *GetUsersParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the get users params +func (o *GetUsersParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the get users params +func (o *GetUsersParams) WithHTTPClient(client *http.Client) *GetUsersParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the get users params +func (o *GetUsersParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WithApikey adds the apikey to the get users params +func (o *GetUsersParams) WithApikey(apikey *string) *GetUsersParams { + o.SetApikey(apikey) + return o +} + +// SetApikey adds the apikey to the get users params +func (o *GetUsersParams) SetApikey(apikey *string) { + o.Apikey = apikey +} + +// WriteToRequest writes these params to a swagger request +func (o *GetUsersParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + + if o.Apikey != nil { + + // query param apikey + var qrApikey string + if o.Apikey != nil { + qrApikey = *o.Apikey + } + qApikey := qrApikey + if qApikey != "" { + if err := r.SetQueryParam("apikey", qApikey); err != nil { + return err + } + } + + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/api/auth/auth_client/user/get_users_responses.go b/api/auth/auth_client/user/get_users_responses.go new file mode 100644 index 0000000..44c934f --- /dev/null +++ b/api/auth/auth_client/user/get_users_responses.go @@ -0,0 +1,268 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package user + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "io" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + + "code.tnxs.net/taxnexus/lib/api/auth/auth_models" +) + +// GetUsersReader is a Reader for the GetUsers structure. +type GetUsersReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *GetUsersReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewGetUsersOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + case 401: + result := NewGetUsersUnauthorized() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + case 403: + result := NewGetUsersForbidden() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + case 404: + result := NewGetUsersNotFound() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + case 422: + result := NewGetUsersUnprocessableEntity() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + case 500: + result := NewGetUsersInternalServerError() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result + + default: + return nil, runtime.NewAPIError("unknown error", response, response.Code()) + } +} + +// NewGetUsersOK creates a GetUsersOK with default headers values +func NewGetUsersOK() *GetUsersOK { + return &GetUsersOK{} +} + +/*GetUsersOK handles this case with default header values. + +Taxnexus Response with User objects +*/ +type GetUsersOK struct { + Payload *auth_models.UserResponse +} + +func (o *GetUsersOK) Error() string { + return fmt.Sprintf("[GET /users][%d] getUsersOK %+v", 200, o.Payload) +} + +func (o *GetUsersOK) GetPayload() *auth_models.UserResponse { + return o.Payload +} + +func (o *GetUsersOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(auth_models.UserResponse) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetUsersUnauthorized creates a GetUsersUnauthorized with default headers values +func NewGetUsersUnauthorized() *GetUsersUnauthorized { + return &GetUsersUnauthorized{} +} + +/*GetUsersUnauthorized handles this case with default header values. + +Access Unauthorized, invalid API-KEY was used +*/ +type GetUsersUnauthorized struct { + Payload *auth_models.Error +} + +func (o *GetUsersUnauthorized) Error() string { + return fmt.Sprintf("[GET /users][%d] getUsersUnauthorized %+v", 401, o.Payload) +} + +func (o *GetUsersUnauthorized) GetPayload() *auth_models.Error { + return o.Payload +} + +func (o *GetUsersUnauthorized) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(auth_models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetUsersForbidden creates a GetUsersForbidden with default headers values +func NewGetUsersForbidden() *GetUsersForbidden { + return &GetUsersForbidden{} +} + +/*GetUsersForbidden handles this case with default header values. + +Access forbidden, account lacks access +*/ +type GetUsersForbidden struct { + Payload *auth_models.Error +} + +func (o *GetUsersForbidden) Error() string { + return fmt.Sprintf("[GET /users][%d] getUsersForbidden %+v", 403, o.Payload) +} + +func (o *GetUsersForbidden) GetPayload() *auth_models.Error { + return o.Payload +} + +func (o *GetUsersForbidden) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(auth_models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetUsersNotFound creates a GetUsersNotFound with default headers values +func NewGetUsersNotFound() *GetUsersNotFound { + return &GetUsersNotFound{} +} + +/*GetUsersNotFound handles this case with default header values. + +Resource was not found +*/ +type GetUsersNotFound struct { + Payload *auth_models.Error +} + +func (o *GetUsersNotFound) Error() string { + return fmt.Sprintf("[GET /users][%d] getUsersNotFound %+v", 404, o.Payload) +} + +func (o *GetUsersNotFound) GetPayload() *auth_models.Error { + return o.Payload +} + +func (o *GetUsersNotFound) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(auth_models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetUsersUnprocessableEntity creates a GetUsersUnprocessableEntity with default headers values +func NewGetUsersUnprocessableEntity() *GetUsersUnprocessableEntity { + return &GetUsersUnprocessableEntity{} +} + +/*GetUsersUnprocessableEntity handles this case with default header values. + +Unprocessable Entity, likely a bad parameter +*/ +type GetUsersUnprocessableEntity struct { + Payload *auth_models.Error +} + +func (o *GetUsersUnprocessableEntity) Error() string { + return fmt.Sprintf("[GET /users][%d] getUsersUnprocessableEntity %+v", 422, o.Payload) +} + +func (o *GetUsersUnprocessableEntity) GetPayload() *auth_models.Error { + return o.Payload +} + +func (o *GetUsersUnprocessableEntity) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(auth_models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetUsersInternalServerError creates a GetUsersInternalServerError with default headers values +func NewGetUsersInternalServerError() *GetUsersInternalServerError { + return &GetUsersInternalServerError{} +} + +/*GetUsersInternalServerError handles this case with default header values. + +Server Internal Error +*/ +type GetUsersInternalServerError struct { + Payload *auth_models.Error +} + +func (o *GetUsersInternalServerError) Error() string { + return fmt.Sprintf("[GET /users][%d] getUsersInternalServerError %+v", 500, o.Payload) +} + +func (o *GetUsersInternalServerError) GetPayload() *auth_models.Error { + return o.Payload +} + +func (o *GetUsersInternalServerError) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + o.Payload = new(auth_models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} diff --git a/api/auth/auth_client/user/user_client.go b/api/auth/auth_client/user/user_client.go new file mode 100644 index 0000000..735bf55 --- /dev/null +++ b/api/auth/auth_client/user/user_client.go @@ -0,0 +1,79 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package user + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" +) + +// New creates a new user API client. +func New(transport runtime.ClientTransport, formats strfmt.Registry) ClientService { + return &Client{transport: transport, formats: formats} +} + +/* +Client for user API +*/ +type Client struct { + transport runtime.ClientTransport + formats strfmt.Registry +} + +// ClientService is the interface for Client methods +type ClientService interface { + GetUsers(params *GetUsersParams, authInfo runtime.ClientAuthInfoWriter) (*GetUsersOK, error) + + SetTransport(transport runtime.ClientTransport) +} + +/* + GetUsers checks API key + + Checks for a valid API key, and returns full user record +*/ +func (a *Client) GetUsers(params *GetUsersParams, authInfo runtime.ClientAuthInfoWriter) (*GetUsersOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewGetUsersParams() + } + + result, err := a.transport.Submit(&runtime.ClientOperation{ + ID: "getUsers", + Method: "GET", + PathPattern: "/users", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http"}, + Params: params, + Reader: &GetUsersReader{formats: a.formats}, + AuthInfo: authInfo, + Context: params.Context, + Client: params.HTTPClient, + }) + if err != nil { + return nil, err + } + success, ok := result.(*GetUsersOK) + if ok { + return success, nil + } + // unexpected success response + // safeguard: normally, absent a default response, unknown success responses return an error above: so this is a codegen issue + msg := fmt.Sprintf("unexpected success response for getUsers: API contract not enforced by server. Client expected to get an error, but got: %T", result) + panic(msg) +} + +// SetTransport changes the transport on the client +func (a *Client) SetTransport(transport runtime.ClientTransport) { + a.transport = transport +} diff --git a/api/auth/auth_models/address.go b/api/auth/auth_models/address.go new file mode 100644 index 0000000..b740ab8 --- /dev/null +++ b/api/auth/auth_models/address.go @@ -0,0 +1,65 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// Address address +// +// swagger:model Address +type Address struct { + + // City + City string `json:"City,omitempty"` + + // Country full name + Country string `json:"Country,omitempty"` + + // Country Code + CountryCode string `json:"CountryCode,omitempty"` + + // Postal Code + PostalCode string `json:"PostalCode,omitempty"` + + // State full name + State string `json:"State,omitempty"` + + // State Code + StateCode string `json:"StateCode,omitempty"` + + // Street number and name + Street string `json:"Street,omitempty"` +} + +// Validate validates this address +func (m *Address) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *Address) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *Address) UnmarshalBinary(b []byte) error { + var res Address + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/api/auth/auth_models/error.go b/api/auth/auth_models/error.go new file mode 100644 index 0000000..413b019 --- /dev/null +++ b/api/auth/auth_models/error.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// Error error +// +// swagger:model Error +type Error struct { + + // code + Code int32 `json:"Code,omitempty"` + + // fields + Fields string `json:"Fields,omitempty"` + + // message + Message string `json:"Message,omitempty"` +} + +// Validate validates this error +func (m *Error) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *Error) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *Error) UnmarshalBinary(b []byte) error { + var res Error + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/api/auth/auth_models/response_meta.go b/api/auth/auth_models/response_meta.go new file mode 100644 index 0000000..eeb7c1e --- /dev/null +++ b/api/auth/auth_models/response_meta.go @@ -0,0 +1,77 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ResponseMeta response meta +// +// swagger:model ResponseMeta +type ResponseMeta struct { + + // Microservice Contact Info + Contact string `json:"Contact,omitempty"` + + // Copyright Info + Copyright string `json:"Copyright,omitempty"` + + // License Information and Restrictions + License string `json:"License,omitempty"` + + // Operation ID + OperationID string `json:"OperationID,omitempty"` + + // Request IP Address + RequestIP string `json:"RequestIP,omitempty"` + + // Request Type + RequestType string `json:"RequestType,omitempty"` + + // Request URL + RequestURL string `json:"RequestURL,omitempty"` + + // Data Server Info + ServerInfo string `json:"ServerInfo,omitempty"` + + // Data Server Response Time (ms) + ServerResponseTime string `json:"ServerResponseTime,omitempty"` + + // Backend Server Timestamp + ServerTimestamp string `json:"ServerTimestamp,omitempty"` + + // Taxnexus Account Number used for recording transactions + TaxnexusAccount string `json:"TaxnexusAccount,omitempty"` +} + +// Validate validates this response meta +func (m *ResponseMeta) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ResponseMeta) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ResponseMeta) UnmarshalBinary(b []byte) error { + var res ResponseMeta + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/api/auth/auth_models/tenant_user.go b/api/auth/auth_models/tenant_user.go new file mode 100644 index 0000000..36c042d --- /dev/null +++ b/api/auth/auth_models/tenant_user.go @@ -0,0 +1,92 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// TenantUser Relationship object that connects users to a tenant +// +// swagger:model TenantUser +type TenantUser struct { + + // The makeTenantUser access level for this User + AccessLevel string `json:"AccessLevel,omitempty"` + + // Account ID + AccountID string `json:"AccountID,omitempty"` + + // Auth0 User ID + Auth0UserID string `json:"Auth0UserID,omitempty"` + + // Account Name + CompanyName string `json:"CompanyName,omitempty"` + + // Contact ID + ContactID string `json:"ContactID,omitempty"` + + // Taxnexus Account + TaxnexusAccount string `json:"TaxnexusAccount,omitempty"` + + // Tenant active? + TenantActive bool `json:"TenantActive,omitempty"` + + // The Tenant ID + TenantID string `json:"TenantID,omitempty"` + + // Tenant Name + TenantName string `json:"TenantName,omitempty"` + + // Tenant Status + TenantStatus string `json:"TenantStatus,omitempty"` + + // Tenant type + TenantType string `json:"TenantType,omitempty"` + + // Tenant Version + TenantVersion string `json:"TenantVersion,omitempty"` + + // User Email Address + UserEmail string `json:"UserEmail,omitempty"` + + // User Full Name + UserFullName string `json:"UserFullName,omitempty"` + + // The User ID + UserID string `json:"UserID,omitempty"` + + // Username + Username string `json:"Username,omitempty"` +} + +// Validate validates this tenant user +func (m *TenantUser) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *TenantUser) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *TenantUser) UnmarshalBinary(b []byte) error { + var res TenantUser + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/api/auth/auth_models/user.go b/api/auth/auth_models/user.go new file mode 100644 index 0000000..5233a6c --- /dev/null +++ b/api/auth/auth_models/user.go @@ -0,0 +1,306 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// User user +// +// swagger:model User +type User struct { + + // API Key + APIKey string `json:"APIKey,omitempty"` + + // About Me + AboutMe string `json:"AboutMe,omitempty"` + + // Account ID + AccountID string `json:"AccountID,omitempty"` + + // address + Address *Address `json:"Address,omitempty"` + + // Alias + Alias string `json:"Alias,omitempty"` + + // Auth0 User Id + Auth0UserID string `json:"Auth0UserID,omitempty"` + + // Nickname + CommunityNickname string `json:"CommunityNickname,omitempty"` + + // Company Name + CompanyName string `json:"CompanyName,omitempty"` + + // Contact + ContactID string `json:"ContactID,omitempty"` + + // Created User ID + CreatedByID string `json:"CreatedByID,omitempty"` + + // Date Created + CreatedDate string `json:"CreatedDate,omitempty"` + + // Delegated Approver + DelegatedApproverID string `json:"DelegatedApproverID,omitempty"` + + // Department + Department string `json:"Department,omitempty"` + + // Division + Division string `json:"Division,omitempty"` + + // Email address + Email string `json:"Email,omitempty"` + + // Employee Number + EmployeeNumber string `json:"EmployeeNumber,omitempty"` + + // Time day ends + EndOfDay string `json:"EndOfDay,omitempty"` + + // Environment + Environment string `json:"Environment,omitempty"` + + // Extension + Extension string `json:"Extension,omitempty"` + + // Fabric API Key + FabricAPIKey string `json:"FabricAPIKey,omitempty"` + + // Fax + Fax string `json:"Fax,omitempty"` + + // The first name + FirstName string `json:"FirstName,omitempty"` + + // Allow Forecasting + ForecastEnabled bool `json:"ForecastEnabled,omitempty"` + + // Full Photo URL + FullPhotoURL string `json:"FullPhotoURL,omitempty"` + + // Taxnexus ID + ID string `json:"ID,omitempty"` + + // Active + IsActive bool `json:"IsActive,omitempty"` + + // Is the user enabled for Communities? + IsPortalEnabled bool `json:"IsPortalEnabled,omitempty"` + + // Has Profile Photo + IsProphilePhotoActive bool `json:"IsProphilePhotoActive,omitempty"` + + // is system controlled + IsSystemControlled bool `json:"IsSystemControlled,omitempty"` + + // IP address of last login + LastIP string `json:"LastIP,omitempty"` + + // Last login time + LastLogin string `json:"LastLogin,omitempty"` + + // Last Modified User ID + LastModifiedByID string `json:"LastModifiedByID,omitempty"` + + // Last Modified Date + LastModifiedDate string `json:"LastModifiedDate,omitempty"` + + // The Last Name + LastName string `json:"LastName,omitempty"` + + // Number of times user has logged in + LoginCount int64 `json:"LoginCount,omitempty"` + + // Manager + ManagerID string `json:"ManagerID,omitempty"` + + // Mobile + MobilePhone string `json:"MobilePhone,omitempty"` + + // Name + Name string `json:"Name,omitempty"` + + // Out of office message + OutOfOfficeMessage string `json:"OutOfOfficeMessage,omitempty"` + + // Phone + Phone string `json:"Phone,omitempty"` + + // Portal Role Level + PortalRole string `json:"PortalRole,omitempty"` + + // Profile + ProfileID string `json:"ProfileID,omitempty"` + + // Info Emails + ReceivesAdminEmails bool `json:"ReceivesAdminEmails,omitempty"` + + // Admin Info Emails + ReceivesAdminInfoEmails bool `json:"ReceivesAdminInfoEmails,omitempty"` + + // Email Sender Address + SenderEmail string `json:"SenderEmail,omitempty"` + + // Email Sender Name + SenderName string `json:"SenderName,omitempty"` + + // Email Signature + Signature string `json:"Signature,omitempty"` + + // Small Photo URL + SmallPhotoURL string `json:"SmallPhotoURL,omitempty"` + + // The time day starts + StartOfDay string `json:"StartOfDay,omitempty"` + + // Taxnexus Account + TaxnexusAccount string `json:"TaxnexusAccount,omitempty"` + + // Tenant ID associated with this user + TenantID string `json:"TenantID,omitempty"` + + // tenant users + TenantUsers []*TenantUser `json:"TenantUsers"` + + // Time Zone + TimeZone string `json:"TimeZone,omitempty"` + + // Title + Title string `json:"Title,omitempty"` + + // Role + UserRoleID string `json:"UserRoleID,omitempty"` + + // user roles + UserRoles []*UserRole `json:"UserRoles"` + + // User Type + UserType string `json:"UserType,omitempty"` + + // Username + Username string `json:"Username,omitempty"` +} + +// Validate validates this user +func (m *User) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateAddress(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTenantUsers(formats); err != nil { + res = append(res, err) + } + + if err := m.validateUserRoles(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *User) validateAddress(formats strfmt.Registry) error { + + if swag.IsZero(m.Address) { // not required + return nil + } + + if m.Address != nil { + if err := m.Address.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Address") + } + return err + } + } + + return nil +} + +func (m *User) validateTenantUsers(formats strfmt.Registry) error { + + if swag.IsZero(m.TenantUsers) { // not required + return nil + } + + for i := 0; i < len(m.TenantUsers); i++ { + if swag.IsZero(m.TenantUsers[i]) { // not required + continue + } + + if m.TenantUsers[i] != nil { + if err := m.TenantUsers[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("TenantUsers" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +func (m *User) validateUserRoles(formats strfmt.Registry) error { + + if swag.IsZero(m.UserRoles) { // not required + return nil + } + + for i := 0; i < len(m.UserRoles); i++ { + if swag.IsZero(m.UserRoles[i]) { // not required + continue + } + + if m.UserRoles[i] != nil { + if err := m.UserRoles[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("UserRoles" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *User) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *User) UnmarshalBinary(b []byte) error { + var res User + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/api/auth/auth_models/user_response.go b/api/auth/auth_models/user_response.go new file mode 100644 index 0000000..7c5ab09 --- /dev/null +++ b/api/auth/auth_models/user_response.go @@ -0,0 +1,109 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// UserResponse An array Taxnexus user objects +// +// swagger:model UserResponse +type UserResponse struct { + + // data + Data []*User `json:"Data"` + + // meta + Meta *ResponseMeta `json:"Meta,omitempty"` +} + +// Validate validates this user response +func (m *UserResponse) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateData(formats); err != nil { + res = append(res, err) + } + + if err := m.validateMeta(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *UserResponse) validateData(formats strfmt.Registry) error { + + if swag.IsZero(m.Data) { // not required + return nil + } + + for i := 0; i < len(m.Data); i++ { + if swag.IsZero(m.Data[i]) { // not required + continue + } + + if m.Data[i] != nil { + if err := m.Data[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Data" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +func (m *UserResponse) validateMeta(formats strfmt.Registry) error { + + if swag.IsZero(m.Meta) { // not required + return nil + } + + if m.Meta != nil { + if err := m.Meta.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Meta") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *UserResponse) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *UserResponse) UnmarshalBinary(b []byte) error { + var res UserResponse + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/api/auth/auth_models/user_role.go b/api/auth/auth_models/user_role.go new file mode 100644 index 0000000..9ea2706 --- /dev/null +++ b/api/auth/auth_models/user_role.go @@ -0,0 +1,83 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// All Code Copyright(c) 2018-2020 by Taxnexus, Inc. +// All rights reserved worldwide. +// Proprietary product; unlicensed use is not allowed + +package auth_models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// UserRole Relationship object that connects user to a role +// +// swagger:model UserRole +type UserRole struct { + + // Account Id + AccountID string `json:"AccountID,omitempty"` + + // Linked role ID + Auth0RoleID string `json:"Auth0RoleID,omitempty"` + + // Auth0 User ID + Auth0UserID string `json:"Auth0UserID,omitempty"` + + // Company Name + CompanyName string `json:"CompanyName,omitempty"` + + // Contact ID + ContactID string `json:"ContactID,omitempty"` + + // Role description + RoleDescription string `json:"RoleDescription,omitempty"` + + // The Role ID + RoleID string `json:"RoleID,omitempty"` + + // Role Name + RoleName string `json:"RoleName,omitempty"` + + // Taxnexus Account Number + TaxnexusAccount string `json:"TaxnexusAccount,omitempty"` + + // User Email Address + UserEmail string `json:"UserEmail,omitempty"` + + // User Full Name + UserFullName string `json:"UserFullName,omitempty"` + + // The User ID + UserID string `json:"UserID,omitempty"` + + // Username + Username string `json:"Username,omitempty"` +} + +// Validate validates this user role +func (m *UserRole) Validate(formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *UserRole) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *UserRole) UnmarshalBinary(b []byte) error { + var res UserRole + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/app/auth0.go b/app/auth0.go new file mode 100644 index 0000000..6169701 --- /dev/null +++ b/app/auth0.go @@ -0,0 +1,67 @@ +package app + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + "time" +) + +type auth0TokenResponse struct { + AccessToken string + TokenType string +} + +const tokenURL = "https://taxnexus.auth0.com/oauth/token" +const tokenTimeout = 86400 * time.Second +const requestTemplate = ` +{ + "client_id": "%s", + "client_secret": "%s" + "audience": "%s", + "grant_type": "client_credentials" +} +` + +var accessToken string +var authTokenTime time.Time + +// GetAuth0AccessToken uses conf file values to get an Auth0 access token +func GetAuth0AccessToken() string { + if time.Now().Before(authTokenTime) && accessToken != "" { + return accessToken + } + serviceAccount := GetServiceAccount("auth0") + payload := strings.NewReader( + fmt.Sprintf(requestTemplate, + serviceAccount.ClientID, + serviceAccount.ClientSecret, + serviceAccount.Endpoint.Scheme+"://"+ + serviceAccount.Endpoint.Host+ + serviceAccount.Endpoint.BasePath) + "/") + req, err := http.NewRequest("POST", tokenURL, payload) + if err != nil { + return "" + } + req.Header.Add("content-type", "application/json") + + res, err := http.DefaultClient.Do(req) + if err != nil { + return "" + } + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return "" + } + var response *auth0TokenResponse + err = json.Unmarshal(body, response) + if err != nil { + return "" + } + accessToken = response.AccessToken + authTokenTime = time.Now().Add(tokenTimeout) + return accessToken +} diff --git a/app/config.go b/app/config.go new file mode 100644 index 0000000..2eb4375 --- /dev/null +++ b/app/config.go @@ -0,0 +1,176 @@ +package app + +import ( + "time" + + "code.tnxs.net/taxnexus/lib/app/logger" + "go.uber.org/zap/zapcore" +) + +// Worker is a struct +type Worker struct { + ChannelSize int64 `mapstructure:"channel_size,omitempty"` + WorkerCount int `mapstructure:"worker_count,omitempty"` +} + +type metrics struct { + Address string `mapstructure:"address,omitempty"` + Enabled bool `mapstructure:"enabled,omitempty"` +} + +type endpoint struct { + BasePath string `mapstructure:"base_path,omitempty"` + Host string `mapstructure:"host,omitempty"` + Scheme string `mapstructure:"scheme,omitempty"` +} + +type chunk struct { + size int32 `mapstructure:"size,omitempty"` +} + +// ServiceAccount is a struct +type ServiceAccount struct { + APIKey string `mapstructure:"api_key,omitempty"` + ApplicationName string `mapstructure:"application_name,omitempty"` + AuthenticationType string `mapstructure:"authentication_type,omitempty"` + BackendID string `mapstructure:"backend_id,omitempty"` + ClientID string `mapstructure:"client_id,omitempty"` + ClientSecret string `mapstructure:"client_secret,omitempty"` + DSN string `mapstructure:"dsn,omitempty"` + Endpoint endpoint `mapstructure:"endpoint,omitempty"` + Password string `mapstructure:"password,omitempty"` + Production bool `mapstructure:"production,omitempty"` + SecurityToken string `mapstructure:"security_token,omitempty"` + Credentials string `mapstructure:"credentials,omitempty"` + Timeout time.Duration `mapstructure:"timeout,omitempty"` + Type string `mapstructure:"type,omitempty"` + Username string `mapstructure:"username,omitempty"` + Vendor string `mapstructure:"vendor,omitempty"` +} + +type configuration struct { + AppName string `mapstructure:"app_name,omitempty"` + BackendID string `mapstructure:"backend_id,omitempty"` + BuildEnv string `mapstructure:"build_env,omitempty"` + ClusterID string `mapstructure:"cluster_id,omitempty"` + Chunks map[string]chunk `mapstructure:"chunks,omitempty"` + DBMS string `mapstructure:"dbms,omitempty"` + DBMSHost string `mapstructure:"dbms_host,omitempty"` + DBMSName string `mapstructure:"dbms_name,omitempty"` + DBMSPassword string `mapstructure:"dbms_password,omitempty"` + DBMSUsername string `mapstructure:"dbms_username,omitempty"` + DSN string `mapstructure:"dsn,omitempty"` + Endpoint endpoint `mapstructure:"endpoint,omitempty"` + Environment string `mapstructure:"environment,omitempty"` + GelfURI string `mapstructure:"gelf_uri,omitempty"` + GitHubOrgName string `mapstructure:"git_hub_org_name,omitempty"` + LogLevel int `mapstructure:"log_level,omitempty"` + Metrics metrics `mapstructure:"metrics,omitempty"` + KafkaServer string `mapstructure:"kafka_server,omitempty"` + PDFRenderEngine string `mapstructure:"pdf_render_engine,omitempty"` + RegistryPriv string `mapstructure:"registry_priv,omitempty"` + RegistryPublic string `mapstructure:"registry_public,omitempty"` + RepoName string `mapstructure:"repo_name,omitempty"` + ServiceAccounts map[string]ServiceAccount `mapstructure:"service_accounts,omitempty"` + ShutdownTimeout time.Duration `mapstructure:"shutdown_timeout,omitempty"` + Version string `mapstructure:"version,omitempty"` + Workers map[string]Worker `mapstructure:"workers,omitempty"` +} + +// GetPDFRenderEngine returns a config file parameter +func GetPDFRenderEngine() string { + return config.PDFRenderEngine +} + +// GetKafkaServer returns a config file parameter +func GetKafkaServer() string { + if config.KafkaServer != "" { + return config.KafkaServer + } + return "nats.fabric.tnxs.net" +} + +// GetChunkSize returns a config file parameter +func GetChunkSize(chunkName string) int { + obj, ok := config.Chunks[chunkName] + if ok { + return int(obj.size) + } + return 0 +} + +// GetMetricsAddress return the metrics Address value +func GetMetricsAddress() string { + return config.Metrics.Address +} + +// IsMetrics returns TRUE if metrics enabled +func IsMetrics() bool { + return config.Metrics.Enabled +} + +// GetWorker returns the named worker record +func GetWorker(name string) *Worker { + worker, ok := config.Workers[name] + if ok { + return &worker + } + return nil +} + +// GetServiceAccount returns the named service account struct +func GetServiceAccount(name string) *ServiceAccount { + serviceaccount, ok := config.ServiceAccounts[name] + if ok { + return &serviceaccount + } + return nil +} + +// GetAppName retrieves the Taxnexus App Name for this microservice +func GetAppName() string { + return config.AppName +} + +// GetEnvironment retrieves the current runtime environment +func GetEnvironment() string { + return config.Environment +} + +// GetBackendID retrieves the backend ID +func GetBackendID() string { + return config.BackendID +} + +// GetClusterID retrieves the cluster ID +func GetClusterID() string { + return config.ClusterID +} + +// GetDSN retrieves the Taxnexus database DSN for this microservice +func GetDSN() string { + return config.DSN +} + +// GetDBMS retrieves the DBMS string +func GetDBMS() string { + return config.DBMS +} + +// GetLogLevel returns the Log Level +func GetLogLevel() zapcore.Level { + switch config.LogLevel { + case int(logger.DebugLevel): + return logger.DebugLevel + case int(logger.InfoLevel): + return logger.InfoLevel + case int(logger.WarnLevel): + return logger.WarnLevel + case int(logger.ErrorLevel): + return logger.ErrorLevel + case int(logger.PanicLevel): + return logger.PanicLevel + default: + return logger.DebugLevel + } +} diff --git a/app/logger/logger.go b/app/logger/logger.go new file mode 100644 index 0000000..9d2825b --- /dev/null +++ b/app/logger/logger.go @@ -0,0 +1,43 @@ +// Package logger wraps an external logging package +package logger + +import ( + "log" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +type logger = zap.SugaredLogger + +// DebugLevel is exported (5) +var DebugLevel = zapcore.DebugLevel + +// InfoLevel is exported (4) +var InfoLevel = zapcore.InfoLevel + +// WarnLevel is exported (3) +var WarnLevel = zapcore.WarnLevel + +// ErrorLevel is exported (2) +var ErrorLevel = zapcore.ErrorLevel + +// PanicLevel is exported (1) +var PanicLevel = zapcore.PanicLevel + +// New creates a new logger and returns it +func New(level zapcore.Level) *logger { + var theLogger *zap.Logger + var err error + if level == zapcore.DebugLevel { + theLogger, err = zap.NewDevelopment() + } else { + theLogger, err = zap.NewProduction() + } + if err != nil { + log.Fatal("logger.New: 💣 ⛔ zap logger init fail") + } + // theLogger.SetLevel + defer theLogger.Sync() + return theLogger.Sugar() +} diff --git a/app/prometheus.go b/app/prometheus.go new file mode 100644 index 0000000..77a32a4 --- /dev/null +++ b/app/prometheus.go @@ -0,0 +1,67 @@ +package app + +import ( + "fmt" + "net/http" + "time" + + "github.com/prometheus/client_golang/prometheus" + "github.com/rs/cors" +) + +var ( + namespace = "collage" + + counter = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Name: "endpoint_request_count", + Help: "collage request count.", + }, []string{"app", "name", "method", "state"}) + + histogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Namespace: namespace, + Name: "endpoint_duration_seconds", + Help: "Time taken to execute endpoint.", + }, []string{"app", "name", "method", "status"}) +) + +type metricResponseWriter struct { + http.ResponseWriter + statusCode int +} + +func newMetricResponseWriter(w http.ResponseWriter) *metricResponseWriter { + return &metricResponseWriter{w, http.StatusOK} +} + +func (lrw *metricResponseWriter) WriteHeader(code int) { + lrw.statusCode = code + lrw.ResponseWriter.WriteHeader(code) +} + +// SetupPrometheusHandler enable CORS, handler metrics +func SetupPrometheusHandler(handler http.Handler, app string) http.Handler { + sugar.Debug("app.SetupPrometheusHandler: 📥") + handleCORS := cors.AllowAll().Handler + h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + lrw := newMetricResponseWriter(w) + handler.ServeHTTP(lrw, r) + statusCode := lrw.statusCode + duration := time.Since(start) + histogram.WithLabelValues(app, r.URL.String(), r.Method, fmt.Sprintf("%d", statusCode)).Observe(duration.Seconds()) + counter.WithLabelValues(app, r.URL.String(), r.Method, fmt.Sprintf("%d", statusCode)).Inc() + }) + err := prometheus.Register(histogram) + if err != nil { + sugar.Errorf("app.SetupPrometheusHandler: 💣 ⛔ %w", err) + return nil + } + err = prometheus.Register(counter) + if err != nil { + sugar.Errorf("app.SetupPrometheusHandler: 💣 ⛔ %w", err) + return nil + } + sugar.Info("app.SetupPrometheusHandler: 👍 📤") + return handleCORS(h) +} diff --git a/app/root.go b/app/root.go new file mode 100644 index 0000000..d6b9027 --- /dev/null +++ b/app/root.go @@ -0,0 +1,45 @@ +// Package app is a utility package +package app + +import ( + "strings" + + "code.tnxs.net/taxnexus/lib/app/logger" + "github.com/spf13/viper" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +var sugar *zap.SugaredLogger +var config = configuration{} +var appViper = viper.New() + +// const dateTimeFormat = "2006-01-02T15:04:05-0800" + +var configured = false + +// InitConfig exports the config initialization func +func InitConfig(systemName string) { + if configured { + return + } + sugar = logger.New(zapcore.InfoLevel) + sugar.Info("app.InitConfig: 📥 %s", systemName) + appViper.SetConfigType("yaml") + appViper.SetConfigName(systemName) + appViper.AddConfigPath("/etc/taxnexus") + appViper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) + appViper.SetEnvPrefix("taxnexus") + appViper.AutomaticEnv() // read in environment variables that match + err := appViper.ReadInConfig() + if err != nil { + sugar.Fatalf("app.InitConfig: 💣 ⛔ can't read system config: %w", err) + } + err = appViper.Unmarshal(&config) + if err != nil { + sugar.Fatalf("app.InitConfig: 💣 ⛔ can't unmarshal system config: %w", err) + } + sugar = logger.New(GetLogLevel()) + sugar.Debugf("app.InitConfig: 👍 📤 serviceAccounts: %d", len(config.ServiceAccounts)) + configured = true +} diff --git a/app/user-helpers.go b/app/user-helpers.go new file mode 100644 index 0000000..2e5e78b --- /dev/null +++ b/app/user-helpers.go @@ -0,0 +1,134 @@ +package app + +import ( + "code.tnxs.net/taxnexus/lib/api/auth/auth_models" + httptransport "github.com/go-openapi/runtime/client" +) + +// MarshalAuthUserToSwagger is a helper function +func MarshalAuthUserToSwagger(obj *auth_models.User) *User { + var address *Address + if obj.Address != nil { + address = &Address{ + City: obj.Address.City, + Country: obj.Address.Country, + CountryCode: obj.Address.CountryCode, + PostalCode: obj.Address.PostalCode, + State: obj.Address.State, + StateCode: obj.Address.StateCode, + Street: obj.Address.Street, + } + } + var userRoles []*UserRole + if obj.UserRoles != nil { + userRoles = []*UserRole{} + for _, itm := range obj.UserRoles { + userRoles = append(userRoles, reMarshalUserRole(itm)) + } + } + var tenantUsers []*TenantUser + if obj.TenantUsers != nil { + tenantUsers = []*TenantUser{} + for _, itm := range obj.TenantUsers { + tenantUsers = append(tenantUsers, reMarshalTenantUser(itm)) + } + } + return &User{ + ID: obj.ID, + AboutMe: obj.AboutMe, + AccountID: obj.AccountID, + Address: address, + Alias: obj.Alias, + APIKey: obj.APIKey, + Auth: httptransport.APIKeyAuth("X-API-Key", "header", obj.APIKey), + Auth0UserID: obj.Auth0UserID, + CommunityNickname: obj.CommunityNickname, + CompanyName: obj.CompanyName, + ContactID: obj.ContactID, + CreatedByID: obj.CreatedByID, + CreatedDate: obj.CreatedDate, + DelegatedApproverID: obj.DelegatedApproverID, + Department: obj.Department, + Division: obj.Division, + Email: obj.Email, + EmployeeNumber: obj.EmployeeNumber, + EndOfDay: obj.EndOfDay, + Environment: obj.Environment, + Extension: obj.Extension, + FabricAPIKey: obj.FabricAPIKey, + Fax: obj.Fax, + FirstName: obj.FirstName, + ForecastEnabled: obj.ForecastEnabled, + FullPhotoURL: obj.FullPhotoURL, + IsActive: obj.IsActive, + IsPortalEnabled: obj.IsPortalEnabled, + IsProfilePhotoActive: obj.IsProphilePhotoActive, + IsSystemControlled: obj.IsSystemControlled, + LastIP: obj.LastIP, + LastLogin: obj.LastLogin, + LastModifiedByID: obj.LastModifiedByID, + LastModifiedDate: obj.LastModifiedDate, + LastName: obj.LastName, + LoginCount: obj.LoginCount, + ManagerID: obj.ManagerID, + MobilePhone: obj.MobilePhone, + Name: obj.Name, + OutOfOfficeMessage: obj.OutOfOfficeMessage, + Phone: obj.Phone, + PortalRole: obj.PortalRole, + ProfileID: obj.ProfileID, + ReceivesAdminEmails: obj.ReceivesAdminEmails, + ReceivesAdminInfoEmails: obj.ReceivesAdminInfoEmails, + SenderEmail: obj.SenderEmail, + SenderName: obj.SenderName, + Signature: obj.Signature, + SmallPhotoURL: obj.SmallPhotoURL, + StartOfDay: obj.StartOfDay, + TaxnexusAccount: obj.TaxnexusAccount, + TenantID: obj.TenantID, + TenantUsers: tenantUsers, + TimeZone: obj.TimeZone, + Title: obj.Title, + Username: obj.Username, + UserRoleID: obj.UserRoleID, + UserRoles: userRoles, + UserType: obj.UserType, + } +} +func reMarshalUserRole(s *auth_models.UserRole) *UserRole { + return &UserRole{ + AccountID: s.AccountID, + Auth0RoleID: s.Auth0RoleID, + Auth0UserID: s.Auth0UserID, + CompanyName: s.CompanyName, + ContactID: s.ContactID, + RoleDescription: s.RoleDescription, + RoleID: s.RoleID, + RoleName: s.RoleName, + TaxnexusAccount: s.TaxnexusAccount, + UserEmail: s.UserEmail, + UserFullName: s.UserFullName, + UserID: s.UserID, + Username: s.Username, + } +} +func reMarshalTenantUser(s *auth_models.TenantUser) *TenantUser { + return &TenantUser{ + AccessLevel: s.AccessLevel, + AccountID: s.AccountID, + Auth0UserID: s.Auth0UserID, + CompanyName: s.CompanyName, + ContactID: s.ContactID, + TaxnexusAccount: s.TaxnexusAccount, + TenantActive: s.TenantActive, + TenantID: s.TenantID, + TenantName: s.TenantName, + TenantStatus: s.TenantStatus, + TenantType: s.TenantType, + TenantVersion: s.TenantVersion, + UserEmail: s.UserEmail, + UserFullName: s.UserFullName, + UserID: s.UserID, + Username: s.Username, + } +} diff --git a/app/user.go b/app/user.go new file mode 100644 index 0000000..31bc5bb --- /dev/null +++ b/app/user.go @@ -0,0 +1,117 @@ +package app + +import ( + "github.com/go-openapi/runtime" +) + +// User is a fist-class object in the app package +type User struct { + ID string + AboutMe string + AccountID string + Address *Address + Alias string + APIKey string + Auth runtime.ClientAuthInfoWriter + Auth0UserID string + CommunityNickname string + CompanyName string + ContactID string + CreatedByID string + CreatedDate string + DelegatedApproverID string + Department string + Division string + Email string + EmployeeNumber string + EndOfDay string + Environment string + Extension string + FabricAPIKey string + Fax string + FirstName string + ForecastEnabled bool + FullPhotoURL string + IsActive bool + IsPortalEnabled bool + IsProfilePhotoActive bool + IsSystemControlled bool + LastIP string + LastLogin string + LastModifiedByID string + LastModifiedDate string + LastName string + LoginCount int64 + ManagerID string + MobilePhone string + Name string + OutOfOfficeMessage string + Phone string + PortalRole string + ProfileID string + ReceivesAdminEmails bool + ReceivesAdminInfoEmails bool + ReceivesInfoEmails bool + SenderEmail string + SenderName string + Signature string + SmallPhotoURL string + StartOfDay string + TaxnexusAccount string + TenantID string + TenantUsers []*TenantUser + TimeZone string + Title string + Username string + UserRoles []*UserRole + UserRoleID string + UserType string +} + +// UserRole is a fist-class object in the app package +type UserRole struct { + AccountID string + Auth0RoleID string + Auth0UserID string + CompanyName string + ContactID string + RoleDescription string + RoleID string + RoleName string + TaxnexusAccount string + UserEmail string + UserFullName string + UserID string + Username string +} + +// TenantUser is a fist-class object in the app package +type TenantUser struct { + AccessLevel string + AccountID string + Auth0UserID string + CompanyName string + ContactID string + TaxnexusAccount string + TenantActive bool + TenantID string + TenantName string + TenantStatus string + TenantType string + TenantVersion string + UserEmail string + UserFullName string + UserID string + Username string +} + +// Address is a fist-class object in the app package +type Address struct { + City string + Country string + CountryCode string + PostalCode string + State string + StateCode string + Street string +} diff --git a/go.mod b/go.mod index 8575dfe..d2dd4c0 100644 --- a/go.mod +++ b/go.mod @@ -8,4 +8,8 @@ require ( github.com/go-openapi/strfmt v0.19.11 github.com/go-openapi/swag v0.19.12 github.com/go-openapi/validate v0.20.0 + github.com/prometheus/client_golang v0.9.3 + github.com/rs/cors v1.7.0 + github.com/spf13/viper v1.7.1 + go.uber.org/zap v1.16.0 ) diff --git a/go.sum b/go.sum index 4b696fb..94e5c85 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,32 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/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/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= @@ -13,14 +34,36 @@ github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:o github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/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.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +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/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-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-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -129,32 +172,89 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-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/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-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/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +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/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -164,31 +264,85 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks= github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= +github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/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/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +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.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +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.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= 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= @@ -197,11 +351,16 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= @@ -209,19 +368,66 @@ go.mongodb.org/mongo-driver v1.3.4/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS go.mongodb.org/mongo-driver v1.4.3/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= go.mongodb.org/mongo-driver v1.4.4 h1:bsPHfODES+/yx2PCWzUYMH8xj6PVniPI8DQrsJuSXSs= go.mongodb.org/mongo-driver v1.4.4/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.16.0 h1:uFRZXykJGK9lLY4HtgSw44DnIcAM+kRBP7x5m+NpAOM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/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-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/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-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-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-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -229,42 +435,109 @@ golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/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-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +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-20180221164845-07fd8470d635/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-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc h1:NCy3Ohtk6Iny5V/reW2Ktypo4zIpWBdRJ1uFMjBxdg8= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -276,3 +549,9 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=