diff --git a/echo_v3/example/docs/docs.go b/echo_v3/example/docs/docs.go new file mode 100644 index 0000000..d783604 --- /dev/null +++ b/echo_v3/example/docs/docs.go @@ -0,0 +1,45 @@ +// Package docs Code generated by swaggo/swag. DO NOT EDIT +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "API Support", + "url": "http://www.swagger.io/support", + "email": "support@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": {} +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "petstore.swagger.io", + BasePath: "/v2", + Schemes: []string{}, + Title: "Swagger Example API With Echo V3", + Description: "This is a sample server Petstore server.", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/echo_v3/example/docs/swagger.json b/echo_v3/example/docs/swagger.json new file mode 100644 index 0000000..e3dd377 --- /dev/null +++ b/echo_v3/example/docs/swagger.json @@ -0,0 +1,21 @@ +{ + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server.", + "title": "Swagger Example API With Echo V3", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "API Support", + "url": "http://www.swagger.io/support", + "email": "support@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0" + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "paths": {} +} \ No newline at end of file diff --git a/echo_v3/example/docs/swagger.yaml b/echo_v3/example/docs/swagger.yaml new file mode 100644 index 0000000..820fc7a --- /dev/null +++ b/echo_v3/example/docs/swagger.yaml @@ -0,0 +1,16 @@ +basePath: /v2 +host: petstore.swagger.io +info: + contact: + email: support@swagger.io + name: API Support + url: http://www.swagger.io/support + description: This is a sample server Petstore server. + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0.html + termsOfService: http://swagger.io/terms/ + title: Swagger Example API With Echo V3 + version: "1.0" +paths: {} +swagger: "2.0" diff --git a/echo_v3/example/main.go b/echo_v3/example/main.go new file mode 100644 index 0000000..81c18ba --- /dev/null +++ b/echo_v3/example/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "github.com/labstack/echo" + "github.com/swaggo/echo-swagger/echo_v3" + _ "github.com/swaggo/echo-swagger/example/docs" // docs is generated by Swag CLI, you have to import it. +) + +// @title Swagger Example API With Echo V3 +// @version 1.0 +// @description This is a sample server Petstore server. +// @termsOfService http://swagger.io/terms/ + +// @contact.name API Support +// @contact.url http://www.swagger.io/support +// @contact.email support@swagger.io + +// @license.name Apache 2.0 +// @license.url http://www.apache.org/licenses/LICENSE-2.0.html + +// @host petstore.swagger.io +// @BasePath /v2 +func main() { + e := echo.New() + + e.GET("/swagger/*", echo_v3.WrapHandler) + + /* + Or can use EchoWrapHandler func with configurations. + url := echoSwagger.URL("http://localhost:1323/swagger/doc.json") //The url pointing to API definition + e.GET("/swagger/*", echoSwagger.EchoWrapHandler(url)) + */ + e.Logger.Fatal(e.Start(":1323")) +} diff --git a/echo_v3/swagger_echo_v3.go b/echo_v3/swagger_echo_v3.go new file mode 100644 index 0000000..c27e853 --- /dev/null +++ b/echo_v3/swagger_echo_v3.go @@ -0,0 +1,311 @@ +package echo_v3 + +import ( + "html/template" + "net/http" + "path/filepath" + "regexp" + + "github.com/ghodss/yaml" + "github.com/labstack/echo" + swaggerFiles "github.com/swaggo/files/v2" + "github.com/swaggo/swag" +) + +// Config stores echoSwagger configuration variables. +type Config struct { + // The url pointing to API definition (normally swagger.json or swagger.yaml). Default is `mockedSwag.json`. + URLs []string + DocExpansion string + DomID string + InstanceName string + DeepLinking bool + PersistAuthorization bool + SyntaxHighlight bool + + // The information for OAuth2 integration, if any. + OAuth *OAuthConfig +} + +// OAuthConfig stores configuration for Swagger UI OAuth2 integration. See +// https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/ for further details. +type OAuthConfig struct { + // The ID of the client sent to the OAuth2 IAM provider. + ClientId string + + // The OAuth2 realm that the client should operate in. If not applicable, use empty string. + Realm string + + // The name to display for the application in the authentication popup. + AppName string +} + +// URL presents the url pointing to API definition (normally swagger.json or swagger.yaml). +func URL(url string) func(*Config) { + return func(c *Config) { + c.URLs = append(c.URLs, url) + } +} + +// DeepLinking true, false. +func DeepLinking(deepLinking bool) func(*Config) { + return func(c *Config) { + c.DeepLinking = deepLinking + } +} + +// SyntaxHighlight true, false. +func SyntaxHighlight(syntaxHighlight bool) func(*Config) { + return func(c *Config) { + c.SyntaxHighlight = syntaxHighlight + } +} + +// DocExpansion list, full, none. +func DocExpansion(docExpansion string) func(*Config) { + return func(c *Config) { + c.DocExpansion = docExpansion + } +} + +// DomID #swagger-ui. +func DomID(domID string) func(*Config) { + return func(c *Config) { + c.DomID = domID + } +} + +// InstanceName specified swag instance name. +func InstanceName(instanceName string) func(*Config) { + return func(c *Config) { + c.InstanceName = instanceName + } +} + +// PersistAuthorization Persist authorization information over browser close/refresh. +// Defaults to false. +func PersistAuthorization(persistAuthorization bool) func(*Config) { + return func(c *Config) { + c.PersistAuthorization = persistAuthorization + } +} + +func OAuth(config *OAuthConfig) func(*Config) { + return func(c *Config) { + c.OAuth = config + } +} + +func newConfig(configFns ...func(*Config)) *Config { + config := Config{ + URLs: []string{"doc.json", "doc.yaml"}, + DocExpansion: "list", + DomID: "swagger-ui", + InstanceName: "swagger", + DeepLinking: true, + PersistAuthorization: false, + SyntaxHighlight: true, + } + + for _, fn := range configFns { + fn(&config) + } + + if config.InstanceName == "" { + config.InstanceName = swag.Name + } + + return &config +} + +// WrapHandler wraps swaggerFiles.Handler and returns echo.HandlerFunc +var WrapHandler = EchoWrapHandler() + +// EchoWrapHandler wraps `http.Handler` into `echo.HandlerFunc`. +func EchoWrapHandler(options ...func(*Config)) echo.HandlerFunc { + config := newConfig(options...) + + // create a template with name + index, _ := template.New("swagger_index.html").Parse(indexTemplate) + + var re = regexp.MustCompile(`^(.*/)([^?].*)?[?|.]*$`) + + return func(c echo.Context) error { + if c.Request().Method != http.MethodGet { + return echo.NewHTTPError(http.StatusMethodNotAllowed, http.StatusText(http.StatusMethodNotAllowed)) + } + + matches := re.FindStringSubmatch(c.Request().RequestURI) + path := matches[2] + + switch filepath.Ext(path) { + case ".html": + c.Response().Header().Set("Content-Type", "text/html; charset=utf-8") + case ".css": + c.Response().Header().Set("Content-Type", "text/css; charset=utf-8") + case ".js": + c.Response().Header().Set("Content-Type", "application/javascript") + case ".json": + c.Response().Header().Set("Content-Type", "application/json; charset=utf-8") + case ".yaml": + c.Response().Header().Set("Content-Type", "text/plain; charset=utf-8") + case ".png": + c.Response().Header().Set("Content-Type", "image/png") + } + + response := c.Response() + // This check fixes an error introduced here: https://github.com/labstack/echo/blob/8da8e161380fd926d4341721f0328f1e94d6d0a2/response.go#L86-L88 + if _, ok := response.Writer.(http.Flusher); ok { + defer response.Flush() + } + + switch path { + case "": + _ = c.Redirect(http.StatusMovedPermanently, matches[1]+"/"+"index.html") + case "index.html": + _ = index.Execute(c.Response().Writer, config) + case "doc.json": + doc, err := swag.ReadDoc(config.InstanceName) + if err != nil { + c.Error(err) + + return nil + } + + _, _ = c.Response().Writer.Write([]byte(doc)) + case "doc.yaml": + jsonString, err := swag.ReadDoc(config.InstanceName) + if err != nil { + c.Error(err) + + return nil + } + doc, err := yaml.JSONToYAML([]byte(jsonString)) + if err != nil { + c.Error(err) + + return nil + } + _, _ = c.Response().Writer.Write(doc) + default: + c.Request().URL.Path = matches[2] + http.FileServer(http.FS(swaggerFiles.FS)).ServeHTTP(c.Response(), c.Request()) + } + + return nil + } +} + +const indexTemplate = ` + + + + + Swagger UI + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +` diff --git a/echo_v3/swagger_echo_v3_test.go b/echo_v3/swagger_echo_v3_test.go new file mode 100644 index 0000000..b18cf58 --- /dev/null +++ b/echo_v3/swagger_echo_v3_test.go @@ -0,0 +1,434 @@ +package echo_v3 + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "testing" + + "github.com/labstack/echo" + "github.com/stretchr/testify/assert" + "github.com/swaggo/swag" +) + +type mockedSwag struct{} + +func (s *mockedSwag) ReadDoc() string { + return `{ + "swagger": "2.0", + "info": { + "description": "This is a sample server Petstore server.", + "title": "Swagger Example API", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "API Support", + "url": "http://www.swagger.io/support", + "email": "support@swagger.io" + }, + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + }, + "version": "1.0" + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "paths": { + "/file/upload": { + "post": { + "description": "Upload file", + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "summary": "Upload file", + "operationId": "file.upload", + "parameters": [ + { + "type": "file", + "description": "this is a test file", + "name": "file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "400": { + "description": "We need ID!!", + "schema": { + "type": "object", + "$ref": "#/definitions/web.APIError" + } + }, + "404": { + "description": "Can not find ID", + "schema": { + "type": "object", + "$ref": "#/definitions/web.APIError" + } + } + } + } + }, + "/testapi/get-string-by-int/{some_id}": { + "get": { + "description": "get string by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "summary": "Add a new pet to the store", + "operationId": "get-string-by-int", + "parameters": [ + { + "type": "int", + "description": "Some ID", + "name": "some_id", + "in": "path", + "required": true + }, + { + "description": "Some ID", + "name": "some_id", + "in": "body", + "required": true, + "schema": { + "type": "object", + "$ref": "#/definitions/web.Pet" + } + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "400": { + "description": "We need ID!!", + "schema": { + "type": "object", + "$ref": "#/definitions/web.APIError" + } + }, + "404": { + "description": "Can not find ID", + "schema": { + "type": "object", + "$ref": "#/definitions/web.APIError" + } + } + } + } + }, + "/testapi/get-struct-array-by-string/{some_id}": { + "get": { + "description": "get struct array by ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "operationId": "get-struct-array-by-string", + "parameters": [ + { + "type": "string", + "description": "Some ID", + "name": "some_id", + "in": "path", + "required": true + }, + { + "type": "int", + "description": "Offset", + "name": "offset", + "in": "query", + "required": true + }, + { + "type": "int", + "description": "Offset", + "name": "limit", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "ok", + "schema": { + "type": "string" + } + }, + "400": { + "description": "We need ID!!", + "schema": { + "type": "object", + "$ref": "#/definitions/web.APIError" + } + }, + "404": { + "description": "Can not find ID", + "schema": { + "type": "object", + "$ref": "#/definitions/web.APIError" + } + } + } + } + } + }, + "definitions": { + "web.APIError": { + "type": "object", + "properties": { + "CreatedAt": { + "type": "string", + "format": "date-time" + }, + "ErrorCode": { + "type": "integer" + }, + "ErrorMessage": { + "type": "string" + } + } + }, + "web.Pet": { + "type": "object", + "properties": { + "Category": { + "type": "object" + }, + "ID": { + "type": "integer" + }, + "Name": { + "type": "string" + }, + "PhotoUrls": { + "type": "array" + }, + "Status": { + "type": "string" + }, + "Tags": { + "type": "array" + } + } + } + } +}` +} + +func TestWrapHandler(t *testing.T) { + router := echo.New() + + router.Any("/*", EchoWrapHandler(DocExpansion("none"), DomID("swagger-ui"))) + + w1 := performRequest(http.MethodGet, "/index.html", router) + assert.Equal(t, http.StatusOK, w1.Code) + assert.Equal(t, w1.Header()["Content-Type"][0], "text/html; charset=utf-8") + + assert.Equal(t, http.StatusInternalServerError, performRequest(http.MethodGet, "/doc.json", router).Code) + + doc := &mockedSwag{} + swag.Register(swag.Name, doc) + w2 := performRequest(http.MethodGet, "/doc.json", router) + assert.Equal(t, http.StatusOK, w2.Code) + assert.Equal(t, w2.Header()["Content-Type"][0], "application/json; charset=utf-8") + + // Perform body rendering validation + w2Body, err := ioutil.ReadAll(w2.Body) + assert.NoError(t, err) + assert.Equal(t, doc.ReadDoc(), string(w2Body)) + + w3 := performRequest(http.MethodGet, "/favicon-16x16.png", router) + assert.Equal(t, http.StatusOK, w3.Code) + assert.Equal(t, w3.Header()["Content-Type"][0], "image/png") + + w4 := performRequest(http.MethodGet, "/swagger-ui.css", router) + assert.Equal(t, http.StatusOK, w4.Code) + assert.Equal(t, w4.Header()["Content-Type"][0], "text/css; charset=utf-8") + + w5 := performRequest(http.MethodGet, "/swagger-ui-bundle.js", router) + assert.Equal(t, http.StatusOK, w5.Code) + assert.Equal(t, w5.Header()["Content-Type"][0], "application/javascript") + + assert.Equal(t, http.StatusNotFound, performRequest(http.MethodGet, "/notfound", router).Code) + + assert.Equal(t, http.StatusMovedPermanently, performRequest(http.MethodGet, "/", router).Code) + + assert.Equal(t, http.StatusMethodNotAllowed, performRequest(http.MethodPost, "/index.html", router).Code) + + assert.Equal(t, http.StatusMethodNotAllowed, performRequest(http.MethodPut, "/index.html", router).Code) + +} + +func TestConfig(t *testing.T) { + router := echo.New() + + swaggerHandler := URL("swagger.json") + router.Any("/*", EchoWrapHandler(swaggerHandler)) + + w := performRequest("GET", "/index.html", router) + assert.Equal(t, 200, w.Code) + assert.Contains(t, w.Body.String(), `url: "swagger.json"`) +} + +func TestConfigWithOAuth(t *testing.T) { + router := echo.New() + + swaggerHandler := EchoWrapHandler(OAuth(&OAuthConfig{ + ClientId: "my-client-id", + Realm: "my-realm", + AppName: "My App Name", + })) + router.GET("/*", swaggerHandler) + + w := performRequest("GET", "/index.html", router) + assert.Equal(t, 200, w.Code) + body := w.Body.String() + assert.Contains(t, body, `ui.initOAuth({ + clientId: "my-client-id", + realm: "my-realm", + appName: "My App Name" + })`) +} + +func TestHandlerReuse(t *testing.T) { + router := echo.New() + + router.GET("/swagger/*", EchoWrapHandler()) + router.GET("/admin/swagger/*", EchoWrapHandler()) + + w1 := performRequest(http.MethodGet, "/swagger/index.html", router) + assert.Equal(t, http.StatusOK, w1.Code) + assert.Equal(t, w1.Header()["Content-Type"][0], "text/html; charset=utf-8") + + w2 := performRequest(http.MethodGet, "/admin/swagger/index.html", router) + assert.Equal(t, http.StatusOK, w2.Code) + assert.Equal(t, w2.Header()["Content-Type"][0], "text/html; charset=utf-8") + + w3 := performRequest(http.MethodGet, "/swagger/index.html", router) + assert.Equal(t, http.StatusOK, w3.Code) + assert.Equal(t, w3.Header()["Content-Type"][0], "text/html; charset=utf-8") + + w4 := performRequest(http.MethodGet, "/admin/swagger/index.html", router) + assert.Equal(t, http.StatusOK, w4.Code) + assert.Equal(t, w4.Header()["Content-Type"][0], "text/html; charset=utf-8") +} + +type httpWriter struct{} + +func (h httpWriter) Header() http.Header { + return http.Header{} +} + +func (h httpWriter) Write(bytes []byte) (int, error) { + return len(bytes), nil +} + +func (h httpWriter) WriteHeader(_ int) {} + +func TestMissingFlusher(t *testing.T) { + router := echo.New() + + router.GET("/swagger/*", EchoWrapHandler()) + + r := httptest.NewRequest(http.MethodGet, "/swagger/index.html", nil) + router.ServeHTTP(httpWriter{}, r) +} + +func performRequest(method, target string, e http.Handler) *httptest.ResponseRecorder { + r := httptest.NewRequest(method, target, nil) + w := httptest.NewRecorder() + + e.ServeHTTP(w, r) + return w +} + +func TestURL(t *testing.T) { + var cfg Config + expected := "https://github.com/swaggo/http-swagger" + URL(expected)(&cfg) + assert.Equal(t, expected, cfg.URLs[0]) +} + +func TestDeepLinking(t *testing.T) { + var cfg Config + expected := true + DeepLinking(expected)(&cfg) + assert.Equal(t, expected, cfg.DeepLinking) +} + +func TestSyntaxHighlight(t *testing.T) { + var cfg Config + expected := true + SyntaxHighlight(expected)(&cfg) + assert.Equal(t, expected, cfg.SyntaxHighlight) +} + +func TestDocExpansion(t *testing.T) { + var cfg Config + expected := "https://github.com/swaggo/docs" + DocExpansion(expected)(&cfg) + assert.Equal(t, expected, cfg.DocExpansion) +} + +func TestDomID(t *testing.T) { + var cfg Config + expected := "swagger-ui" + DomID(expected)(&cfg) + assert.Equal(t, expected, cfg.DomID) +} + +func TestInstanceName(t *testing.T) { + var cfg Config + + expected := "custom-instance-name" + InstanceName(expected)(&cfg) + assert.Equal(t, expected, cfg.InstanceName) + + newCfg := newConfig(InstanceName("")) + assert.Equal(t, swag.Name, newCfg.InstanceName) +} + +func TestPersistAuthorization(t *testing.T) { + var cfg Config + expected := true + PersistAuthorization(expected)(&cfg) + assert.Equal(t, expected, cfg.PersistAuthorization) +} + +func TestOAuth(t *testing.T) { + var cfg Config + expected := OAuthConfig{ + ClientId: "my-client-id", + Realm: "my-realm", + AppName: "My App Name", + } + OAuth(&expected)(&cfg) + assert.Equal(t, expected.ClientId, cfg.OAuth.ClientId) + assert.Equal(t, expected.Realm, cfg.OAuth.Realm) + assert.Equal(t, expected.AppName, cfg.OAuth.AppName) +} + +func TestOAuthNil(t *testing.T) { + var cfg Config + var expected *OAuthConfig + OAuth(expected)(&cfg) + assert.Equal(t, expected, cfg.OAuth) +} diff --git a/go.mod b/go.mod index 1b50ec8..98a86f9 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,9 @@ go 1.17 require ( github.com/ghodss/yaml v1.0.0 + github.com/labstack/echo v3.3.10+incompatible github.com/labstack/echo/v4 v4.9.0 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.4 github.com/swaggo/files/v2 v2.0.0 github.com/swaggo/swag v1.8.12 ) @@ -20,18 +21,18 @@ require ( github.com/go-openapi/spec v0.20.4 // indirect github.com/go-openapi/swag v0.19.15 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/labstack/gommon v0.3.1 // indirect + github.com/labstack/gommon v0.4.2 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-colorable v0.1.11 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.1 // indirect - golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.8.0 // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect - golang.org/x/tools v0.7.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9886809..e7b1014 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,7 @@ github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -30,19 +31,25 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= +github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/echo/v4 v4.9.0 h1:wPOF1CE6gvt/kmbMR4dGzWvHMPT+sAEUJOwOTtvITVY= github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= -github.com/labstack/gommon v0.3.1 h1:OomWaJXm7xR6L1HmEtGyQf26TEn7V6X88mktX9kee9o= github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 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-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -50,10 +57,15 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= 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.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +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/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw= github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w= @@ -61,30 +73,45 @@ github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -95,27 +122,47 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= 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/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/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.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 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= @@ -128,5 +175,5 @@ 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-20200615113413-eeeca48fe776/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 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= -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=