From 7bc59c92ae903e3b2c6d273ee5e7953b2a6160d1 Mon Sep 17 00:00:00 2001 From: Christian Stauffer <116654419+christian-stauffer@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:32:11 +0200 Subject: [PATCH] Initial commit --- .github/workflows/code-analysis.yml | 17 + .github/workflows/integration-test.yml | 17 + .gitignore | 5 + Dockerfile | 40 + LICENSE.md | 21 + README.md | 81 ++ apiserver/.openapi-generator-ignore | 9 + apiserver/api.go | 64 ++ apiserver/api_configuration.go | 101 ++ apiserver/api_customization.go | 77 ++ apiserver/api_version.go | 89 ++ apiserver/error.go | 62 ++ apiserver/helpers.go | 54 ++ apiserver/impl.go | 16 + apiserver/logger.go | 32 + apiserver/model_configuration.go | 37 + apiserver/model_dashboard.go | 67 ++ apiserver/model_widget.go | 65 ++ apiserver/model_widget_data.go | 43 + apiserver/openapi.json | 415 ++++++++ apiserver/routers.go | 218 +++++ apiservices/api_configuration_service.go | 56 ++ apiservices/api_customization_service.go | 42 + apiservices/api_version_service.go | 79 ++ app.go | 43 + conf/conf.go | 20 + conf/init.go | 31 + conf/init.sql | 20 + eliona/assets.go | 20 + eliona/init.go | 31 + generate-api-server.cmd | 21 + generate-api-server.sh | 14 + generate-db.cmd | 9 + generate-db.sh | 11 + go.mod | 40 + go.sum | 1101 ++++++++++++++++++++++ icon | 1 + inegration_test.go | 21 + install_hook.sh | 31 + main.go | 63 ++ metadata.json | 23 + openapi.yaml | 159 ++++ pipeline/build-pipeline.yml | 25 + pipeline/deploy-pipeline.yml | 24 + reset.sql | 68 ++ sqlboiler.toml | 30 + 46 files changed, 3513 insertions(+) create mode 100644 .github/workflows/code-analysis.yml create mode 100644 .github/workflows/integration-test.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 apiserver/.openapi-generator-ignore create mode 100644 apiserver/api.go create mode 100644 apiserver/api_configuration.go create mode 100644 apiserver/api_customization.go create mode 100644 apiserver/api_version.go create mode 100644 apiserver/error.go create mode 100644 apiserver/helpers.go create mode 100644 apiserver/impl.go create mode 100644 apiserver/logger.go create mode 100644 apiserver/model_configuration.go create mode 100644 apiserver/model_dashboard.go create mode 100644 apiserver/model_widget.go create mode 100644 apiserver/model_widget_data.go create mode 100644 apiserver/openapi.json create mode 100644 apiserver/routers.go create mode 100644 apiservices/api_configuration_service.go create mode 100644 apiservices/api_customization_service.go create mode 100644 apiservices/api_version_service.go create mode 100644 app.go create mode 100644 conf/conf.go create mode 100644 conf/init.go create mode 100644 conf/init.sql create mode 100644 eliona/assets.go create mode 100644 eliona/init.go create mode 100644 generate-api-server.cmd create mode 100755 generate-api-server.sh create mode 100644 generate-db.cmd create mode 100755 generate-db.sh create mode 100644 go.mod create mode 100644 go.sum create mode 100644 icon create mode 100644 inegration_test.go create mode 100755 install_hook.sh create mode 100644 main.go create mode 100644 metadata.json create mode 100644 openapi.yaml create mode 100644 pipeline/build-pipeline.yml create mode 100644 pipeline/deploy-pipeline.yml create mode 100644 reset.sql create mode 100644 sqlboiler.toml diff --git a/.github/workflows/code-analysis.yml b/.github/workflows/code-analysis.yml new file mode 100644 index 0000000..448d626 --- /dev/null +++ b/.github/workflows/code-analysis.yml @@ -0,0 +1,17 @@ +name: Code Analysis + +on: + workflow_dispatch: + pull_request: + types: + - opened + - synchronize + branches: + - master + schedule: + - cron: '0 0 * * *' # Runs the job at 00:00 UTC every day + +jobs: + app-integration-test: + uses: eliona-smart-building-assistant/app-integration-tests/.github/workflows/code-analysis.yml@main + secrets: inherit diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml new file mode 100644 index 0000000..73986dd --- /dev/null +++ b/.github/workflows/integration-test.yml @@ -0,0 +1,17 @@ +name: Integration Test + +on: + workflow_dispatch: + pull_request: + types: + - opened + - synchronize + branches: + - master + schedule: + - cron: '0 0 * * *' # Runs the job at 00:00 UTC every day + +jobs: + app-integration-test: + uses: eliona-smart-building-assistant/app-integration-tests/.github/workflows/app-integration-test.yml@main + secrets: inherit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5adbe0d --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.iml +.idea/** +apiserver/.openapi-generator/** +apiserver/api/** +apiserver/*_service.go \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..629d874 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +# This file is part of the eliona project. +# Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +# ______ _ _ +# | ____| (_) +# | |__ | |_ ___ _ __ __ _ +# | __| | | |/ _ \| '_ \ / _` | +# | |____| | | (_) | | | | (_| | +# |______|_|_|\___/|_| |_|\__,_| +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +FROM eliona/base-golang:latest-1-alpine AS build + +RUN apk add git + +WORKDIR / +COPY . ./ + +RUN go mod download +RUN go build -o ../app + +RUN DATE=$(date) && \ + GIT_COMMIT=$(git rev-list -1 HEAD) && \ + go build -ldflags "-X 'template/apiservices.BuildTimestamp=$DATE' -X 'template/apiservices.GitCommit=$GIT_COMMIT'" -o ../app + +FROM eliona/base-alpine:latest-3.17 AS target + +COPY --from=build /app ./ +COPY conf/*.sql ./conf/ +# COPY eliona/*.json ./eliona/ +COPY openapi.yaml ./ + +ENV APPNAME=template + +ENV TZ=Europe/Zurich +CMD [ "/app" ] diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..ce9acc6 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Leicom ITEC AG + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5b71cfb --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +# App Template + +This template is a part of the Eliona App SDK. It can be used to create an app stub for an Eliona environment. + +## Configuration + +The app needs environment variables and database tables for configuration. To edit the database tables the app provides an own API access. + + +### Registration in Eliona ### + +To start and initialize an app in an Eliona environment, the app has to be registered in Eliona. For this, entries in database tables `public.eliona_app` and `public.eliona_store` are necessary. + +This initialization can be handled by the `reset.sql` script. + + +### Environment variables + +Todo: Describe further environment variables tables the app needs for configuration + + +- `APPNAME`: must be set to `template`. Some resources use this name to identify the app inside an Eliona environment. + +- `CONNECTION_STRING`: configures the [Eliona database](https://github.com/eliona-smart-building-assistant/go-eliona/tree/main/db). Otherwise, the app can't be initialized and started. (e.g. `postgres://user:pass@localhost:5432/iot`) + +- `API_ENDPOINT`: configures the endpoint to access the [Eliona API v2](https://github.com/eliona-smart-building-assistant/eliona-api). Otherwise, the app can't be initialized and started. (e.g. `http://api-v2:3000/v2`) + +- `API_TOKEN`: defines the secret to authenticate the app and access the Eliona API. + +- `API_SERVER_PORT`(optional): define the port the API server listens. The default value is Port `3000`. Todo: Decide if the app needs its own API. If so, an API server have to implemented and the port have to be configurable. + +- `LOG_LEVEL`(optional): defines the minimum level that should be [logged](https://github.com/eliona-smart-building-assistant/go-utils/blob/main/log/README.md). The default level is `info`. + +### Database tables ### + +Todo: Describe the database objects the app needs for configuration + +Todo: Decide if the app uses its own data and which data should be accessible from outside the app. This is always the case with configuration data. If so, the app needs its own API server to provide access to this data. To define the API use an openapi.yaml file and generators to build the server stub. + +The app requires configuration data that remains in the database. To do this, the app creates its own database schema `template` during initialization. To modify and handle the configuration data the app provides an API access. Have a look at the [API specification](https://eliona-smart-building-assistant.github.io/open-api-docs/?https://raw.githubusercontent.com/eliona-smart-building-assistant/app-template/develop/openapi.yaml) how the configuration tables should be used. + +- `template.example_table`: Todo: Describe the database table in short. + +**Generation**: to generate access method to database see Generation section below. + + +## References + +### App API ### + +The app provides its own API to access configuration data and other functions. The full description of the API is defined in the `openapi.yaml` OpenAPI definition file. + +- [API Reference](https://eliona-smart-building-assistant.github.io/open-api-docs/?https://raw.githubusercontent.com/eliona-smart-building-assistant/app-template/develop/openapi.yaml) shows Details of the API + +**Generation**: to generate api server stub see Generation section below. + + +### Eliona ### + +Todo: Describe all the data the app writes to eliona + + +## Tools + +### Generate API server stub ### + +For the API server the [OpenAPI Generator](https://openapi-generator.tech/docs/generators/openapi-yaml) for go-server is used to generate a server stub. The easiest way to generate the server files is to use one of the predefined generation script which use the OpenAPI Generator Docker image. + +``` +.\generate-api-server.cmd # Windows +./generate-api-server.sh # Linux +``` + +### Generate Database access ### + +For the database access [SQLBoiler](https://github.com/volatiletech/sqlboiler) is used. The easiest way to generate the database files is to use one of the predefined generation script which use the SQLBoiler implementation. Please note that the database connection in the `sqlboiler.toml` file have to be configured. + +``` +.\generate-db.cmd # Windows +./generate-db.sh # Linux +``` diff --git a/apiserver/.openapi-generator-ignore b/apiserver/.openapi-generator-ignore new file mode 100644 index 0000000..b7ec3fe --- /dev/null +++ b/apiserver/.openapi-generator-ignore @@ -0,0 +1,9 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# If the API changes please remove these lines and merge the generated files with the existing ones. + +api/** +README.md \ No newline at end of file diff --git a/apiserver/api.go b/apiserver/api.go new file mode 100644 index 0000000..cbb01e6 --- /dev/null +++ b/apiserver/api.go @@ -0,0 +1,64 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "context" + "net/http" +) + +// ConfigurationApiRouter defines the required methods for binding the api requests to a responses for the ConfigurationApi +// The ConfigurationApiRouter implementation should parse necessary information from the http request, +// pass the data to a ConfigurationApiServicer to perform the required actions, then write the service results to the http response. +type ConfigurationApiRouter interface { + GetConfigurations(http.ResponseWriter, *http.Request) + PostConfiguration(http.ResponseWriter, *http.Request) +} + +// CustomizationApiRouter defines the required methods for binding the api requests to a responses for the CustomizationApi +// The CustomizationApiRouter implementation should parse necessary information from the http request, +// pass the data to a CustomizationApiServicer to perform the required actions, then write the service results to the http response. +type CustomizationApiRouter interface { + GetDashboardTemplateByName(http.ResponseWriter, *http.Request) +} + +// VersionApiRouter defines the required methods for binding the api requests to a responses for the VersionApi +// The VersionApiRouter implementation should parse necessary information from the http request, +// pass the data to a VersionApiServicer to perform the required actions, then write the service results to the http response. +type VersionApiRouter interface { + GetOpenAPI(http.ResponseWriter, *http.Request) + GetVersion(http.ResponseWriter, *http.Request) +} + +// ConfigurationApiServicer defines the api actions for the ConfigurationApi service +// This interface intended to stay up to date with the openapi yaml used to generate it, +// while the service implementation can be ignored with the .openapi-generator-ignore file +// and updated with the logic required for the API. +type ConfigurationApiServicer interface { + GetConfigurations(context.Context) (ImplResponse, error) + PostConfiguration(context.Context, Configuration) (ImplResponse, error) +} + +// CustomizationApiServicer defines the api actions for the CustomizationApi service +// This interface intended to stay up to date with the openapi yaml used to generate it, +// while the service implementation can be ignored with the .openapi-generator-ignore file +// and updated with the logic required for the API. +type CustomizationApiServicer interface { + GetDashboardTemplateByName(context.Context, string, string) (ImplResponse, error) +} + +// VersionApiServicer defines the api actions for the VersionApi service +// This interface intended to stay up to date with the openapi yaml used to generate it, +// while the service implementation can be ignored with the .openapi-generator-ignore file +// and updated with the logic required for the API. +type VersionApiServicer interface { + GetOpenAPI(context.Context) (ImplResponse, error) + GetVersion(context.Context) (ImplResponse, error) +} diff --git a/apiserver/api_configuration.go b/apiserver/api_configuration.go new file mode 100644 index 0000000..4135c45 --- /dev/null +++ b/apiserver/api_configuration.go @@ -0,0 +1,101 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "encoding/json" + "net/http" + "strings" +) + +// ConfigurationApiController binds http requests to an api service and writes the service results to the http response +type ConfigurationApiController struct { + service ConfigurationApiServicer + errorHandler ErrorHandler +} + +// ConfigurationApiOption for how the controller is set up. +type ConfigurationApiOption func(*ConfigurationApiController) + +// WithConfigurationApiErrorHandler inject ErrorHandler into controller +func WithConfigurationApiErrorHandler(h ErrorHandler) ConfigurationApiOption { + return func(c *ConfigurationApiController) { + c.errorHandler = h + } +} + +// NewConfigurationApiController creates a default api controller +func NewConfigurationApiController(s ConfigurationApiServicer, opts ...ConfigurationApiOption) Router { + controller := &ConfigurationApiController{ + service: s, + errorHandler: DefaultErrorHandler, + } + + for _, opt := range opts { + opt(controller) + } + + return controller +} + +// Routes returns all the api routes for the ConfigurationApiController +func (c *ConfigurationApiController) Routes() Routes { + return Routes{ + { + "GetConfigurations", + strings.ToUpper("Get"), + "/v1/configurations", + c.GetConfigurations, + }, + { + "PostConfiguration", + strings.ToUpper("Post"), + "/v1/configurations", + c.PostConfiguration, + }, + } +} + +// GetConfigurations - Get configurations +func (c *ConfigurationApiController) GetConfigurations(w http.ResponseWriter, r *http.Request) { + result, err := c.service.GetConfigurations(r.Context()) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, w) + +} + +// PostConfiguration - Creates a configuration +func (c *ConfigurationApiController) PostConfiguration(w http.ResponseWriter, r *http.Request) { + configurationParam := Configuration{} + d := json.NewDecoder(r.Body) + d.DisallowUnknownFields() + if err := d.Decode(&configurationParam); err != nil { + c.errorHandler(w, r, &ParsingError{Err: err}, nil) + return + } + if err := AssertConfigurationRequired(configurationParam); err != nil { + c.errorHandler(w, r, err, nil) + return + } + result, err := c.service.PostConfiguration(r.Context(), configurationParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, w) + +} diff --git a/apiserver/api_customization.go b/apiserver/api_customization.go new file mode 100644 index 0000000..34a3f62 --- /dev/null +++ b/apiserver/api_customization.go @@ -0,0 +1,77 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "net/http" + "strings" + + "github.com/gorilla/mux" +) + +// CustomizationApiController binds http requests to an api service and writes the service results to the http response +type CustomizationApiController struct { + service CustomizationApiServicer + errorHandler ErrorHandler +} + +// CustomizationApiOption for how the controller is set up. +type CustomizationApiOption func(*CustomizationApiController) + +// WithCustomizationApiErrorHandler inject ErrorHandler into controller +func WithCustomizationApiErrorHandler(h ErrorHandler) CustomizationApiOption { + return func(c *CustomizationApiController) { + c.errorHandler = h + } +} + +// NewCustomizationApiController creates a default api controller +func NewCustomizationApiController(s CustomizationApiServicer, opts ...CustomizationApiOption) Router { + controller := &CustomizationApiController{ + service: s, + errorHandler: DefaultErrorHandler, + } + + for _, opt := range opts { + opt(controller) + } + + return controller +} + +// Routes returns all the api routes for the CustomizationApiController +func (c *CustomizationApiController) Routes() Routes { + return Routes{ + { + "GetDashboardTemplateByName", + strings.ToUpper("Get"), + "/v1/dashboard-templates/{dashboard-template-name}", + c.GetDashboardTemplateByName, + }, + } +} + +// GetDashboardTemplateByName - Get a full dashboard template +func (c *CustomizationApiController) GetDashboardTemplateByName(w http.ResponseWriter, r *http.Request) { + params := mux.Vars(r) + query := r.URL.Query() + dashboardTemplateNameParam := params["dashboard-template-name"] + + projectIdParam := query.Get("projectId") + result, err := c.service.GetDashboardTemplateByName(r.Context(), dashboardTemplateNameParam, projectIdParam) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, w) + +} diff --git a/apiserver/api_version.go b/apiserver/api_version.go new file mode 100644 index 0000000..27a1c05 --- /dev/null +++ b/apiserver/api_version.go @@ -0,0 +1,89 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "net/http" + "strings" +) + +// VersionApiController binds http requests to an api service and writes the service results to the http response +type VersionApiController struct { + service VersionApiServicer + errorHandler ErrorHandler +} + +// VersionApiOption for how the controller is set up. +type VersionApiOption func(*VersionApiController) + +// WithVersionApiErrorHandler inject ErrorHandler into controller +func WithVersionApiErrorHandler(h ErrorHandler) VersionApiOption { + return func(c *VersionApiController) { + c.errorHandler = h + } +} + +// NewVersionApiController creates a default api controller +func NewVersionApiController(s VersionApiServicer, opts ...VersionApiOption) Router { + controller := &VersionApiController{ + service: s, + errorHandler: DefaultErrorHandler, + } + + for _, opt := range opts { + opt(controller) + } + + return controller +} + +// Routes returns all the api routes for the VersionApiController +func (c *VersionApiController) Routes() Routes { + return Routes{ + { + "GetOpenAPI", + strings.ToUpper("Get"), + "/v1/version/openapi.json", + c.GetOpenAPI, + }, + { + "GetVersion", + strings.ToUpper("Get"), + "/v1/version", + c.GetVersion, + }, + } +} + +// GetOpenAPI - OpenAPI specification for this API version +func (c *VersionApiController) GetOpenAPI(w http.ResponseWriter, r *http.Request) { + result, err := c.service.GetOpenAPI(r.Context()) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, w) + +} + +// GetVersion - Version of the API +func (c *VersionApiController) GetVersion(w http.ResponseWriter, r *http.Request) { + result, err := c.service.GetVersion(r.Context()) + // If an error occurred, encode the error with the status code + if err != nil { + c.errorHandler(w, r, err, &result) + return + } + // If no error, encode the body and the result code + EncodeJSONResponse(result.Body, &result.Code, w) + +} diff --git a/apiserver/error.go b/apiserver/error.go new file mode 100644 index 0000000..3250fdc --- /dev/null +++ b/apiserver/error.go @@ -0,0 +1,62 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "errors" + "fmt" + "net/http" +) + +var ( + // ErrTypeAssertionError is thrown when type an interface does not match the asserted type + ErrTypeAssertionError = errors.New("unable to assert type") +) + +// ParsingError indicates that an error has occurred when parsing request parameters +type ParsingError struct { + Err error +} + +func (e *ParsingError) Unwrap() error { + return e.Err +} + +func (e *ParsingError) Error() string { + return e.Err.Error() +} + +// RequiredError indicates that an error has occurred when parsing request parameters +type RequiredError struct { + Field string +} + +func (e *RequiredError) Error() string { + return fmt.Sprintf("required field '%s' is zero value.", e.Field) +} + +// ErrorHandler defines the required method for handling error. You may implement it and inject this into a controller if +// you would like errors to be handled differently from the DefaultErrorHandler +type ErrorHandler func(w http.ResponseWriter, r *http.Request, err error, result *ImplResponse) + +// DefaultErrorHandler defines the default logic on how to handle errors from the controller. Any errors from parsing +// request params will return a StatusBadRequest. Otherwise, the error code originating from the servicer will be used. +func DefaultErrorHandler(w http.ResponseWriter, r *http.Request, err error, result *ImplResponse) { + if _, ok := err.(*ParsingError); ok { + // Handle parsing errors + EncodeJSONResponse(err.Error(), func(i int) *int { return &i }(http.StatusBadRequest), w) + } else if _, ok := err.(*RequiredError); ok { + // Handle missing required errors + EncodeJSONResponse(err.Error(), func(i int) *int { return &i }(http.StatusUnprocessableEntity), w) + } else { + // Handle all other errors + EncodeJSONResponse(err.Error(), &result.Code, w) + } +} diff --git a/apiserver/helpers.go b/apiserver/helpers.go new file mode 100644 index 0000000..54a31db --- /dev/null +++ b/apiserver/helpers.go @@ -0,0 +1,54 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "reflect" +) + +// Response return a ImplResponse struct filled +func Response(code int, body interface{}) ImplResponse { + return ImplResponse{ + Code: code, + Body: body, + } +} + +// IsZeroValue checks if the val is the zero-ed value. +func IsZeroValue(val interface{}) bool { + return val == nil || reflect.DeepEqual(val, reflect.Zero(reflect.TypeOf(val)).Interface()) +} + +// AssertRecurseInterfaceRequired recursively checks each struct in a slice against the callback. +// This method traverse nested slices in a preorder fashion. +func AssertRecurseInterfaceRequired(obj interface{}, callback func(interface{}) error) error { + return AssertRecurseValueRequired(reflect.ValueOf(obj), callback) +} + +// AssertRecurseValueRequired checks each struct in the nested slice against the callback. +// This method traverse nested slices in a preorder fashion. +func AssertRecurseValueRequired(value reflect.Value, callback func(interface{}) error) error { + switch value.Kind() { + // If it is a struct we check using callback + case reflect.Struct: + if err := callback(value.Interface()); err != nil { + return err + } + + // If it is a slice we continue recursion + case reflect.Slice: + for i := 0; i < value.Len(); i += 1 { + if err := AssertRecurseValueRequired(value.Index(i), callback); err != nil { + return err + } + } + } + return nil +} diff --git a/apiserver/impl.go b/apiserver/impl.go new file mode 100644 index 0000000..00988e7 --- /dev/null +++ b/apiserver/impl.go @@ -0,0 +1,16 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +// ImplResponse response defines an error code with the associated body +type ImplResponse struct { + Code int + Body interface{} +} diff --git a/apiserver/logger.go b/apiserver/logger.go new file mode 100644 index 0000000..a734d4a --- /dev/null +++ b/apiserver/logger.go @@ -0,0 +1,32 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "log" + "net/http" + "time" +) + +func Logger(inner http.Handler, name string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + + inner.ServeHTTP(w, r) + + log.Printf( + "%s %s %s %s", + r.Method, + r.RequestURI, + name, + time.Since(start), + ) + }) +} diff --git a/apiserver/model_configuration.go b/apiserver/model_configuration.go new file mode 100644 index 0000000..c4bdff4 --- /dev/null +++ b/apiserver/model_configuration.go @@ -0,0 +1,37 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +// Configuration - Simply a example configuration +type Configuration struct { + + // A id identifying the example configuration + Id *int64 `json:"id,omitempty"` + + // Configuration data for example + Config string `json:"config,omitempty"` +} + +// AssertConfigurationRequired checks if the required fields are not zero-ed +func AssertConfigurationRequired(obj Configuration) error { + return nil +} + +// AssertRecurseConfigurationRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of Configuration (e.g. [][]Configuration), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseConfigurationRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aConfiguration, ok := obj.(Configuration) + if !ok { + return ErrTypeAssertionError + } + return AssertConfigurationRequired(aConfiguration) + }) +} diff --git a/apiserver/model_dashboard.go b/apiserver/model_dashboard.go new file mode 100644 index 0000000..ba5404f --- /dev/null +++ b/apiserver/model_dashboard.go @@ -0,0 +1,67 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +// Dashboard - A frontend dashboard +type Dashboard struct { + + // The internal Id of dashboard + Id *int32 `json:"id,omitempty"` + + // The name for this dashboard + Name string `json:"name"` + + // ID of the project to which the dashboard belongs + ProjectId string `json:"projectId"` + + // ID of the user who owns the dashboard + UserId string `json:"userId"` + + // The sequence of the dashboard + Sequence *int32 `json:"sequence,omitempty"` + + // List of widgets on this dashboard (order matches the order of widgets on the dashboard) + Widgets *[]Widget `json:"widgets,omitempty"` +} + +// AssertDashboardRequired checks if the required fields are not zero-ed +func AssertDashboardRequired(obj Dashboard) error { + elements := map[string]interface{}{ + "name": obj.Name, + "projectId": obj.ProjectId, + "userId": obj.UserId, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if obj.Widgets != nil { + for _, el := range *obj.Widgets { + if err := AssertWidgetRequired(el); err != nil { + return err + } + } + } + return nil +} + +// AssertRecurseDashboardRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of Dashboard (e.g. [][]Dashboard), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseDashboardRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aDashboard, ok := obj.(Dashboard) + if !ok { + return ErrTypeAssertionError + } + return AssertDashboardRequired(aDashboard) + }) +} diff --git a/apiserver/model_widget.go b/apiserver/model_widget.go new file mode 100644 index 0000000..c959c72 --- /dev/null +++ b/apiserver/model_widget.go @@ -0,0 +1,65 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +// Widget - A widget on a frontend dashboard +type Widget struct { + + // The internal Id of widget + Id *int32 `json:"id,omitempty"` + + // The name for the type of this widget + WidgetTypeName string `json:"widgetTypeName"` + + // Detailed configuration depending on the widget type + Details *map[string]interface{} `json:"details,omitempty"` + + // The master asset id of this widget + AssetId *int32 `json:"assetId,omitempty"` + + // Placement order on dashboard; if not set the index in array is taken + Sequence *int32 `json:"sequence,omitempty"` + + // List of data for the elements of widget + Data *[]WidgetData `json:"data,omitempty"` +} + +// AssertWidgetRequired checks if the required fields are not zero-ed +func AssertWidgetRequired(obj Widget) error { + elements := map[string]interface{}{ + "widgetTypeName": obj.WidgetTypeName, + } + for name, el := range elements { + if isZero := IsZeroValue(el); isZero { + return &RequiredError{Field: name} + } + } + + if obj.Data != nil { + for _, el := range *obj.Data { + if err := AssertWidgetDataRequired(el); err != nil { + return err + } + } + } + return nil +} + +// AssertRecurseWidgetRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of Widget (e.g. [][]Widget), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseWidgetRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aWidget, ok := obj.(Widget) + if !ok { + return ErrTypeAssertionError + } + return AssertWidgetRequired(aWidget) + }) +} diff --git a/apiserver/model_widget_data.go b/apiserver/model_widget_data.go new file mode 100644 index 0000000..9c67386 --- /dev/null +++ b/apiserver/model_widget_data.go @@ -0,0 +1,43 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +// WidgetData - Data for a widget +type WidgetData struct { + + // The internal Id of widget data + Id *int32 `json:"id,omitempty"` + + // Position of the element in widget type + ElementSequence *int32 `json:"elementSequence,omitempty"` + + // The master asset id of this widget + AssetId *int32 `json:"assetId,omitempty"` + + // individual config parameters depending on category + Data *map[string]interface{} `json:"data,omitempty"` +} + +// AssertWidgetDataRequired checks if the required fields are not zero-ed +func AssertWidgetDataRequired(obj WidgetData) error { + return nil +} + +// AssertRecurseWidgetDataRequired recursively checks if required fields are not zero-ed in a nested slice. +// Accepts only nested slice of WidgetData (e.g. [][]WidgetData), otherwise ErrTypeAssertionError is thrown. +func AssertRecurseWidgetDataRequired(objSlice interface{}) error { + return AssertRecurseInterfaceRequired(objSlice, func(obj interface{}) error { + aWidgetData, ok := obj.(WidgetData) + if !ok { + return ErrTypeAssertionError + } + return AssertWidgetDataRequired(aWidgetData) + }) +} diff --git a/apiserver/openapi.json b/apiserver/openapi.json new file mode 100644 index 0000000..6b767cd --- /dev/null +++ b/apiserver/openapi.json @@ -0,0 +1,415 @@ +{ + "openapi" : "3.0.3", + "info" : { + "description" : "API to access and configure the app template", + "title" : "App template API", + "version" : "1.0.0" + }, + "externalDocs" : { + "description" : "Find out more about the app template", + "url" : "https://github.com/eliona-smart-building-assistant/app-template" + }, + "servers" : [ { + "url" : "http://template/v1" + } ], + "tags" : [ { + "description" : "Configuration stuff for app template", + "externalDocs" : { + "url" : "https://github.com/eliona-smart-building-assistant/app-template" + }, + "name" : "Configuration" + }, { + "description" : "API version", + "externalDocs" : { + "url" : "https://github.com/eliona-smart-building-assistant/app-template" + }, + "name" : "Version" + }, { + "description" : "Help to customize Eliona", + "externalDocs" : { + "url" : "https://github.com/eliona-smart-building-assistant/app-template" + }, + "name" : "Customization" + } ], + "paths" : { + "/configurations" : { + "get" : { + "description" : "Gets information about configurations.", + "operationId" : "getConfigurations", + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "items" : { + "$ref" : "#/components/schemas/Configuration" + }, + "type" : "array" + } + } + }, + "description" : "Successfully returned example configurations" + } + }, + "summary" : "Get example configurations", + "tags" : [ "Configuration" ] + }, + "post" : { + "description" : "Creates an example configuration.", + "operationId" : "postConfiguration", + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Configuration" + } + } + } + }, + "responses" : { + "201" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Configuration" + } + } + }, + "description" : "Successfully created an example configuration" + } + }, + "summary" : "Creates an example configuration", + "tags" : [ "Configuration" ] + } + }, + "/version" : { + "get" : { + "description" : "Gets information about the APIs version.", + "operationId" : "getVersion", + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object" + } + } + }, + "description" : "Successfully returned the APIs version." + } + }, + "summary" : "Version of the API", + "tags" : [ "Version" ] + } + }, + "/version/openapi.json" : { + "get" : { + "description" : "Gets specification for this API version as an openapi.json file.", + "operationId" : "getOpenAPI", + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object" + } + } + }, + "description" : "Successfully returned the openapi.json file." + } + }, + "summary" : "OpenAPI specification for this API version", + "tags" : [ "Version" ] + } + }, + "/dashboard-templates/{dashboard-template-name}" : { + "get" : { + "description" : "Delivers a dashboard template which can assigned to users in Eliona", + "externalDocs" : { + "description" : "The API to assign the dashboard to users in Eliona (see post /dashboards endpoint).", + "url" : "https://github.com/eliona-smart-building-assistant/eliona-api" + }, + "operationId" : "getDashboardTemplateByName", + "parameters" : [ { + "description" : "Name of the dashboard template", + "explode" : false, + "in" : "path", + "name" : "dashboard-template-name", + "required" : true, + "schema" : { + "example" : "Template", + "type" : "string" + }, + "style" : "simple" + }, { + "description" : "Define the project the dashboard should be", + "explode" : true, + "in" : "query", + "name" : "projectId", + "required" : true, + "schema" : { + "example" : "99", + "type" : "string" + }, + "style" : "form" + } ], + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/Dashboard" + } + } + }, + "description" : "Successfully returned dashboard template" + }, + "404" : { + "description" : "Template name not found" + } + }, + "summary" : "Get a full dashboard template", + "tags" : [ "Customization" ] + } + } + }, + "components" : { + "schemas" : { + "Configuration" : { + "description" : "Simply a example configuration", + "properties" : { + "id" : { + "description" : "A id identifying the example configuration", + "format" : "int64", + "nullable" : true, + "readOnly" : true, + "type" : "integer" + }, + "config" : { + "description" : "Configuration data for example", + "type" : "string" + } + }, + "type" : "object" + }, + "Dashboard" : { + "description" : "A frontend dashboard", + "example" : { + "sequence" : 1, + "name" : "Weather info", + "id" : 4711, + "widgets" : [ { + "sequence" : 1, + "data" : [ { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + }, { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + } ], + "assetId" : 4711, + "details" : { }, + "id" : 4711, + "widgetTypeName" : "Weather" + }, { + "sequence" : 1, + "data" : [ { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + }, { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + } ], + "assetId" : 4711, + "details" : { }, + "id" : 4711, + "widgetTypeName" : "Weather" + } ], + "projectId" : "99", + "userId" : "42" + }, + "properties" : { + "id" : { + "description" : "The internal Id of dashboard", + "example" : 4711, + "nullable" : true, + "readOnly" : true, + "type" : "integer" + }, + "name" : { + "description" : "The name for this dashboard", + "example" : "Weather info", + "type" : "string" + }, + "projectId" : { + "description" : "ID of the project to which the dashboard belongs", + "example" : "99", + "type" : "string" + }, + "userId" : { + "description" : "ID of the user who owns the dashboard", + "example" : "42", + "type" : "string" + }, + "sequence" : { + "default" : 0, + "description" : "The sequence of the dashboard", + "example" : 1, + "nullable" : true, + "type" : "integer" + }, + "widgets" : { + "description" : "List of widgets on this dashboard (order matches the order of widgets on the dashboard)", + "items" : { + "$ref" : "#/components/schemas/Widget" + }, + "nullable" : true, + "type" : "array" + } + }, + "required" : [ "name", "projectId", "userId" ], + "type" : "object" + }, + "Widget" : { + "description" : "A widget on a frontend dashboard", + "example" : { + "sequence" : 1, + "data" : [ { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + }, { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + } ], + "assetId" : 4711, + "details" : { }, + "id" : 4711, + "widgetTypeName" : "Weather" + }, + "properties" : { + "id" : { + "description" : "The internal Id of widget", + "example" : 4711, + "nullable" : true, + "readOnly" : true, + "type" : "integer" + }, + "widgetTypeName" : { + "description" : "The name for the type of this widget", + "example" : "Weather", + "type" : "string" + }, + "details" : { + "description" : "Detailed configuration depending on the widget type", + "example" : { }, + "nullable" : true, + "type" : "object" + }, + "assetId" : { + "description" : "The master asset id of this widget", + "example" : 4711, + "nullable" : true, + "type" : "integer" + }, + "sequence" : { + "description" : "Placement order on dashboard; if not set the index in array is taken", + "example" : 1, + "nullable" : true, + "type" : "integer" + }, + "data" : { + "description" : "List of data for the elements of widget", + "items" : { + "$ref" : "#/components/schemas/WidgetData" + }, + "nullable" : true, + "type" : "array" + } + }, + "required" : [ "widgetTypeName", "width" ], + "type" : "object" + }, + "WidgetData" : { + "description" : "Data for a widget", + "example" : { + "elementSequence" : 1, + "data" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "assetId" : 4711, + "id" : 4711 + }, + "properties" : { + "id" : { + "description" : "The internal Id of widget data", + "example" : 4711, + "nullable" : true, + "readOnly" : true, + "type" : "integer" + }, + "elementSequence" : { + "description" : "Position of the element in widget type", + "example" : 1, + "nullable" : true, + "type" : "integer" + }, + "assetId" : { + "description" : "The master asset id of this widget", + "example" : 4711, + "nullable" : true, + "type" : "integer" + }, + "data" : { + "description" : "individual config parameters depending on category", + "example" : { + "subtype" : "input", + "attribute" : "temperature", + "key" : "humidity" + }, + "nullable" : true, + "type" : "object" + } + }, + "type" : "object" + } + } + } +} \ No newline at end of file diff --git a/apiserver/routers.go b/apiserver/routers.go new file mode 100644 index 0000000..0e5ccd9 --- /dev/null +++ b/apiserver/routers.go @@ -0,0 +1,218 @@ +/* + * App template API + * + * API to access and configure the app template + * + * API version: 1.0.0 + * Generated by: OpenAPI Generator (https://openapi-generator.tech) + */ + +package apiserver + +import ( + "encoding/json" + "errors" + "io/ioutil" + "mime/multipart" + "net/http" + "os" + "strconv" + "strings" + + "github.com/gorilla/mux" +) + +// A Route defines the parameters for an api endpoint +type Route struct { + Name string + Method string + Pattern string + HandlerFunc http.HandlerFunc +} + +// Routes are a collection of defined api endpoints +type Routes []Route + +// Router defines the required methods for retrieving api routes +type Router interface { + Routes() Routes +} + +const errMsgRequiredMissing = "required parameter is missing" + +// NewRouter creates a new router for any number of api routers +func NewRouter(routers ...Router) *mux.Router { + router := mux.NewRouter().StrictSlash(true) + for _, api := range routers { + for _, route := range api.Routes() { + var handler http.Handler + handler = route.HandlerFunc + handler = Logger(handler, route.Name) + + router. + Methods(route.Method). + Path(route.Pattern). + Name(route.Name). + Handler(handler) + } + } + + return router +} + +// EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code +func EncodeJSONResponse(i interface{}, status *int, w http.ResponseWriter) error { + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + if status != nil { + w.WriteHeader(*status) + } else { + w.WriteHeader(http.StatusOK) + } + + return json.NewEncoder(w).Encode(i) +} + +// ReadFormFileToTempFile reads file data from a request form and writes it to a temporary file +func ReadFormFileToTempFile(r *http.Request, key string) (*os.File, error) { + _, fileHeader, err := r.FormFile(key) + if err != nil { + return nil, err + } + + return readFileHeaderToTempFile(fileHeader) +} + +// ReadFormFilesToTempFiles reads files array data from a request form and writes it to a temporary files +func ReadFormFilesToTempFiles(r *http.Request, key string) ([]*os.File, error) { + if err := r.ParseMultipartForm(32 << 20); err != nil { + return nil, err + } + + files := make([]*os.File, 0, len(r.MultipartForm.File[key])) + + for _, fileHeader := range r.MultipartForm.File[key] { + file, err := readFileHeaderToTempFile(fileHeader) + if err != nil { + return nil, err + } + + files = append(files, file) + } + + return files, nil +} + +// readFileHeaderToTempFile reads multipart.FileHeader and writes it to a temporary file +func readFileHeaderToTempFile(fileHeader *multipart.FileHeader) (*os.File, error) { + formFile, err := fileHeader.Open() + if err != nil { + return nil, err + } + + defer formFile.Close() + + fileBytes, err := ioutil.ReadAll(formFile) + if err != nil { + return nil, err + } + + file, err := ioutil.TempFile("", fileHeader.Filename) + if err != nil { + return nil, err + } + + defer file.Close() + + file.Write(fileBytes) + + return file, nil +} + +// parseInt64Parameter parses a string parameter to an int64. +func parseInt64Parameter(param string, required bool) (int64, error) { + if param == "" { + if required { + return 0, errors.New(errMsgRequiredMissing) + } + + return 0, nil + } + + return strconv.ParseInt(param, 10, 64) +} + +// parseInt32Parameter parses a string parameter to an int32. +func parseInt32Parameter(param string, required bool) (int32, error) { + if param == "" { + if required { + return 0, errors.New(errMsgRequiredMissing) + } + + return 0, nil + } + + val, err := strconv.ParseInt(param, 10, 32) + if err != nil { + return -1, err + } + + return int32(val), nil +} + +// parseBoolParameter parses a string parameter to a bool +func parseBoolParameter(param string) (bool, error) { + val, err := strconv.ParseBool(param) + if err != nil { + return false, err + } + + return bool(val), nil +} + +// parseInt64ArrayParameter parses a string parameter containing array of values to []int64. +func parseInt64ArrayParameter(param, delim string, required bool) ([]int64, error) { + if param == "" { + if required { + return nil, errors.New(errMsgRequiredMissing) + } + + return nil, nil + } + + str := strings.Split(param, delim) + ints := make([]int64, len(str)) + + for i, s := range str { + if v, err := strconv.ParseInt(s, 10, 64); err != nil { + return nil, err + } else { + ints[i] = v + } + } + + return ints, nil +} + +// parseInt32ArrayParameter parses a string parameter containing array of values to []int32. +func parseInt32ArrayParameter(param, delim string, required bool) ([]int32, error) { + if param == "" { + if required { + return nil, errors.New(errMsgRequiredMissing) + } + + return nil, nil + } + + str := strings.Split(param, delim) + ints := make([]int32, len(str)) + + for i, s := range str { + if v, err := strconv.ParseInt(s, 10, 32); err != nil { + return nil, err + } else { + ints[i] = int32(v) + } + } + + return ints, nil +} diff --git a/apiservices/api_configuration_service.go b/apiservices/api_configuration_service.go new file mode 100644 index 0000000..64d0c71 --- /dev/null +++ b/apiservices/api_configuration_service.go @@ -0,0 +1,56 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package apiservices + +import ( + "context" + "errors" + "net/http" + "template/apiserver" +) + +// ConfigurationApiService is a service that implements the logic for the ConfigurationApiServicer +// This service should implement the business logic for every endpoint for the ConfigurationApi API. +// Include any external packages or services that will be required by this service. +type ConfigurationApiService struct { +} + +// NewConfigurationApiService creates a default api service +func NewConfigurationApiService() apiserver.ConfigurationApiServicer { + return &ConfigurationApiService{} +} + +// GetConfigurations - Get example configurations +func (s *ConfigurationApiService) GetConfigurations(ctx context.Context) (apiserver.ImplResponse, error) { + // TODO - update GetConfigurations with the required logic for this service method. + // Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + //TODO: Uncomment the next line to return response Response(200, []Configuration{}) or use other options such as http.Ok ... + //return Response(200, []Configuration{}), nil + + return apiserver.Response(http.StatusNotImplemented, nil), errors.New("GetConfigurations method not implemented") +} + +// PostConfiguration - Creates an example configuration +func (s *ConfigurationApiService) PostConfiguration(ctx context.Context, configuration apiserver.Configuration) (apiserver.ImplResponse, error) { + // TODO - update PostConfiguration with the required logic for this service method. + // Add api_configuration_service.go to the .openapi-generator-ignore to avoid overwriting this service implementation when updating open api generation. + + //TODO: Uncomment the next line to return response Response(201, Configuration{}) or use other options such as http.Ok ... + //return Response(201, Configuration{}), nil + + return apiserver.Response(http.StatusNotImplemented, nil), errors.New("PostConfiguration method not implemented") +} diff --git a/apiservices/api_customization_service.go b/apiservices/api_customization_service.go new file mode 100644 index 0000000..4a26f58 --- /dev/null +++ b/apiservices/api_customization_service.go @@ -0,0 +1,42 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package apiservices + +import ( + "context" + "net/http" + "template/apiserver" +) + +// CustomizationApiService is a service that implements the logic for the CustomizationApiServicer +// This service should implement the business logic for every endpoint for the CustomizationApi API. +// Include any external packages or services that will be required by this service. +type CustomizationApiService struct { +} + +// NewCustomizationApiService creates a default api service +func NewCustomizationApiService() apiserver.CustomizationApiServicer { + return &CustomizationApiService{} +} + +// GetDashboardTemplateByName - Get a full dashboard template +func (s *CustomizationApiService) GetDashboardTemplateByName(ctx context.Context, dashboardTemplateName string, projectId string) (apiserver.ImplResponse, error) { + if dashboardTemplateName == "Template" { + return apiserver.ImplResponse{Code: http.StatusNotImplemented}, nil + } else { + return apiserver.ImplResponse{Code: http.StatusNotFound}, nil + } +} diff --git a/apiservices/api_version_service.go b/apiservices/api_version_service.go new file mode 100644 index 0000000..a306a99 --- /dev/null +++ b/apiservices/api_version_service.go @@ -0,0 +1,79 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package apiservices + +import ( + "context" + "encoding/json" + "io" + "net/http" + "os" + "template/apiserver" + + "github.com/eliona-smart-building-assistant/go-utils/common" + "github.com/eliona-smart-building-assistant/go-utils/log" + "gopkg.in/yaml.v3" +) + +// VersionApiService is a service that implements the logic for the VersionApiServicer +// This service should implement the business logic for every endpoint for the VersionApi API. +// Include any external packages or services that will be required by this service. +type VersionApiService struct { +} + +// NewVersionApiService creates a default api service +func NewVersionApiService() apiserver.VersionApiServicer { + return &VersionApiService{} +} + +// GetOpenAPI - OpenAPI specification for this API version +func (s *VersionApiService) GetOpenAPI(ctx context.Context) (apiserver.ImplResponse, error) { + bytes, err := os.ReadFile("openapi.yaml") + if err != nil { + log.Error("services", "%s: %v", "GetOpenAPI", err) + return apiserver.ImplResponse{Code: http.StatusNotFound}, err + } + var body interface{} + err = yaml.Unmarshal(bytes, &body) + if err != nil { + log.Error("services", "%s: %v", "GetOpenAPI", err) + return apiserver.ImplResponse{Code: http.StatusInternalServerError}, err + } + if err := tryJSONEncoding(body); err != nil { + log.Error("services", "openapi file not encodable to JSON: %v", err) + return apiserver.ImplResponse{Code: http.StatusInternalServerError}, nil + } + return apiserver.Response(http.StatusOK, body), nil +} + +func tryJSONEncoding(i interface{}) error { + return json.NewEncoder(io.Discard).Encode(i) +} + +var BuildTimestamp string // injected during linking, see Dockerfile +var GitCommit string // injected during linking, see Dockerfile + +// GetVersion - Version of the API +func (s *VersionApiService) GetVersion(ctx context.Context) (apiserver.ImplResponse, error) { + return apiserver.Response(http.StatusOK, common.Ptr(version())), nil +} + +func version() map[string]any { + return map[string]any{ + "timestamp": BuildTimestamp, + "commit": GitCommit, + } +} diff --git a/app.go b/app.go new file mode 100644 index 0000000..c4ab940 --- /dev/null +++ b/app.go @@ -0,0 +1,43 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package main + +import ( + "net/http" + "template/apiserver" + "template/apiservices" + + "github.com/eliona-smart-building-assistant/go-utils/common" + "github.com/eliona-smart-building-assistant/go-utils/log" +) + +// doAnything is the main app function which is called periodically +func doAnything() { + + // Todo: implement everything the app should do + log.Debug("main", "do anything") + +} + +// listenApi starts the API server and listen for requests +func listenApi() { + err := http.ListenAndServe(":"+common.Getenv("API_SERVER_PORT", "3000"), apiserver.NewRouter( + apiserver.NewConfigurationApiController(apiservices.NewConfigurationApiService()), + apiserver.NewVersionApiController(apiservices.NewVersionApiService()), + apiserver.NewCustomizationApiController(apiservices.NewCustomizationApiService()), + )) + log.Fatal("main", "API server: %v", err) +} diff --git a/conf/conf.go b/conf/conf.go new file mode 100644 index 0000000..c08b701 --- /dev/null +++ b/conf/conf.go @@ -0,0 +1,20 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package conf + +// +// Todo: Define anything for configuration like structures and methods to read and process configuration +// diff --git a/conf/init.go b/conf/init.go new file mode 100644 index 0000000..db09150 --- /dev/null +++ b/conf/init.go @@ -0,0 +1,31 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package conf + +import ( + "github.com/eliona-smart-building-assistant/go-utils/db" +) + +// InitConfiguration initialize the configuration of the app +func InitConfiguration(connection db.Connection) error { + + // + // Todo: do anything which is necessary to initialize the app like creating text data to demonstrate the configuration + // + + return nil + +} diff --git a/conf/init.sql b/conf/init.sql new file mode 100644 index 0000000..5b5f106 --- /dev/null +++ b/conf/init.sql @@ -0,0 +1,20 @@ +-- This file is part of the eliona project. +-- Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +-- ______ _ _ +-- | ____| (_) +-- | |__ | |_ ___ _ __ __ _ +-- | __| | | |/ _ \| '_ \ / _` | +-- | |____| | | (_) | | | | (_| | +-- |______|_|_|\___/|_| |_|\__,_| +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +create schema if not exists template; + +-- +-- Todo: create tables and database objects necessary for this app like tables persisting configuration +-- \ No newline at end of file diff --git a/eliona/assets.go b/eliona/assets.go new file mode 100644 index 0000000..32a40c7 --- /dev/null +++ b/eliona/assets.go @@ -0,0 +1,20 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package eliona + +// +// Todo: Define anything for eliona like writing assets or heap data +// diff --git a/eliona/init.go b/eliona/init.go new file mode 100644 index 0000000..f5c590b --- /dev/null +++ b/eliona/init.go @@ -0,0 +1,31 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package eliona + +import ( + "github.com/eliona-smart-building-assistant/go-utils/db" +) + +// InitEliona initialize the app in aliona +func InitEliona(connection db.Connection) error { + + // + // Todo: do anything which is necessary to initialize the app within Eliona like creating asset types + // + + return nil + +} diff --git a/generate-api-server.cmd b/generate-api-server.cmd new file mode 100644 index 0000000..5f706fc --- /dev/null +++ b/generate-api-server.cmd @@ -0,0 +1,21 @@ +go install golang.org/x/tools/cmd/goimports@latest + +docker run --rm ^ + -v "%cd%":/local ^ + openapitools/openapi-generator-cli:v6.2.1 generate ^ + -g go-server ^ + --git-user-id eliona-smart-building-assistant ^ + --git-repo-id python-eliona-api-client ^ + -i /local/openapi.yaml ^ + -o /local/apiserver ^ + --additional-properties="packageName=apiserver,sourceFolder=,outputAsLibrary=true" + +docker run --rm ^ + -v "%cd%":/local ^ + openapitools/openapi-generator-cli:v6.2.1 generate ^ + -g openapi ^ + -i /local/openapi.yaml ^ + -o /local/apiserver ^ + --additional-properties=outputFile=openapi.json + +goimports -w ./apiserver \ No newline at end of file diff --git a/generate-api-server.sh b/generate-api-server.sh new file mode 100755 index 0000000..356721c --- /dev/null +++ b/generate-api-server.sh @@ -0,0 +1,14 @@ +go install golang.org/x/tools/cmd/goimports@latest + +docker run --rm \ + --user $(id -u):$(id -g) \ + -v "${PWD}:/local" \ + openapitools/openapi-generator-cli:v6.2.1 generate \ + -g go-server \ + --git-user-id eliona-smart-building-assistant \ + --git-repo-id python-eliona-api-client \ + -i /local/openapi.yaml \ + -o /local/apiserver \ + --additional-properties="packageName=apiserver,sourceFolder=,outputAsLibrary=true" + +goimports -w ./apiserver \ No newline at end of file diff --git a/generate-db.cmd b/generate-db.cmd new file mode 100644 index 0000000..30177ac --- /dev/null +++ b/generate-db.cmd @@ -0,0 +1,9 @@ +go install github.com/volatiletech/sqlboiler/v4@latest +go install github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-psql@latest + +go get github.com/volatiletech/sqlboiler/v4 +go get github.com/volatiletech/null/v8 + +sqlboiler psql ^ + -c sqlboiler.toml ^ + --wipe --no-tests diff --git a/generate-db.sh b/generate-db.sh new file mode 100755 index 0000000..68de5ce --- /dev/null +++ b/generate-db.sh @@ -0,0 +1,11 @@ +go install github.com/volatiletech/sqlboiler/v4@latest +go install github.com/volatiletech/sqlboiler/v4/drivers/sqlboiler-psql@latest + +go get github.com/volatiletech/sqlboiler/v4 +go get github.com/volatiletech/null/v8 + +sqlboiler psql \ + -c sqlboiler.toml \ + --wipe --no-tests + +go mod tidy diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..ea51480 --- /dev/null +++ b/go.mod @@ -0,0 +1,40 @@ +module template + +go 1.20 + +require ( + github.com/eliona-smart-building-assistant/app-integration-tests v0.0.5 + github.com/eliona-smart-building-assistant/go-eliona v1.9.7 + github.com/eliona-smart-building-assistant/go-utils v1.0.30 + github.com/gorilla/mux v1.8.0 + github.com/volatiletech/sqlboiler/v4 v4.14.2 + gopkg.in/yaml.v3 v3.0.1 +) + +// Bugfix see: https://github.com/volatiletech/sqlboiler/blob/91c4f335dd886d95b03857aceaf17507c46f9ec5/README.md +// decimal library showing errors like: pq: encode: unknown type types.NullDecimal is a result of a too-new and broken version of the github.com/ericlargergren/decimal package, use the following version in your go.mod: github.com/ericlagergren/decimal v0.0.0-20181231230500-73749d4874d5 +replace github.com/ericlagergren/decimal => github.com/ericlagergren/decimal v0.0.0-20181231230500-73749d4874d5 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/eliona-smart-building-assistant/go-eliona-api-client/v2 v2.4.14 // indirect + github.com/friendsofgo/errors v0.9.2 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.0 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgtype v1.14.0 // indirect + github.com/jackc/pgx/v4 v4.18.1 // indirect + github.com/jackc/puddle v1.3.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/stretchr/testify v1.8.4 // indirect + github.com/volatiletech/inflect v0.0.1 // indirect + github.com/volatiletech/strmangle v0.0.4 // indirect + golang.org/x/crypto v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..fed1f7c --- /dev/null +++ b/go.sum @@ -0,0 +1,1101 @@ +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.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= +cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= +cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= +cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= +cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= +cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.0.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.0.0/go.mod h1:+6sju8gk8FRmSajX3Oz4G5Gm7P+mbqE9FVaXXFYTkCM= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/AzureAD/microsoft-authentication-library-for-go v0.4.0/go.mod h1:Vt9sXTKwMyGcOxSmLDMnGPgqsUg7m8pe215qMLrDXw4= +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/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apmckinlay/gsuneido v0.0.0-20180907175622-1f10244968e3/go.mod h1:hJnaqxrCRgMCTWtpNz9XUFkBCREiQdlcyK6YNmOfroM= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +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/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +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/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eliona-smart-building-assistant/app-integration-tests v0.0.5 h1:syohiP7FaNhWRAE+fTBLqN6B4T2mrWt2WNikM/Wq4Sc= +github.com/eliona-smart-building-assistant/app-integration-tests v0.0.5/go.mod h1:D5fA+9HOneH/CuBU0W0fkPb16QERDA9+N7eejKPS6rI= +github.com/eliona-smart-building-assistant/go-eliona v1.9.7 h1:seMXuz8IQn/QnXPP/OHkYyLuZNKOiZDjGRXihG+hc60= +github.com/eliona-smart-building-assistant/go-eliona v1.9.7/go.mod h1:4QgaDTC/A4tQ1lK4gnCaww6gyPmtSoxOHkq03vA8Wd4= +github.com/eliona-smart-building-assistant/go-eliona-api-client/v2 v2.4.14 h1:Jufr7Kn4sf3zrfk03vI4m9WIAQXv3IS1WFWVVK4BJwI= +github.com/eliona-smart-building-assistant/go-eliona-api-client/v2 v2.4.14/go.mod h1:AdhCjJsNuT2WA6HpC++Kf4SBO0ZDJhwc3QnYk59naFQ= +github.com/eliona-smart-building-assistant/go-utils v1.0.30 h1:7y41sFzRGZhJBBst7jYOjl+9qFrKVaWaxL+nSLAeIuU= +github.com/eliona-smart-building-assistant/go-utils v1.0.30/go.mod h1:rmn9OFVA5ADax/tKPYR54e9P7Yi47VHF4RepCZxg4es= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ericlagergren/decimal v0.0.0-20181231230500-73749d4874d5/go.mod h1:1yj25TwtUlJ+pfOu9apAVaM1RWfZGg+aFpd4hPQZekQ= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= +github.com/friendsofgo/errors v0.9.2 h1:X6NYxef4efCBdwI7BgS820zFaN7Cphrmb+Pljdzjtgk= +github.com/friendsofgo/errors v0.9.2/go.mod h1:yCvFW5AkDIL9qn7suHVLiI/gH228n7PC4Pn44IGoTOI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/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/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= +github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0/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.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= +github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/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/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= +github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pashagolub/pgxmock v1.6.0 h1:4zugVDde5sBKEsuDog0e7aqQRu/mGpxxQP4GMZ1F7Kk= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.6.0/go.mod h1:U8+INwJo3nBv1m6A/8OBXAq7Jnpspk5AxSgDyEQcea8= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.2.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/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU= +github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA= +github.com/volatiletech/null/v8 v8.1.2/go.mod h1:98DbwNoKEpRrYtGjWFctievIfm4n4MxG0A6EBUcoS5g= +github.com/volatiletech/randomize v0.0.1/go.mod h1:GN3U0QYqfZ9FOJ67bzax1cqZ5q2xuj2mXrXBjWaRTlY= +github.com/volatiletech/sqlboiler/v4 v4.14.2 h1:j5QnlR5/wYDmGDDTutI3BO+4oPBiqYoVrfReVr7VSxA= +github.com/volatiletech/sqlboiler/v4 v4.14.2/go.mod h1:65288sb8jBLnTynTumBK6eU8C2JwWsiPjoPihEfC0/A= +github.com/volatiletech/strmangle v0.0.1/go.mod h1:F6RA6IkB5vq0yTG4GQ0UsbbRcl3ni9P76i+JrTBKFFg= +github.com/volatiletech/strmangle v0.0.4 h1:CxrEPhobZL/PCZOTDSH1aq7s4Kv76hQpRoTVVlUOim4= +github.com/volatiletech/strmangle v0.0.4/go.mod h1:ycDvbDkjDvhC0NUU8w3fWwl5JEMTV56vTKXzR3GeR+0= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A= +go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.4/go.mod h1:Ud+VUwIi9/uQHOMA+4ekToJ12lTxlv0zB/+DHwTGEbU= +go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +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-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +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-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= +google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= +google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= +google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= +google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= +google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.81.0/go.mod h1:FA6Mb/bZxj706H2j+j2d6mHEEaHBmbbWnkfvmorOCko= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= +google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.2/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/cc/v3 v3.36.3/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI= +modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc= +modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw= +modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ= +modernc.org/ccgo/v3 v3.16.8/go.mod h1:zNjwkizS+fIFDrDjIAgBSCLkWbJuHF+ar3QRn+Z9aws= +modernc.org/ccgo/v3 v3.16.9/go.mod h1:zNMzC9A9xeNUepy6KuZBbugn3c0Mc9TeiJO4lgvkJDo= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A= +modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU= +modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU= +modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA= +modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0= +modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw= +modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.18.1/go.mod h1:6ho+Gow7oX5V+OiOQ6Tr4xeqbx13UZ6t+Fw9IRUG4d4= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw= +modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/icon b/icon new file mode 100644 index 0000000..544686f --- /dev/null +++ b/icon @@ -0,0 +1 @@ +data:image/jpeg;base64,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 \ No newline at end of file diff --git a/inegration_test.go b/inegration_test.go new file mode 100644 index 0000000..75cc272 --- /dev/null +++ b/inegration_test.go @@ -0,0 +1,21 @@ +package main + +import ( + "github.com/eliona-smart-building-assistant/app-integration-tests/app" + "github.com/eliona-smart-building-assistant/app-integration-tests/assert" + "github.com/eliona-smart-building-assistant/app-integration-tests/test" + "testing" +) + +func TestApp(t *testing.T) { + app.StartApp() + test.AppWorks(t) + t.Run("TestSchema", schema) + app.StopApp() +} + +func schema(t *testing.T) { + t.Parallel() + + assert.SchemaExists(t, "template", []string{ /* insert tables */ }) +} diff --git a/install_hook.sh b/install_hook.sh new file mode 100755 index 0000000..defc339 --- /dev/null +++ b/install_hook.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +HOOK_DIR=".git/hooks" +HOOK_FILE="${HOOK_DIR}/pre-commit" + +# Check if we're in a git repository +if [ ! -d "${HOOK_DIR}" ]; then + echo "Error: Not a git repository or no .git directory found" + exit 1 +fi + +# Define the hook content +HOOK_CONTENT='#!/bin/sh + +# Redirect output to stderr. +exec 1>&2 + +# Check for unformatted Go files. +unformatted=$(git diff --cached --name-only --diff-filter=ACM | grep ".go$" | xargs gofmt -l) +if [ ! -z "$unformatted" ]; then + echo >&2 "Go files must be formatted with gofmt. Unformatted files:" + echo >&2 "$unformatted" + exit 1 +fi +' + +# Write the hook content to the pre-commit file +echo "${HOOK_CONTENT}" > "${HOOK_FILE}" +chmod +x "${HOOK_FILE}" + +echo "pre-commit hook for go fmt installed successfully!" diff --git a/main.go b/main.go new file mode 100644 index 0000000..f986720 --- /dev/null +++ b/main.go @@ -0,0 +1,63 @@ +// This file is part of the eliona project. +// Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +// ______ _ _ +// | ____| (_) +// | |__ | |_ ___ _ __ __ _ +// | __| | | |/ _ \| '_ \ / _` | +// | |____| | | (_) | | | | (_| | +// |______|_|_|\___/|_| |_|\__,_| +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package main + +import ( + "template/conf" + "template/eliona" + "time" + + "github.com/eliona-smart-building-assistant/go-eliona/app" + "github.com/eliona-smart-building-assistant/go-utils/common" + "github.com/eliona-smart-building-assistant/go-utils/db" + "github.com/eliona-smart-building-assistant/go-utils/log" + "github.com/volatiletech/sqlboiler/v4/boil" +) + +// The main function starts the app by starting all services necessary for this app and waits +// until all services are finished. +func main() { + log.Info("main", "Starting the app.") + + // Set default database to use boil.*G functions. + database := db.Database(app.AppName()) + defer database.Close() + boil.SetDB(database) + + // Set the database logging level. + if log.Lev() >= log.DebugLevel { + boil.DebugMode = true + boil.DebugWriter = log.GetWriter(log.DebugLevel, "database") + } + + // Necessary to close used init resources, because db.Pool() is used in this app. + defer db.ClosePool() + + // Init the app before the first run. + app.Init(db.Pool(), app.AppName(), + app.ExecSqlFile("conf/init.sql"), + conf.InitConfiguration, + eliona.InitEliona, + ) + + // Starting the service to collect the data for this app. + common.WaitForWithOs( + common.Loop(doAnything, time.Second), + listenApi, + ) + + log.Info("main", "Terminate the app.") +} diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..5909d01 --- /dev/null +++ b/metadata.json @@ -0,0 +1,23 @@ +{ + "name": "template", + "elionaMinVersion": "v10.1.0", + "displayName": { + "en": "App template", + "de": "App Vorlage" + }, + "description": { + "en": "This template can be used to create an app stub for an Eliona environment.", + "de": "Diese Vorlage kann verwendet werden um eine App für Eliona zu erstellen." + }, + "dashboardTemplateNames": [ + "Template" + ], + "apiUrl": "v1", + "apiSpecificationPath": "/version/openapi.json", + "documentationUrl": "https://doc.eliona.io/eliona/referenzen/app-entwicklung", + "useEnvironment": [ + "CONNECTION_STRING", + "API_ENDPOINT", + "API_TOKEN" + ] +} diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..7d6c6f7 --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,159 @@ +openapi: 3.0.3 + +# This file is part of the eliona project. +# Copyright © 2022 LEICOM iTEC AG. All Rights Reserved. +# ______ _ _ +# | ____| (_) +# | |__ | |_ ___ _ __ __ _ +# | __| | | |/ _ \| '_ \ / _` | +# | |____| | | (_) | | | | (_| | +# |______|_|_|\___/|_| |_|\__,_| +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +info: + version: 1.0.0 + title: App template API + description: API to access and configure the app template +externalDocs: + description: Find out more about the app template + url: https://github.com/eliona-smart-building-assistant/app-template +servers: + - url: http://template/v1 + +tags: + - name: Configuration + description: Configure the app + externalDocs: + url: https://github.com/eliona-smart-building-assistant/app-template + + - name: Version + description: API version + externalDocs: + url: https://github.com/eliona-smart-building-assistant/app-template + + - name: Customization + description: Help to customize Eliona environment + externalDocs: + url: https://github.com/eliona-smart-building-assistant/app-template + +paths: + /configurations: + get: + tags: + - Configuration + summary: Get configurations + description: Gets information about all configurations. + operationId: getConfigurations + responses: + "200": + description: Successfully returned all configurations + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Configuration' + post: + tags: + - Configuration + summary: Creates a configuration + description: Creates a configuration. + operationId: postConfiguration + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Configuration' + responses: + "201": + description: Successfully created a configuration + content: + application/json: + schema: + $ref: '#/components/schemas/Configuration' + + /version: + get: + summary: Version of the API + description: Gets information about the APIs version. + operationId: getVersion + tags: + - Version + responses: + "200": + description: Successfully returned the APIs version. + content: + application/json: + schema: + type: object + + /version/openapi.json: + get: + summary: OpenAPI specification for this API version + description: Gets specification for this API version as an openapi.json file. + operationId: getOpenAPI + tags: + - Version + responses: + "200": + description: Successfully returned the openapi.json file. + content: + application/json: + schema: + type: object + + /dashboard-templates/{dashboard-template-name}: + get: + tags: + - Customization + summary: Get a full dashboard template + description: Delivers a dashboard template which can assigned to users in Eliona + externalDocs: + description: The API to assign the dashboard to users in Eliona (see post /dashboards endpoint). + url: https://github.com/eliona-smart-building-assistant/eliona-api + operationId: getDashboardTemplateByName + parameters: + - name: dashboard-template-name + in: path + description: Name of the dashboard template + required: true + schema: + type: string + example: Template + - name: projectId + in: query + description: Define the project the dashboard should be + required: true + schema: + type: string + example: 99 + responses: + "200": + description: Successfully returned dashboard template + content: + application/json: + schema: + $ref: 'https://raw.githubusercontent.com/eliona-smart-building-assistant/eliona-api/main/openapi.yaml#/components/schemas/Dashboard' + "404": + description: Template name not found + +components: + schemas: + Configuration: + type: object + description: Simply a example configuration + properties: + id: + type: integer + format: int64 + description: A id identifying the example configuration + readOnly: true + nullable: true + config: + type: string + description: Configuration data for example diff --git a/pipeline/build-pipeline.yml b/pipeline/build-pipeline.yml new file mode 100644 index 0000000..34fcf16 --- /dev/null +++ b/pipeline/build-pipeline.yml @@ -0,0 +1,25 @@ +# ______ _ _ +# | ____| (_) +# | |__ | |_ ___ _ __ __ _ +# | __| | | |/ _ \| '_ \ / _` | +# | |____| | | (_) | | | | (_| | +# |______|_|_|\___/|_| |_|\__,_| +# +name: $(Build.DefinitionName)_$(Build.SourceBranchName)_$(Date:yyyyMMdd) + +trigger: + batch: true + tags: + include: + - 'v*' + branches: + include: + - develop + +resources: + repositories: + - repository: pipeline + type: git + name: utils/pipeline +stages: + - template: "stages/build/stage-build-github.yml@pipeline" diff --git a/pipeline/deploy-pipeline.yml b/pipeline/deploy-pipeline.yml new file mode 100644 index 0000000..11a9f34 --- /dev/null +++ b/pipeline/deploy-pipeline.yml @@ -0,0 +1,24 @@ +parameters: + - name: deploymentEnvironment + type: string + default: experimental + - name: repository + type: string + - name: deploymentRepository + type: string + +name: $(Build.DefinitionName)_${{ parameters.deploymentEnvironment }}_$(Date:yyyyMMdd) +trigger: none + +resources: + repositories: + - repository: pipeline + type: git + name: utils/pipeline + +extends: + template: 'jobs/deployment-from-docker-hub.yml@pipeline' + parameters: + deploymentEnvironment: ${{ parameters.deploymentEnvironment }} + repository: ${{ parameters.repository }} + deploymentRepository: ${{ parameters.deploymentRepository }} diff --git a/reset.sql b/reset.sql new file mode 100644 index 0000000..9f32ac0 --- /dev/null +++ b/reset.sql @@ -0,0 +1,68 @@ +-- This file is part of the eliona project. +-- Copyright © 2023 LEICOM iTEC AG. All Rights Reserved. +-- ______ _ _ +-- | ____| (_) +-- | |__ | |_ ___ _ __ __ _ +-- | __| | | |/ _ \| '_ \ / _` | +-- | |____| | | (_) | | | | (_| | +-- |______|_|_|\___/|_| |_|\__,_| +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +-- BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +-- NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +-- DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +-- This idempotent script resets the database to a defined state ready for testing. +-- The only thing that remains after testing then are the incremented auto-increment values and app +-- registration (which you can optionally remove as well by uncommenting the last command). + +DELETE FROM versioning.patches +WHERE app_name = 'template'; + +INSERT INTO public.eliona_store (app_name, category, version) +VALUES ('template', 'app', '1.0.0') + ON CONFLICT (app_name) DO UPDATE SET version = '1.0.0'; + +INSERT INTO public.eliona_app (app_name, enable) +VALUES ('template', 't') + ON CONFLICT (app_name) DO UPDATE SET initialized_at = null; + +DROP SCHEMA IF EXISTS template CASCADE; + +DELETE FROM heap +WHERE asset_id IN ( + SELECT asset_id + FROM asset + WHERE asset_type LIKE E'template\\_%' +); + +DELETE FROM attribute_schema +WHERE asset_type LIKE E'template\\_%'; + +DELETE FROM asset +WHERE asset_type LIKE E'template\\_%'; + +DELETE FROM asset_type +WHERE asset_type LIKE E'template\\_%'; + +DELETE FROM public.widget_data +WHERE widget_id IN ( + SELECT public.widget.id + FROM public.widget + JOIN public.dashboard USING (dashboard_id) + WHERE public.dashboard.name LIKE 'Template%' +); + +DELETE FROM public.widget +WHERE dashboard_id IN ( + SELECT dashboard_id + FROM public.dashboard + WHERE name LIKE 'Template%' +); + +DELETE FROM public.dashboard +WHERE name LIKE 'Template%'; + +-- DELETE FROM eliona_app WHERE app_name = 'template'; +-- DELETE FROM eliona_store WHERE app_name = 'template'; diff --git a/sqlboiler.toml b/sqlboiler.toml new file mode 100644 index 0000000..dd9d226 --- /dev/null +++ b/sqlboiler.toml @@ -0,0 +1,30 @@ +output = "appdb" +pkgname = "appdb" +add-global-variants = true +wipe = true +no-tests = true +add-enum-types = true + +[psql] +dbname = "postgres" +host = "localhost" +port = 5432 +user = "postgres" +pass = "secret" +schema = "template" +sslmode = "disable" + +[[types]] +[types.match] +type = "null.Int" +nullable = true + +[types.replace] +type = "null.Int32" + +[[types]] +[types.match] +type = "int" + +[types.replace] +type = "int32"