From 97467966a4db33a45732f6f5d967b7ec5cb7a754 Mon Sep 17 00:00:00 2001 From: Toboshii Nakama <63410334+toboshii@users.noreply.github.com> Date: Thu, 23 Sep 2021 08:05:18 -0500 Subject: [PATCH 01/46] Initial work to move to an SPA architecture --- .air.toml | 32 + .gitignore | 9 +- go.mod | 1 + go.sum | 2 + internal/config/config.go | 8 +- internal/hajimari/customapps/customapps.go | 39 +- internal/hajimari/hajimari.go | 9 - internal/hajimari/ingressapps/apps.go | 39 +- internal/handlers/apps.go | 125 ++ internal/handlers/bookmarks.go | 80 + internal/handlers/errors.go | 45 + internal/handlers/handler.go | 51 + internal/handlers/startpage.go | 501 ++--- internal/models/app.go | 7 + internal/models/app_group.go | 6 + internal/models/bookmark.go | 7 + internal/models/bookmark_group.go | 6 + internal/models/models.go | 17 - internal/models/startpage.go | 6 + internal/services/startpage.go | 160 +- internal/stores/memory.go | 160 +- main.go | 37 +- web/.gitignore | 4 + web/README.md | 107 + web/package-lock.json | 1819 +++++++++++++++++ web/package.json | 23 + web/public/favicon.png | Bin 0 -> 3127 bytes .../css/styles.css => public/global.css} | 204 +- web/public/index.html | 19 + web/rollup.config.js | 76 + web/scripts/setupTypeScript.js | 121 ++ web/src/App.svelte | 131 ++ web/src/AppList/AppGroup.svelte | 74 + web/src/AppList/index.svelte | 66 + web/src/BookmarkList/BookmarkGroup.svelte | 16 + web/src/BookmarkList/index.svelte | 68 + web/src/header.svelte | 16 + web/src/main.js | 7 + web/src/store.js | 20 + web/static/js/main.js | 46 - web/static/js/search.js | 95 - web/static/js/themer.js | 139 -- web/template/index.html.tmpl | 141 -- 43 files changed, 3407 insertions(+), 1132 deletions(-) create mode 100644 .air.toml delete mode 100644 internal/hajimari/hajimari.go create mode 100644 internal/handlers/apps.go create mode 100644 internal/handlers/bookmarks.go create mode 100644 internal/handlers/errors.go create mode 100644 internal/models/app.go create mode 100644 internal/models/app_group.go create mode 100644 internal/models/bookmark.go create mode 100644 internal/models/bookmark_group.go delete mode 100644 internal/models/models.go create mode 100644 internal/models/startpage.go create mode 100644 web/.gitignore create mode 100644 web/README.md create mode 100644 web/package-lock.json create mode 100644 web/package.json create mode 100644 web/public/favicon.png rename web/{static/css/styles.css => public/global.css} (68%) mode change 100755 => 100644 create mode 100644 web/public/index.html create mode 100644 web/rollup.config.js create mode 100644 web/scripts/setupTypeScript.js create mode 100644 web/src/App.svelte create mode 100644 web/src/AppList/AppGroup.svelte create mode 100644 web/src/AppList/index.svelte create mode 100644 web/src/BookmarkList/BookmarkGroup.svelte create mode 100644 web/src/BookmarkList/index.svelte create mode 100644 web/src/header.svelte create mode 100644 web/src/main.js create mode 100644 web/src/store.js delete mode 100644 web/static/js/main.js delete mode 100755 web/static/js/search.js delete mode 100755 web/static/js/themer.js delete mode 100644 web/template/index.html.tmpl diff --git a/.air.toml b/.air.toml new file mode 100644 index 00000000..d5ee9275 --- /dev/null +++ b/.air.toml @@ -0,0 +1,32 @@ +root = "." +tmp_dir = "tmp" + +[build] + bin = "./tmp/main" + cmd = "go build -o ./tmp/main ." + delay = 1000 + exclude_dir = ["web", "docs", "charts", "tmp", "vendor"] + exclude_file = [] + exclude_regex = [] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go", "tpl", "tmpl", "html"] + kill_delay = "0s" + log = "build-errors.log" + send_interrupt = false + stop_on_error = true + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + time = false + +[misc] + clean_on_exit = true diff --git a/.gitignore b/.gitignore index 677b69ae..c3568529 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ *.dll *.so *.dylib +tmp # Test binary, built with `go test -c` *.test @@ -18,4 +19,10 @@ # Chart dependencies charts/hajimari/charts charts/hajimari/Chart.lock -charts/hajimari/local.yaml \ No newline at end of file +charts/hajimari/local.yaml + +# UI dependencies +node_modules +public/build/ + +.DS_Store \ No newline at end of file diff --git a/go.mod b/go.mod index 23c310cd..f63a3a3f 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/chi-middleware/logrus-logger v0.2.0 github.com/go-chi/chi v1.5.4 github.com/go-chi/chi/v5 v5.0.3 + github.com/go-chi/cors v1.2.0 github.com/go-chi/render v1.0.1 github.com/matoous/go-nanoid/v2 v2.0.0 github.com/onrik/logrus v0.9.0 diff --git a/go.sum b/go.sum index 0c011766..78c47ee6 100644 --- a/go.sum +++ b/go.sum @@ -95,6 +95,8 @@ github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIu github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= +github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= diff --git a/internal/config/config.go b/internal/config/config.go index 8233761f..902d664f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -34,8 +34,8 @@ type CustomApp struct { } type Group struct { - Name string - Links []Link + Name string `json:"name"` + Links []Link `json:"links"` } type Provider struct { @@ -52,8 +52,8 @@ type Module struct { } type Link struct { - Name string - URL string + Name string `json:"name"` + URL string `json:"url"` } // NamespaceSelector struct for selecting namespaces based on labels and names diff --git a/internal/hajimari/customapps/customapps.go b/internal/hajimari/customapps/customapps.go index 85b37e55..3bc1aba7 100644 --- a/internal/hajimari/customapps/customapps.go +++ b/internal/hajimari/customapps/customapps.go @@ -2,8 +2,8 @@ package customapps import ( "github.com/toboshii/hajimari/internal/config" - "github.com/toboshii/hajimari/internal/hajimari" "github.com/toboshii/hajimari/internal/log" + "github.com/toboshii/hajimari/internal/models" ) var ( @@ -14,7 +14,7 @@ var ( type List struct { appConfig config.Config err error // Used for forwarding errors - items []hajimari.App + items []models.AppGroup } // NewList func creates a new instance of apps lister @@ -32,21 +32,38 @@ func (al *List) Populate() *List { } // Get function returns the apps currently present in List -func (al *List) Get() ([]hajimari.App, error) { +func (al *List) Get() ([]models.AppGroup, error) { return al.items, al.err } -func convertCustomAppsToHajimariApps(customApps []config.CustomApp) (apps []hajimari.App) { +func convertCustomAppsToHajimariApps(customApps []config.CustomApp) (appGroups []models.AppGroup) { for _, customApp := range customApps { logger.Debugf("Found custom app with Name '%v'", customApp.Name) - apps = append(apps, hajimari.App{ - Name: customApp.Name, - URL: customApp.URL, - Icon: customApp.Icon, - Group: customApp.Group, - }) + groupMap := make(map[string]int, len(appGroups)) + for i, v := range appGroups { + groupMap[v.Name] = i + } + + if _, ok := groupMap[customApp.Group]; !ok { + appGroups = append(appGroups, models.AppGroup{ + Name: customApp.Group, + }) + } + + appMap := make(map[string]int, len(appGroups)) + for i, v := range appGroups { + appMap[v.Name] = i + } + + if i, ok := appMap[customApp.Group]; ok { + appGroups[i].Apps = append(appGroups[i].Apps, models.App{ + Name: customApp.Name, + Icon: customApp.Icon, + URL: customApp.URL, + }) + } } - return apps + return } diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go deleted file mode 100644 index d1bc0821..00000000 --- a/internal/hajimari/hajimari.go +++ /dev/null @@ -1,9 +0,0 @@ -package hajimari - -// App struct that contains information about an app that is enabled in hajimari -type App struct { - Name string - Icon string - Group string - URL string -} diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index 9af2a590..3a0afc7e 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -3,10 +3,10 @@ package ingressapps import ( "github.com/toboshii/hajimari/internal/annotations" "github.com/toboshii/hajimari/internal/config" - "github.com/toboshii/hajimari/internal/hajimari" "github.com/toboshii/hajimari/internal/kube/lists/ingresses" "github.com/toboshii/hajimari/internal/kube/wrappers" "github.com/toboshii/hajimari/internal/log" + "github.com/toboshii/hajimari/internal/models" "k8s.io/api/extensions/v1beta1" "k8s.io/client-go/kubernetes" ) @@ -19,7 +19,7 @@ var ( type List struct { appConfig config.Config err error // Used for forwarding errors - items []hajimari.App + items []models.AppGroup kubeClient kubernetes.Interface } @@ -53,21 +53,40 @@ func (al *List) Populate(namespaces ...string) *List { } // Get function returns the apps currently present in List -func (al *List) Get() ([]hajimari.App, error) { +func (al *List) Get() ([]models.AppGroup, error) { return al.items, al.err } -func convertIngressesToHajimariApps(ingresses []v1beta1.Ingress) (apps []hajimari.App) { +func convertIngressesToHajimariApps(ingresses []v1beta1.Ingress) (appGroups []models.AppGroup) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) wrapper := wrappers.NewIngressWrapper(&ingress) - apps = append(apps, hajimari.App{ - Name: wrapper.GetName(), - Group: wrapper.GetGroup(), - Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), - URL: wrapper.GetURL(), - }) + + groupMap := make(map[string]int, len(appGroups)) + for i, v := range appGroups { + groupMap[v.Name] = i + } + + if _, ok := groupMap[wrapper.GetGroup()]; !ok { + appGroups = append(appGroups, models.AppGroup{ + Name: wrapper.GetGroup(), + }) + } + + appMap := make(map[string]int, len(appGroups)) + for i, v := range appGroups { + appMap[v.Name] = i + } + + if i, ok := appMap[wrapper.GetGroup()]; ok { + appGroups[i].Apps = append(appGroups[i].Apps, models.App{ + Name: wrapper.GetName(), + Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), + URL: wrapper.GetURL(), + }) + } + } return } diff --git a/internal/handlers/apps.go b/internal/handlers/apps.go new file mode 100644 index 00000000..6e872a8c --- /dev/null +++ b/internal/handlers/apps.go @@ -0,0 +1,125 @@ +package handlers + +import ( + "net/http" + "strings" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/render" + "github.com/toboshii/hajimari/internal/config" + "github.com/toboshii/hajimari/internal/hajimari/customapps" + "github.com/toboshii/hajimari/internal/hajimari/ingressapps" + "github.com/toboshii/hajimari/internal/kube" + "github.com/toboshii/hajimari/internal/kube/util" + "github.com/toboshii/hajimari/internal/models" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type appResource struct{} + +func NewAppResource() *appResource { + return &appResource{} +} + +func (rs *appResource) AppRoutes() chi.Router { + router := chi.NewRouter() + router.Get("/", rs.ListApps) + + return router +} + +func (rs *appResource) ListApps(w http.ResponseWriter, r *http.Request) { + appConfig, err := config.GetConfig() + if err != nil { + logger.Error("Failed to read configuration for hajimari", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + kubeClient := kube.GetClient() + + var ingressApps []models.AppGroup + + ingressAppsList := ingressapps.NewList(kubeClient, *appConfig) + + namespaces, err := util.PopulateNamespaceList(kubeClient, appConfig.NamespaceSelector) + if err != nil { + logger.Error("An error occurred while populating namespaces", err) + render.Render(w, r, ErrServerError(err)) + return + } + + var namespacesString string + // All Namespaces are selected + if len(namespaces) == 1 && namespaces[0] == metav1.NamespaceAll { + namespacesString = "* (All Namespaces)" + } else { + namespacesString = strings.Join(namespaces, ", ") + } + + logger.Info("Looking for hajimari apps in the following namespaces: " + namespacesString) + + ingressApps, err = ingressAppsList.Populate(namespaces...).Get() + if err != nil { + logger.Error("An error occurred while looking for hajimari apps", err) + render.Render(w, r, ErrServerError(err)) + return + } + + customAppsList := customapps.NewList(*appConfig) + + customApps, err := customAppsList.Populate().Get() + if err != nil { + logger.Error("An error occured while populating custom hajimari apps", err) + render.Render(w, r, ErrServerError(err)) + } + + // logger.Info(apps) + // logger.Info(customApps) + // // Append both generated and custom apps + //mergo.Merge(&apps, customApps) + // logger.Info(apps) + + // apps = append(apps, customApps...) + + var apps []models.AppGroup + + for i, appGroup := range ingressApps { + for x, customAppGroup := range customApps { + if customAppGroup.Name == appGroup.Name { + ingressApps[i].Apps = append(ingressApps[i].Apps, customAppGroup.Apps...) + customApps = append(customApps[:x], customApps[x+1:]...) + } + } + } + + apps = append(ingressApps, customApps...) + + if err := render.RenderList(w, r, NewAppListResponse(apps)); err != nil { + render.Render(w, r, ErrServerError(err)) + return + } + +} + +type AppResponse struct { + models.AppGroup +} + +func NewAppResponse(appGroup models.AppGroup) *AppResponse { + resp := &AppResponse{AppGroup: appGroup} + + return resp +} + +func (rd *AppResponse) Render(w http.ResponseWriter, r *http.Request) error { + return nil +} + +func NewAppListResponse(appGroups []models.AppGroup) []render.Renderer { + list := []render.Renderer{} + for _, app := range appGroups { + list = append(list, NewAppResponse(app)) + } + return list +} diff --git a/internal/handlers/bookmarks.go b/internal/handlers/bookmarks.go new file mode 100644 index 00000000..352ddb4a --- /dev/null +++ b/internal/handlers/bookmarks.go @@ -0,0 +1,80 @@ +package handlers + +import ( + "net/http" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/render" + "github.com/toboshii/hajimari/internal/config" + "github.com/toboshii/hajimari/internal/models" +) + +type bookmarkResource struct{} + +func NewBookmarkResource() *bookmarkResource { + return &bookmarkResource{} +} + +func (rs *bookmarkResource) BookmarkRoutes() chi.Router { + router := chi.NewRouter() + router.Get("/", rs.ListBookmarks) + + return router +} + +func (rs *bookmarkResource) ListBookmarks(w http.ResponseWriter, r *http.Request) { + appConfig, err := config.GetConfig() + if err != nil { + logger.Error("Failed to read configuration for hajimari", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + defaultBookmarkGroups := appConfig.Groups + + bookmarkGroups := []models.BookmarkGroup{} + + for _, bookmarkGroup := range defaultBookmarkGroups { + bookmarks := []models.Bookmark{} + + for _, bookmark := range bookmarkGroup.Links { + bookmarks = append(bookmarks, models.Bookmark{ + Name: bookmark.Name, + URL: bookmark.URL, + }) + } + + bookmarkGroups = append(bookmarkGroups, models.BookmarkGroup{ + Name: bookmarkGroup.Name, + Bookmarks: bookmarks, + }) + } + + if err := render.RenderList(w, r, NewBookmarkListResponse(bookmarkGroups)); err != nil { + render.Render(w, r, ErrServerError(err)) + return + } + +} + +type BookmarkResponse struct { + models.BookmarkGroup +} + +func NewBookmarkResponse(bookmarkGroup models.BookmarkGroup) *BookmarkResponse { + resp := &BookmarkResponse{BookmarkGroup: bookmarkGroup} + + return resp +} + +func (rd *BookmarkResponse) Render(w http.ResponseWriter, r *http.Request) error { + return nil +} + +func NewBookmarkListResponse(bookmarkGroups []models.BookmarkGroup) []render.Renderer { + list := []render.Renderer{} + for _, bookmark := range bookmarkGroups { + list = append(list, NewBookmarkResponse(bookmark)) + } + return list +} diff --git a/internal/handlers/errors.go b/internal/handlers/errors.go new file mode 100644 index 00000000..8dfe3beb --- /dev/null +++ b/internal/handlers/errors.go @@ -0,0 +1,45 @@ +package handlers + +import ( + "net/http" + + "github.com/go-chi/render" +) + +type ErrorResponse struct { + Err error `json:"-"` // low-level runtime error + HTTPStatusCode int `json:"-"` // http response status code + + StatusText string `json:"status"` // user-level status message + AppCode int64 `json:"code,omitempty"` // application-specific error code + ErrorText string `json:"error,omitempty"` // application-level error message, for debugging +} + +var ( + ErrMethodNotAllowed = &ErrorResponse{HTTPStatusCode: 405, StatusText: "Method not allowed"} + ErrNotFound = &ErrorResponse{HTTPStatusCode: 404, StatusText: "Resource not found"} + ErrBadRequest = &ErrorResponse{HTTPStatusCode: 400, StatusText: "Bad request"} +) + +func (e *ErrorResponse) Render(w http.ResponseWriter, r *http.Request) error { + render.Status(r, e.HTTPStatusCode) + return nil +} + +func ErrInvalidRequest(err error) *ErrorResponse { + return &ErrorResponse{ + Err: err, + HTTPStatusCode: 400, + StatusText: "Bad request", + ErrorText: err.Error(), + } +} + +func ErrServerError(err error) *ErrorResponse { + return &ErrorResponse{ + Err: err, + HTTPStatusCode: 500, + StatusText: "Internal server error", + ErrorText: err.Error(), + } +} diff --git a/internal/handlers/handler.go b/internal/handlers/handler.go index 5630c660..82890683 100644 --- a/internal/handlers/handler.go +++ b/internal/handlers/handler.go @@ -1,9 +1,60 @@ package handlers import ( + "net/http" + "time" + + loggerMiddleware "github.com/chi-middleware/logrus-logger" + "github.com/go-chi/chi/middleware" + "github.com/go-chi/chi/v5" + "github.com/go-chi/cors" + "github.com/go-chi/render" "github.com/toboshii/hajimari/internal/log" ) var ( logger = log.New() ) + +func NewHandler() http.Handler { + router := chi.NewRouter() + + router.Use(middleware.RequestID) + router.Use(middleware.RealIP) + router.Use(loggerMiddleware.Logger("router", logger)) + router.Use(middleware.Recoverer) + router.Use(middleware.Timeout(60 * time.Second)) + router.Use(cors.Handler(cors.Options{ + // AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts + AllowedOrigins: []string{"https://*", "http://*"}, + // AllowOriginFunc: func(r *http.Request, origin string) bool { return true }, + AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, + AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, + ExposedHeaders: []string{"Link"}, + AllowCredentials: false, + MaxAge: 300, // Maximum value not ignored by any of major browsers + })) + + router.MethodNotAllowed(methodNotAllowedHandler) + router.NotFound(notFoundHandler) + + // startpageService := services.NewStartpageService(stores.NewFileStore(), logger) + + // router.Mount("/", NewStartpageResource(startpageService).StartpageRoutes()) + router.Mount("/apps", NewAppResource().AppRoutes()) + router.Mount("/bookmarks", NewBookmarkResource().BookmarkRoutes()) + + return router +} + +func methodNotAllowedHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-type", "application/json") + w.WriteHeader(405) + render.Render(w, r, ErrMethodNotAllowed) +} + +func notFoundHandler(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-type", "application/json") + w.WriteHeader(404) + render.Render(w, r, ErrNotFound) +} diff --git a/internal/handlers/startpage.go b/internal/handlers/startpage.go index abcf0642..23d04515 100644 --- a/internal/handlers/startpage.go +++ b/internal/handlers/startpage.go @@ -1,276 +1,229 @@ package handlers -import ( - "context" - "errors" - "net/http" - "text/template" - "time" - - "github.com/go-chi/chi/v5" - "github.com/go-chi/render" - "github.com/toboshii/hajimari/internal/config" - "github.com/toboshii/hajimari/internal/hajimari" - "github.com/toboshii/hajimari/internal/hajimari/customapps" - "github.com/toboshii/hajimari/internal/hajimari/ingressapps" - "github.com/toboshii/hajimari/internal/kube" - "github.com/toboshii/hajimari/internal/kube/util" - "github.com/toboshii/hajimari/internal/models" - "github.com/toboshii/hajimari/internal/services" - "github.com/toboshii/hajimari/internal/util/tplutil" -) - -type startpageResource struct { - service services.StartpageService - tpl *template.Template -} - -func NewStartpageResource(service services.StartpageService, tpl *template.Template) *startpageResource { - return &startpageResource{service: service, tpl: tpl} -} - -func (rs *startpageResource) StartpageRoutes() chi.Router { - router := chi.NewRouter() - router.Get("/", rs.GetStartpage) - router.Get("/config", rs.GetDefaultConfig) - router.Post("/", rs.CreateStartpage) - - router.Route("/{startpageID}", func(r chi.Router) { - r.Use(rs.StartpageCtx) - r.Get("/", rs.GetStartpage) - r.Get("/config", rs.GetStartpageConfig) - r.Put("/", rs.UpdateStartpage) - r.Delete("/", rs.DeleteStartpage) - }) - - return router -} - -// StartpageCtx middleware is used to load a Startpage object from -// the URL parameters passed through as the request. In case -// the Startpage could not be found, we stop here and return a 404. -func (sr *startpageResource) StartpageCtx(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var startpage *models.Startpage - var err error - - if startpageID := chi.URLParam(r, "startpageID"); startpageID != "" { - startpage, err = sr.service.GetStartpage(startpageID) - } else { - http.Error(w, err.Error(), http.StatusNotFound) - return - } - if err != nil { - http.Error(w, err.Error(), http.StatusNotFound) - return - } - - ctx := context.WithValue(r.Context(), "startpage", startpage) - next.ServeHTTP(w, r.WithContext(ctx)) - }) -} - -func (sr *startpageResource) GetStartpage(w http.ResponseWriter, r *http.Request) { - appConfig, err := config.GetConfig() - if err != nil { - logger.Error("Failed to read configuration for hajimari", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - if r.Context().Value("startpage") != nil { - startpage := r.Context().Value("startpage").(*models.Startpage) - - sr.service.ConvertStartpageToConfig(appConfig, startpage) - } - - kubeClient := kube.GetClient() - - var hajimariApps []hajimari.App - - ingressAppsList := ingressapps.NewList(kubeClient, *appConfig) - - namespaces, err := util.PopulateNamespaceList(kubeClient, appConfig.NamespaceSelector) - - if err != nil { - logger.Error("An error occurred while populating namespaces", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - logger.Debug("Namespaces to look for hajimari apps: ", namespaces) - hajimariApps, err = ingressAppsList.Populate(namespaces...).Get() - - if err != nil { - logger.Error("An error occurred while looking for hajimari apps", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - customAppsList := customapps.NewList(*appConfig) - - customHajimariApps, err := customAppsList.Populate().Get() - if err != nil { - logger.Error("An error occured while populating custom hajimari apps", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - } - - // Append both generated and custom apps - hajimariApps = append(hajimariApps, customHajimariApps...) - - w.Header().Add("Content-Type", "text/html") - - err = sr.tpl.Execute(w, struct { - Title string - Greeting string - Date string - Apps []hajimari.App - Groups []config.Group - Providers []config.Provider - Modules []config.Module - }{ - Title: appConfig.Title, - Greeting: tplutil.Greet(appConfig.Name, time.Now().Hour()), - Date: time.Now().Format("Mon, Jan 02"), - Apps: hajimariApps, - Groups: appConfig.Groups, - Providers: appConfig.Providers, - Modules: appConfig.Modules, - }) - - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } -} - -func (sr *startpageResource) GetDefaultConfig(w http.ResponseWriter, r *http.Request) { - startpage := models.Startpage{} - - appConfig, err := config.GetConfig() - if err != nil { - logger.Error("Failed to read configuration for hajimari", err) - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - sr.service.ConvertConfigToStartpage(appConfig, &startpage) - - if err := render.Render(w, r, NewStartpageResponse(&startpage)); err != nil { - render.Render(w, r, ErrRender(err)) - return - } -} - -func (sr *startpageResource) GetStartpageConfig(w http.ResponseWriter, r *http.Request) { - startpage := r.Context().Value("startpage").(*models.Startpage) - - if err := render.Render(w, r, NewStartpageResponse(startpage)); err != nil { - render.Render(w, r, ErrRender(err)) - return - } -} - -func (sr *startpageResource) CreateStartpage(w http.ResponseWriter, r *http.Request) { - data := &StartpageRequest{} - if err := render.Bind(r, data); err != nil { - render.Render(w, r, ErrInvalidRequest(err)) - return - } - - startpage := data.Startpage - _, _ = sr.service.NewStartpage(startpage) - - render.Status(r, http.StatusCreated) - render.Render(w, r, NewStartpageResponse(startpage)) -} - -func (sr *startpageResource) UpdateStartpage(w http.ResponseWriter, r *http.Request) { - startpage := r.Context().Value("startpage").(*models.Startpage) - - data := &StartpageRequest{Startpage: startpage} - if err := render.Bind(r, data); err != nil { - render.Render(w, r, ErrInvalidRequest(err)) - return - } - startpage = data.Startpage - _, _ = sr.service.UpdateStartpage(startpage.ID, startpage) - - render.Render(w, r, NewStartpageResponse(startpage)) -} - -func (sr *startpageResource) DeleteStartpage(w http.ResponseWriter, r *http.Request) { - var err error - - startpage := r.Context().Value("startpage").(*models.Startpage) - - startpage, err = sr.service.RemoveStartpage(startpage.ID) - if err != nil { - render.Render(w, r, ErrInvalidRequest(err)) - return - } - - render.Render(w, r, NewStartpageResponse(startpage)) -} - -type StartpageRequest struct { - *models.Startpage - - ProtectedID string `json:"id"` -} - -func (s *StartpageRequest) Bind(r *http.Request) error { - if s.Startpage == nil { - return errors.New("missing required Startpage fields") - } - - return nil -} - -type StartpageResponse struct { - *models.Startpage -} - -func NewStartpageResponse(startpage *models.Startpage) *StartpageResponse { - resp := &StartpageResponse{Startpage: startpage} - - return resp -} - -func (rd *StartpageResponse) Render(w http.ResponseWriter, r *http.Request) error { - return nil -} - -type ErrResponse struct { - Err error `json:"-"` // low-level runtime error - HTTPStatusCode int `json:"-"` // http response status code - - StatusText string `json:"status"` // user-level status message - AppCode int64 `json:"code,omitempty"` // application-specific error code - ErrorText string `json:"error,omitempty"` // application-level error message, for debugging -} - -func (e *ErrResponse) Render(w http.ResponseWriter, r *http.Request) error { - render.Status(r, e.HTTPStatusCode) - return nil -} - -func ErrInvalidRequest(err error) render.Renderer { - return &ErrResponse{ - Err: err, - HTTPStatusCode: 400, - StatusText: "Invalid request.", - ErrorText: err.Error(), - } -} - -func ErrRender(err error) render.Renderer { - return &ErrResponse{ - Err: err, - HTTPStatusCode: 422, - StatusText: "Error rendering response.", - ErrorText: err.Error(), - } -} - -var ErrNotFound = &ErrResponse{HTTPStatusCode: 404, StatusText: "Resource not found."} +// import ( +// "context" +// "encoding/json" +// "errors" +// "net/http" +// "time" + +// "github.com/go-chi/chi/v5" +// "github.com/go-chi/render" +// "github.com/toboshii/hajimari/internal/config" +// "github.com/toboshii/hajimari/internal/models" +// "github.com/toboshii/hajimari/internal/services" +// "github.com/toboshii/hajimari/internal/util/tplutil" +// ) + +// type startpageResource struct { +// service services.StartpageService +// } + +// func NewStartpageResource(service services.StartpageService) *startpageResource { +// return &startpageResource{service: service} +// } + +// func (rs *startpageResource) StartpageRoutes() chi.Router { +// router := chi.NewRouter() +// router.Get("/", rs.GetStartpage) +// router.Get("/config", rs.GetDefaultConfig) +// router.Post("/", rs.CreateStartpage) + +// router.Route("/{startpageID}", func(r chi.Router) { +// r.Use(rs.StartpageCtx) +// r.Get("/", rs.GetStartpage) +// r.Get("/config", rs.GetStartpageConfig) +// r.Put("/", rs.UpdateStartpage) +// r.Delete("/", rs.DeleteStartpage) +// }) + +// return router +// } + +// // StartpageCtx middleware is used to load a Startpage object from +// // the URL parameters passed through as the request. In case +// // the Startpage could not be found, we stop here and return a 404. +// func (sr *startpageResource) StartpageCtx(next http.Handler) http.Handler { +// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// var startpage *models.Startpage +// var err error + +// if startpageID := chi.URLParam(r, "startpageID"); startpageID != "" { +// startpage, err = sr.service.GetStartpage(startpageID) +// } else { +// http.Error(w, err.Error(), http.StatusNotFound) +// return +// } +// if err != nil { +// render.Render(w, r, ErrNotFound) +// return +// } + +// ctx := context.WithValue(r.Context(), "startpage", startpage) +// next.ServeHTTP(w, r.WithContext(ctx)) +// }) +// } + +// func (sr *startpageResource) GetStartpage(w http.ResponseWriter, r *http.Request) { +// appConfig, err := config.GetConfig() +// if err != nil { +// logger.Error("Failed to read configuration for hajimari", err) +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } + +// if r.Context().Value("startpage") != nil { +// startpage := r.Context().Value("startpage").(*models.Startpage) + +// sr.service.ConvertStartpageToConfig(appConfig, startpage) +// } + +// w.Header().Add("Content-Type", "application/json") + +// js, err := json.Marshal(struct { +// Title string `json:"title"` +// Greeting string `json:"greeting"` +// Date string `json:"date"` +// Groups []config.Group `json:"groups"` +// Providers []config.Provider `json:"providers"` +// Modules []config.Module `json:"modules"` +// }{ +// Title: appConfig.Title, +// Greeting: tplutil.Greet(appConfig.Name, time.Now().Hour()), +// Date: time.Now().Format("Mon, Jan 02"), +// Groups: appConfig.Groups, +// Providers: appConfig.Providers, +// Modules: appConfig.Modules, +// }) +// if err != nil { +// logger.Error("An error occurred while marshalling apps to json: ", err) +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } + +// _, err = w.Write(js) +// if err != nil { +// logger.Error("An error occurred while rendering json to output: ", err) +// http.Error(w, err.Error(), http.StatusInternalServerError) +// } + +// // err = sr.tpl.Execute(w, struct { +// // Title string +// // Greeting string +// // Date string +// // Apps []hajimari.App +// // Groups []config.Group +// // Providers []config.Provider +// // Modules []config.Module +// // }{ +// // Title: appConfig.Title, +// // Greeting: tplutil.Greet(appConfig.Name, time.Now().Hour()), +// // Date: time.Now().Format("Mon, Jan 02"), +// // Apps: hajimariApps, +// // Groups: appConfig.Groups, +// // Providers: appConfig.Providers, +// // Modules: appConfig.Modules, +// // }) + +// // if err != nil { +// // http.Error(w, err.Error(), http.StatusInternalServerError) +// // return +// // } +// } + +// func (sr *startpageResource) GetDefaultConfig(w http.ResponseWriter, r *http.Request) { +// startpage := models.Startpage{} + +// appConfig, err := config.GetConfig() +// if err != nil { +// logger.Error("Failed to read configuration for hajimari", err) +// http.Error(w, err.Error(), http.StatusInternalServerError) +// return +// } + +// sr.service.ConvertConfigToStartpage(appConfig, &startpage) + +// if err := render.Render(w, r, NewStartpageResponse(&startpage)); err != nil { +// render.Render(w, r, ErrServerError(err)) +// return +// } +// } + +// func (sr *startpageResource) GetStartpageConfig(w http.ResponseWriter, r *http.Request) { +// startpage := r.Context().Value("startpage").(*models.Startpage) + +// if err := render.Render(w, r, NewStartpageResponse(startpage)); err != nil { +// render.Render(w, r, ErrServerError(err)) +// return +// } +// } + +// func (sr *startpageResource) CreateStartpage(w http.ResponseWriter, r *http.Request) { +// data := &StartpageRequest{} +// if err := render.Bind(r, data); err != nil { +// render.Render(w, r, ErrInvalidRequest(err)) +// return +// } + +// startpage := data.Startpage +// _, _ = sr.service.NewStartpage(startpage) + +// render.Status(r, http.StatusCreated) +// render.Render(w, r, NewStartpageResponse(startpage)) +// } + +// func (sr *startpageResource) UpdateStartpage(w http.ResponseWriter, r *http.Request) { +// startpage := r.Context().Value("startpage").(*models.Startpage) + +// data := &StartpageRequest{Startpage: startpage} +// if err := render.Bind(r, data); err != nil { +// render.Render(w, r, ErrInvalidRequest(err)) +// return +// } +// startpage = data.Startpage +// _, _ = sr.service.UpdateStartpage(startpage.ID, startpage) + +// render.Render(w, r, NewStartpageResponse(startpage)) +// } + +// func (sr *startpageResource) DeleteStartpage(w http.ResponseWriter, r *http.Request) { +// var err error + +// startpage := r.Context().Value("startpage").(*models.Startpage) + +// startpage, err = sr.service.RemoveStartpage(startpage.ID) +// if err != nil { +// render.Render(w, r, ErrInvalidRequest(err)) +// return +// } + +// render.Render(w, r, NewStartpageResponse(startpage)) +// } + +// type StartpageRequest struct { +// *models.Startpage + +// ProtectedID string `json:"id"` +// } + +// func (s *StartpageRequest) Bind(r *http.Request) error { +// if s.Startpage == nil { +// return errors.New("missing required Startpage fields") +// } + +// return nil +// } + +// type StartpageResponse struct { +// *models.Startpage +// } + +// func NewStartpageResponse(startpage *models.Startpage) *StartpageResponse { +// resp := &StartpageResponse{Startpage: startpage} + +// return resp +// } + +// func (rd *StartpageResponse) Render(w http.ResponseWriter, r *http.Request) error { +// return nil +// } diff --git a/internal/models/app.go b/internal/models/app.go new file mode 100644 index 00000000..9c545518 --- /dev/null +++ b/internal/models/app.go @@ -0,0 +1,7 @@ +package models + +type App struct { + Name string `json:"name"` + Icon string `json:"icon"` + URL string `json:"url"` +} diff --git a/internal/models/app_group.go b/internal/models/app_group.go new file mode 100644 index 00000000..5db0a269 --- /dev/null +++ b/internal/models/app_group.go @@ -0,0 +1,6 @@ +package models + +type AppGroup struct { + Name string `json:"name"` + Apps []App `json:"apps"` +} diff --git a/internal/models/bookmark.go b/internal/models/bookmark.go new file mode 100644 index 00000000..89167937 --- /dev/null +++ b/internal/models/bookmark.go @@ -0,0 +1,7 @@ +package models + +type Bookmark struct { + Name string `json:"name"` + Icon string `json:"icon"` + URL string `json:"url"` +} diff --git a/internal/models/bookmark_group.go b/internal/models/bookmark_group.go new file mode 100644 index 00000000..f3dccc8a --- /dev/null +++ b/internal/models/bookmark_group.go @@ -0,0 +1,6 @@ +package models + +type BookmarkGroup struct { + Name string `json:"name"` + Bookmarks []Bookmark `json:"bookmarks"` +} diff --git a/internal/models/models.go b/internal/models/models.go deleted file mode 100644 index 4c21360c..00000000 --- a/internal/models/models.go +++ /dev/null @@ -1,17 +0,0 @@ -package models - -type Startpage struct { - ID string `json:"id,omitempty"` - Name string `json:"name"` - Groups []Group `json:"groups"` -} - -type Group struct { - Name string `json:"name"` - Links []Link `json:"links"` -} - -type Link struct { - Name string `json:"name"` - URL string `json:"url"` -} diff --git a/internal/models/startpage.go b/internal/models/startpage.go new file mode 100644 index 00000000..e2fff408 --- /dev/null +++ b/internal/models/startpage.go @@ -0,0 +1,6 @@ +package models + +type Startpage struct { + ID string `json:"id,omitempty"` + Name string `json:"name"` +} diff --git a/internal/services/startpage.go b/internal/services/startpage.go index a4675f65..1366fd90 100644 --- a/internal/services/startpage.go +++ b/internal/services/startpage.go @@ -1,82 +1,82 @@ package services -import ( - "github.com/sirupsen/logrus" - "github.com/toboshii/hajimari/internal/config" - "github.com/toboshii/hajimari/internal/models" - "github.com/toboshii/hajimari/internal/stores" -) - -type StartpageService interface { - NewStartpage(startpage *models.Startpage) (string, error) - GetStartpage(id string) (*models.Startpage, error) - UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) - RemoveStartpage(id string) (*models.Startpage, error) - ConvertStartpageToConfig(appConfig *config.Config, startpage *models.Startpage) - ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) -} - -type startpageService struct { - store stores.StartpageStore - logger *logrus.Logger -} - -func NewStartpageService(store stores.StartpageStore, logger *logrus.Logger) *startpageService { - return &startpageService{store: store, logger: logger} -} - -func (s *startpageService) NewStartpage(startpage *models.Startpage) (string, error) { - return s.store.NewStartpage(startpage) -} - -func (s *startpageService) GetStartpage(id string) (*models.Startpage, error) { - log := s.logger.WithFields(logrus.Fields{ - "startpageId": id, - }) - log.Info("GetStartpage") - return s.store.GetStartpage(id) -} - -func (s *startpageService) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { - return s.store.UpdateStartpage(id, startpage) -} - -func (s *startpageService) RemoveStartpage(id string) (*models.Startpage, error) { - return s.store.RemoveStartpage(id) -} - -func (s *startpageService) ConvertStartpageToConfig(appConfig *config.Config, startpage *models.Startpage) { - appConfig.Name = startpage.Name - appConfig.Groups = []config.Group{} - - for _, g := range startpage.Groups { - links := []config.Link{} - - for _, l := range g.Links { - links = append(links, config.Link(l)) - } - - appConfig.Groups = append(appConfig.Groups, config.Group{ - Name: g.Name, - Links: links, - }) - } -} - -func (s *startpageService) ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) { - startpage.Name = appConfig.Name - startpage.Groups = []models.Group{} - - for _, g := range appConfig.Groups { - links := []models.Link{} - - for _, l := range g.Links { - links = append(links, models.Link(l)) - } - - startpage.Groups = append(startpage.Groups, models.Group{ - Name: g.Name, - Links: links, - }) - } -} +// import ( +// "github.com/sirupsen/logrus" +// "github.com/toboshii/hajimari/internal/config" +// "github.com/toboshii/hajimari/internal/models" +// "github.com/toboshii/hajimari/internal/stores" +// ) + +// type StartpageService interface { +// NewStartpage(startpage *models.Startpage) (string, error) +// GetStartpage(id string) (*models.Startpage, error) +// UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) +// RemoveStartpage(id string) (*models.Startpage, error) +// ConvertStartpageToConfig(appConfig *config.Config, startpage *models.Startpage) +// ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) +// } + +// type startpageService struct { +// store stores.StartpageStore +// logger *logrus.Logger +// } + +// func NewStartpageService(store stores.StartpageStore, logger *logrus.Logger) *startpageService { +// return &startpageService{store: store, logger: logger} +// } + +// func (s *startpageService) NewStartpage(startpage *models.Startpage) (string, error) { +// return s.store.NewStartpage(startpage) +// } + +// func (s *startpageService) GetStartpage(id string) (*models.Startpage, error) { +// log := s.logger.WithFields(logrus.Fields{ +// "startpageId": id, +// }) +// log.Info("GetStartpage") +// return s.store.GetStartpage(id) +// } + +// func (s *startpageService) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { +// return s.store.UpdateStartpage(id, startpage) +// } + +// func (s *startpageService) RemoveStartpage(id string) (*models.Startpage, error) { +// return s.store.RemoveStartpage(id) +// } + +// func (s *startpageService) ConvertStartpageToConfig(appConfig *config.Config, startpage *models.Startpage) { +// appConfig.Name = startpage.Name +// appConfig.Groups = []config.Group{} + +// for _, g := range startpage.Groups { +// links := []config.Link{} + +// for _, l := range g.Links { +// links = append(links, config.Link(l)) +// } + +// appConfig.Groups = append(appConfig.Groups, config.Group{ +// Name: g.Name, +// Links: links, +// }) +// } +// } + +// func (s *startpageService) ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) { +// startpage.Name = appConfig.Name +// startpage.Groups = []models.Group{} + +// for _, g := range appConfig.Groups { +// links := []models.Link{} + +// for _, l := range g.Links { +// links = append(links, models.Link(l)) +// } + +// startpage.Groups = append(startpage.Groups, models.Group{ +// Name: g.Name, +// Links: links, +// }) +// } +// } diff --git a/internal/stores/memory.go b/internal/stores/memory.go index a6477f7c..598ae3d0 100644 --- a/internal/stores/memory.go +++ b/internal/stores/memory.go @@ -1,90 +1,90 @@ package stores -import ( - "errors" +// import ( +// "errors" - gonanoid "github.com/matoous/go-nanoid/v2" - "github.com/toboshii/hajimari/internal/models" -) +// gonanoid "github.com/matoous/go-nanoid/v2" +// "github.com/toboshii/hajimari/internal/models" +// ) -var startpages = []*models.Startpage{ - { - ID: "108ZTGB77K09P4QJfu4vG", - Name: "Adam", - Groups: []models.Group{ - { - Name: "Media", - Links: []models.Link{ - { - Name: "Youtube", - URL: "https://youtube.com", - }, - { - Name: "Netflix", - URL: "https://netflix.com", - }, - }, - }, - { - Name: "Code", - Links: []models.Link{ - { - Name: "Github", - URL: "https://github.com", - }, - }, - }, - }, - }, - {ID: "r1NqSpS1C0z3cMHyzX-Y5", Name: "Bob"}, - {ID: "NmcvYTdRozUDNpbjAxFTO", Name: "Carol"}, - {ID: "3OG1X_GuRS_TrCcWb5YjK", Name: "Derrick"}, - {ID: "Qq4EF6MaSKaYZpEldtLTn", Name: "Emily"}, -} +// var startpages = []*models.Startpage{ +// { +// ID: "108ZTGB77K09P4QJfu4vG", +// Name: "Adam", +// Groups: []models.Group{ +// { +// Name: "Media", +// Links: []models.Link{ +// { +// Name: "Youtube", +// URL: "https://youtube.com", +// }, +// { +// Name: "Netflix", +// URL: "https://netflix.com", +// }, +// }, +// }, +// { +// Name: "Code", +// Links: []models.Link{ +// { +// Name: "Github", +// URL: "https://github.com", +// }, +// }, +// }, +// }, +// }, +// {ID: "r1NqSpS1C0z3cMHyzX-Y5", Name: "Bob"}, +// {ID: "NmcvYTdRozUDNpbjAxFTO", Name: "Carol"}, +// {ID: "3OG1X_GuRS_TrCcWb5YjK", Name: "Derrick"}, +// {ID: "Qq4EF6MaSKaYZpEldtLTn", Name: "Emily"}, +// } -type memoryStore struct { - StartpageStore -} +// type memoryStore struct { +// StartpageStore +// } -func NewMemoryStore() StartpageStore { - return &memoryStore{} -} +// func NewMemoryStore() StartpageStore { +// return &memoryStore{} +// } -func (s *memoryStore) NewStartpage(startpage *models.Startpage) (string, error) { - id, err := gonanoid.New() - if err != nil { - return "", err - } - startpage.ID = id - startpages = append(startpages, startpage) - return startpage.ID, nil -} +// func (s *memoryStore) NewStartpage(startpage *models.Startpage) (string, error) { +// id, err := gonanoid.New() +// if err != nil { +// return "", err +// } +// startpage.ID = id +// startpages = append(startpages, startpage) +// return startpage.ID, nil +// } -func (s *memoryStore) GetStartpage(id string) (*models.Startpage, error) { - for _, s := range startpages { - if s.ID == id { - return s, nil - } - } - return nil, errors.New("startpage not found") -} +// func (s *memoryStore) GetStartpage(id string) (*models.Startpage, error) { +// for _, s := range startpages { +// if s.ID == id { +// return s, nil +// } +// } +// return nil, errors.New("startpage not found") +// } -func (s *memoryStore) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { - for i, s := range startpages { - if s.ID == id { - startpages[i] = startpage - return startpage, nil - } - } - return nil, errors.New("startpage not found") -} +// func (s *memoryStore) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { +// for i, s := range startpages { +// if s.ID == id { +// startpages[i] = startpage +// return startpage, nil +// } +// } +// return nil, errors.New("startpage not found") +// } -func (s *memoryStore) RemoveStartpage(id string) (*models.Startpage, error) { - for i, s := range startpages { - if s.ID == id { - startpages = append((startpages)[:i], (startpages)[i+1:]...) - return s, nil - } - } - return nil, errors.New("startpage not found") -} +// func (s *memoryStore) RemoveStartpage(id string) (*models.Startpage, error) { +// for i, s := range startpages { +// if s.ID == id { +// startpages = append((startpages)[:i], (startpages)[i+1:]...) +// return s, nil +// } +// } +// return nil, errors.New("startpage not found") +// } diff --git a/main.go b/main.go index 7c6ad78e..861f85b4 100644 --- a/main.go +++ b/main.go @@ -1,21 +1,12 @@ package main import ( - "embed" "errors" - "io/fs" "net/http" - "text/template" - "time" - loggerMiddleware "github.com/chi-middleware/logrus-logger" - "github.com/go-chi/chi/middleware" - "github.com/go-chi/chi/v5" "github.com/spf13/viper" "github.com/toboshii/hajimari/internal/handlers" "github.com/toboshii/hajimari/internal/log" - "github.com/toboshii/hajimari/internal/services" - "github.com/toboshii/hajimari/internal/stores" ) var ( @@ -34,13 +25,13 @@ func init() { } } -//go:embed web/template -var indexHTML embed.FS +// //go:embed web/template +// var indexHTML embed.FS -//go:embed web/static -var staticFiles embed.FS +// //go:embed web/static +// var staticFiles embed.FS -var tpl = template.Must(template.ParseFS(indexHTML, "web/template/index.html.tmpl")) +// var tpl = template.Must(template.ParseFS(indexHTML, "web/template/index.html.tmpl")) func main() { @@ -50,22 +41,8 @@ func main() { // return // } - r := chi.NewRouter() - - r.Use(middleware.RequestID) - r.Use(middleware.RealIP) - r.Use(loggerMiddleware.Logger("router", logger)) - r.Use(middleware.Recoverer) - - r.Use(middleware.Timeout(60 * time.Second)) - - staticFiles, _ := fs.Sub(staticFiles, "web") - r.Handle("/static/*", http.FileServer(http.FS(staticFiles))) - - service := services.NewStartpageService(stores.NewFileStore(), logger) - - r.Mount("/", handlers.NewStartpageResource(service, tpl).StartpageRoutes()) + httpHandler := handlers.NewHandler() logger.Printf("Listening on :%d\n", 3000) - logger.Fatal(http.ListenAndServe(":3000", r)) + logger.Fatal(http.ListenAndServe(":3000", httpHandler)) } diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 00000000..da93220b --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/public/build/ + +.DS_Store diff --git a/web/README.md b/web/README.md new file mode 100644 index 00000000..debe24cb --- /dev/null +++ b/web/README.md @@ -0,0 +1,107 @@ +*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)* + +--- + +# svelte app + +This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template. + +To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit): + +```bash +npx degit sveltejs/template svelte-app +cd svelte-app +``` + +*Note that you will need to have [Node.js](https://nodejs.org) installed.* + + +## Get started + +Install the dependencies... + +```bash +cd svelte-app +npm install +``` + +...then start [Rollup](https://rollupjs.org): + +```bash +npm run dev +``` + +Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes. + +By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`. + +If you're using [Visual Studio Code](https://code.visualstudio.com/) we recommend installing the official extension [Svelte for VS Code](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). If you are using other editors you may need to install a plugin in order to get syntax highlighting and intellisense. + +## Building and running in production mode + +To create an optimised version of the app: + +```bash +npm run build +``` + +You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com). + + +## Single-page app mode + +By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere. + +If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json: + +```js +"start": "sirv public --single" +``` + +## Using TypeScript + +This template comes with a script to set up a TypeScript development environment, you can run it immediately after cloning the template with: + +```bash +node scripts/setupTypeScript.js +``` + +Or remove the script via: + +```bash +rm scripts/setupTypeScript.js +``` + +If you want to use `baseUrl` or `path` aliases within your `tsconfig`, you need to set up `@rollup/plugin-alias` to tell Rollup to resolve the aliases. For more info, see [this StackOverflow question](https://stackoverflow.com/questions/63427935/setup-tsconfig-path-in-svelte). + +## Deploying to the web + +### With [Vercel](https://vercel.com) + +Install `vercel` if you haven't already: + +```bash +npm install -g vercel +``` + +Then, from within your project folder: + +```bash +cd public +vercel deploy --name my-project +``` + +### With [surge](https://surge.sh/) + +Install `surge` if you haven't already: + +```bash +npm install -g surge +``` + +Then, from within your project folder: + +```bash +npm run build +surge public my-project.surge.sh +``` diff --git a/web/package-lock.json b/web/package-lock.json new file mode 100644 index 00000000..620e9478 --- /dev/null +++ b/web/package-lock.json @@ -0,0 +1,1819 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "svelte-app", + "version": "1.0.0", + "dependencies": { + "sirv-cli": "^1.0.0" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.17", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.17.tgz", + "integrity": "sha512-0p1rCgM3LLbAdwBnc7gqgnvjHg9KpbhcSphergHShlkWz8EdPawoMJ3/VbezI0mGC5eKCDzMaPgF9Yca6cKvrg==" + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz", + "integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "commondir": "^1.0.1", + "estree-walker": "^2.0.1", + "glob": "^7.1.6", + "is-reference": "^1.2.1", + "magic-string": "^0.25.7", + "resolve": "^1.17.0" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^2.30.0" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.0.tgz", + "integrity": "sha512-e66BrnjWQ3BRBZ2+iA5e85fcH9GLNe4S0n1H0T3OalK2sXg5XWEFTO4xvmGrYQ3edy+q6fdOh5t0/HOY8OAqBg==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/console-clear": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", + "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", + "engines": { + "node": ">=4" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "node_modules/livereload": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", + "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.0", + "livereload-js": "^3.3.1", + "opts": ">= 1.2.0", + "ws": "^7.4.3" + }, + "bin": { + "livereload": "bin/livereload.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/livereload-js": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.2.tgz", + "integrity": "sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==", + "dev": true + }, + "node_modules/local-access": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz", + "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/opts": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", + "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", + "dev": true + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.56.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.56.2.tgz", + "integrity": "sha512-s8H00ZsRi29M2/lGdm1u8DJpJ9ML8SUOpVVBd33XNeEeL3NVaTiUcSBHzBdF3eAyR0l7VSpsuoVUGrRHq7aPwQ==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-css-only": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", + "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "4" + }, + "engines": { + "node": ">=10.12.0" + }, + "peerDependencies": { + "rollup": "1 || 2" + } + }, + "node_modules/rollup-plugin-css-only/node_modules/@rollup/pluginutils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", + "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/rollup-plugin-livereload": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz", + "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==", + "dev": true, + "dependencies": { + "livereload": "^0.9.1" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-svelte": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", + "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", + "dev": true, + "dependencies": { + "require-relative": "^0.8.7", + "rollup-pluginutils": "^2.8.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "rollup": ">=2.0.0", + "svelte": ">=3.5.0" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/sade": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", + "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semiver": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", + "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/sirv": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.14.tgz", + "integrity": "sha512-czTFDFjK9lXj0u9mJ3OmJoXFztoilYS+NdRPcJoT182w44wSEkHSiO7A2517GLJ8wKM4GjCm2OXE66Dhngbzjg==", + "dependencies": { + "@polka/url": "^1.0.0-next.17", + "mime": "^2.3.1", + "totalist": "^1.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sirv-cli": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.14.tgz", + "integrity": "sha512-yyUTNr984ANKDloqepkYbBSqvx3buwYg2sQKPWjSU+IBia5loaoka2If8N9CMwt8AfP179cdEl7kYJ//iWJHjQ==", + "dependencies": { + "console-clear": "^1.1.0", + "get-port": "^3.2.0", + "kleur": "^3.0.0", + "local-access": "^1.0.1", + "sade": "^1.6.0", + "semiver": "^1.0.0", + "sirv": "^1.0.13", + "tinydate": "^1.0.0" + }, + "bin": { + "sirv": "bin.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svelte": { + "version": "3.42.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.42.2.tgz", + "integrity": "sha512-FOyNYKXb8wdE0Ot+Ctt2/OyDLsNBP8+V6PUE9ag6ZKeLslIou0LnMu1fhtWUA+HjzKTbAM1yj+4PFLtg/3pMJA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/terser": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", + "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tinydate": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", + "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/ws": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", + "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", + "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@polka/url": { + "version": "1.0.0-next.17", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.17.tgz", + "integrity": "sha512-0p1rCgM3LLbAdwBnc7gqgnvjHg9KpbhcSphergHShlkWz8EdPawoMJ3/VbezI0mGC5eKCDzMaPgF9Yca6cKvrg==" + }, + "@rollup/plugin-commonjs": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz", + "integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "commondir": "^1.0.1", + "estree-walker": "^2.0.1", + "glob": "^7.1.6", + "is-reference": "^1.2.1", + "magic-string": "^0.25.7", + "resolve": "^1.17.0" + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.19.0" + } + }, + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "dependencies": { + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + } + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "@types/node": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.0.tgz", + "integrity": "sha512-e66BrnjWQ3BRBZ2+iA5e85fcH9GLNe4S0n1H0T3OalK2sXg5XWEFTO4xvmGrYQ3edy+q6fdOh5t0/HOY8OAqBg==", + "dev": true + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "builtin-modules": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", + "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "console-clear": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", + "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==" + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-port": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", + "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=" + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "requires": { + "@types/estree": "*" + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "livereload": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", + "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", + "dev": true, + "requires": { + "chokidar": "^3.5.0", + "livereload-js": "^3.3.1", + "opts": ">= 1.2.0", + "ws": "^7.4.3" + } + }, + "livereload-js": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.2.tgz", + "integrity": "sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==", + "dev": true + }, + "local-access": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz", + "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==" + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "mri": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", + "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==" + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "opts": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", + "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "require-relative": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", + "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "2.56.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.56.2.tgz", + "integrity": "sha512-s8H00ZsRi29M2/lGdm1u8DJpJ9ML8SUOpVVBd33XNeEeL3NVaTiUcSBHzBdF3eAyR0l7VSpsuoVUGrRHq7aPwQ==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-css-only": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", + "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "4" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", + "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", + "dev": true, + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + } + } + }, + "rollup-plugin-livereload": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz", + "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==", + "dev": true, + "requires": { + "livereload": "^0.9.1" + } + }, + "rollup-plugin-svelte": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", + "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", + "dev": true, + "requires": { + "require-relative": "^0.8.7", + "rollup-pluginutils": "^2.8.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + } + } + }, + "sade": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", + "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", + "requires": { + "mri": "^1.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "semiver": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", + "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==" + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "sirv": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.14.tgz", + "integrity": "sha512-czTFDFjK9lXj0u9mJ3OmJoXFztoilYS+NdRPcJoT182w44wSEkHSiO7A2517GLJ8wKM4GjCm2OXE66Dhngbzjg==", + "requires": { + "@polka/url": "^1.0.0-next.17", + "mime": "^2.3.1", + "totalist": "^1.0.0" + } + }, + "sirv-cli": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.14.tgz", + "integrity": "sha512-yyUTNr984ANKDloqepkYbBSqvx3buwYg2sQKPWjSU+IBia5loaoka2If8N9CMwt8AfP179cdEl7kYJ//iWJHjQ==", + "requires": { + "console-clear": "^1.1.0", + "get-port": "^3.2.0", + "kleur": "^3.0.0", + "local-access": "^1.0.1", + "sade": "^1.6.0", + "semiver": "^1.0.0", + "sirv": "^1.0.13", + "tinydate": "^1.0.0" + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svelte": { + "version": "3.42.2", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.42.2.tgz", + "integrity": "sha512-FOyNYKXb8wdE0Ot+Ctt2/OyDLsNBP8+V6PUE9ag6ZKeLslIou0LnMu1fhtWUA+HjzKTbAM1yj+4PFLtg/3pMJA==", + "dev": true + }, + "terser": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", + "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + } + }, + "tinydate": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", + "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "totalist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", + "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", + "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", + "dev": true, + "requires": {} + } + } +} diff --git a/web/package.json b/web/package.json new file mode 100644 index 00000000..03cd4553 --- /dev/null +++ b/web/package.json @@ -0,0 +1,23 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "private": true, + "scripts": { + "build": "rollup -c", + "dev": "rollup -c -w", + "start": "sirv public --no-clear" + }, + "devDependencies": { + "@rollup/plugin-commonjs": "^17.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", + "rollup": "^2.3.4", + "rollup-plugin-css-only": "^3.1.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-svelte": "^7.0.0", + "rollup-plugin-terser": "^7.0.0", + "svelte": "^3.0.0" + }, + "dependencies": { + "sirv-cli": "^1.0.0" + } +} diff --git a/web/public/favicon.png b/web/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..7e6f5eb5a2f1f1c882d265cf479de25caa925645 GIT binary patch literal 3127 zcmV-749N3|P)i z7)}s4L53SJCkR}iVi00SFk;`MXX*#X*kkwKs@nFGS}c;=?XFjU|G$3t^5sjIVS2G+ zw)WGF83CpoGXhLGW(1gW%uV|X7>1P6VhCX=Ux)Lb!*DZ%@I3!{Gsf7d?gtIQ%nQiK z3%(LUSkBji;C5Rfgd6$VsF@H`Pk@xtY6t<>FNR-pD}=C~$?)9pdm3XZ36N5PNWYjb z$xd$yNQR9N!dfj-Vd@BwQo^FIIWPPmT&sZyQ$v81(sCBV=PGy{0wltEjB%~h157*t zvbe_!{=I_783x!0t1-r#-d{Y?ae$Q4N_Nd^Ui^@y(%)Gjou6y<3^XJdu{rmUf-Me?)zZ>9OR&6U5H*cK; z$gUlB{g0O4gN0sLSO|Of?hU(l?;h(jA3uH!Z{EBKuV23ouU@^Y6#%v+QG;>e*E}%?wlu-NT4DG zs)z)7WbLr)vGAu(ohrKc^em@OpO&f~6_>E61n_e0_V3@{U3^O;j{`^mNCJUj_>;7v zsMs6Hu3g7+@v+lSo;=yTYFqq}jZmQ-BK8K{C4kqi_i*jBaQE(Au0607V-zKeT;EPg zX(`vrn=L+e74+-Tqeok@_`tDa$G9I|$nTU5H*2V8@y()n*zqM?J1G!-1aX;CfDC9B zTnJ#j_%*n8Qb1)re*Bno7g0RG{Eb;IK14irJYJp$5Z6ac9~b_P?+5t~95~SRG$g?1 znFJ7p$xV&GZ18m~79TGRdfsc-BcX$9yXTR*n)mPD@1~O(_?cT$ZvFPucRmGlq&se0 zKrcUf^k}4hM*biEJOWKzz!qQe;CB_ZtSOO9Owg#lZAc=s65^rb{fZe(TYu_rk!wKkEf}RIt=#Om( zR8mN`DM<^xj~59euMMspBolVN zAPTr8sSDI104orIAdmL$uOXn*6hga1G+0WD0E?UtabxC#VC~vf3|10|phW;yQ3CY8 z2CM=)ErF;xq-YJ5G|um}>*1#E+O_Mu|Nr#qQ&G1P-NMq@f?@*XUcSbV?tX=)ilM-Q zBZP|!Bpv0V;#ojKcpc7$=eqO;#Uy~#?^kNI{vSZfLx&DEt~LTmaKWXcx=joubklI<*Aw z>LtMaQ7DR<1I2LkWvwyu#Rwn~;ezT}_g(@5l3h?W%-a86Y-t#O1PubP+z<%?V5D(U zy57A6{h+{?kOZp7&WKZR+=sznMJ}+Dnpo=C_0%R_x_t~J5T?E_{+))l5v1%52>)d-`iiZyx|5!%M2Fb2dU zW3~MwwpEH9Rhue+k$UIOoo($Ds!NbOyMR36fRHu;*15(YcA7siIZk#%JWz>P!qX1?IUojG&nKR>^gArBt2 zit(ETyZ=@V&7mv_Fi4bABcnwP+jzQuHcfU&BrAV91u-rFvEi7y-KnWsvHH=d2 zgAk(GKm_S8RcTJ>2N3~&Hbwp{Z3NF_Xeh}g4Eke)V&dY{W(3&b1j9t4yK_aYJisZZ{1rcU5- z;eD>K;ndPq&B-8yA_S0F!4ThA&{1{x)H<#?k9a#6Pc6L?V^s0``ynL&D;p(!Nmx`Y zFkHex{4p!Ggm^@DlehW}iHHVi}~u=$&N? z(NEBLQ#UxxAkdW>X9LnqUr#t4Lu0=9L8&o>JsqTtT5|%gb3QA~hr0pED71+iFFr)dZ=Q=E6ng{NE{Z~0)C?deO#?Aj zSDQ$z#TeC2T^|=}6GBo-&$;E{HL3!q3Z-szuf)O=G#zDjin4SSP%o%6+2IT#sLjQa ziyxFFz~LMjWY+_a5H!U6%a<=b7QVP^ z*90a62;bVq{?@)P6^DWd^Yilq4|YTV2Nw!Yu;a1lPI-sxR)rf@Fe5DhDP7FH zZZ%4S*1C30P;|O+jB!1;m|rXT90Sm5*RBbQN`PKu+hDD*S^yE(CdtSfg=z>u$cIj> zdiv{ margin-left: auto; margin-right: auto; @@ -531,71 +392,24 @@ table a{ } } -@media screen and (max-width: 667px) -{ - html{ +@media screen and (max-width: 667px) { + html { font-size: calc(16px + 6 * ((100vw - 320px) / 680)); } - #container{ - align-items: stretch; - display: grid; - grid-column-gap: 20px; - grid-row-gap: 0px; - grid-template-columns: 1fr; - grid-template-rows: 80px auto; - justify-items: stretch; - margin-bottom: 1vh; - width: 90%; - } - - h1{ + h1 { font-size: 4em; height: auto; margin-bottom: 0em; } - h2{ + h2 { font-size: 1em; height: auto; margin-bottom: 0em; } - h3{ + h3 { font-size: 1em; } - - #apps_loop{ - grid-column-gap: 0px; - grid-row-gap: 0px; - grid-template-columns: 1fr 1fr; - width: 90vw; - } - - .apps_icon{ - height: 64px; - margin-right: 0.8em; - padding-top: 14px; - } - - .apps_icon span{ - font-size: 2em; - line-height: 2.5rem; - } - - #links_loop{ - display: grid; - flex-wrap: nowrap; - grid-column-gap: 20px; - grid-row-gap: 0px; - grid-template-columns: 1fr 1fr; - grid-template-rows: auto; - } -} - -/* Small Screens */ -@media only screen and (max-width: 400px) { - #app-address { - display: none; - } } diff --git a/web/public/index.html b/web/public/index.html new file mode 100644 index 00000000..a2f10df5 --- /dev/null +++ b/web/public/index.html @@ -0,0 +1,19 @@ + + + + + + + Hajimari + + + + + + + + + + + + \ No newline at end of file diff --git a/web/rollup.config.js b/web/rollup.config.js new file mode 100644 index 00000000..e8965ec8 --- /dev/null +++ b/web/rollup.config.js @@ -0,0 +1,76 @@ +import svelte from 'rollup-plugin-svelte'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import livereload from 'rollup-plugin-livereload'; +import { terser } from 'rollup-plugin-terser'; +import css from 'rollup-plugin-css-only'; + +const production = !process.env.ROLLUP_WATCH; + +function serve() { + let server; + + function toExit() { + if (server) server.kill(0); + } + + return { + writeBundle() { + if (server) return; + server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], { + stdio: ['ignore', 'inherit', 'inherit'], + shell: true + }); + + process.on('SIGTERM', toExit); + process.on('exit', toExit); + } + }; +} + +export default { + input: 'src/main.js', + output: { + sourcemap: true, + format: 'iife', + name: 'app', + file: 'public/build/bundle.js' + }, + plugins: [ + svelte({ + compilerOptions: { + // enable run-time checks when not in production + dev: !production + } + }), + // we'll extract any component CSS out into + // a separate file - better for performance + css({ output: 'bundle.css' }), + + // If you have external dependencies installed from + // npm, you'll most likely need these plugins. In + // some cases you'll need additional configuration - + // consult the documentation for details: + // https://github.com/rollup/plugins/tree/master/packages/commonjs + resolve({ + browser: true, + dedupe: ['svelte'] + }), + commonjs(), + + // In dev mode, call `npm run start` once + // the bundle has been generated + !production && serve(), + + // Watch the `public` directory and refresh the + // browser on changes when not in production + !production && livereload('public'), + + // If we're building for production (npm run build + // instead of npm run dev), minify + production && terser() + ], + watch: { + clearScreen: false + } +}; diff --git a/web/scripts/setupTypeScript.js b/web/scripts/setupTypeScript.js new file mode 100644 index 00000000..133658af --- /dev/null +++ b/web/scripts/setupTypeScript.js @@ -0,0 +1,121 @@ +// @ts-check + +/** This script modifies the project to support TS code in .svelte files like: + + + + As well as validating the code for CI. + */ + +/** To work on this script: + rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template +*/ + +const fs = require("fs") +const path = require("path") +const { argv } = require("process") + +const projectRoot = argv[2] || path.join(__dirname, "..") + +// Add deps to pkg.json +const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) +packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { + "svelte-check": "^2.0.0", + "svelte-preprocess": "^4.0.0", + "@rollup/plugin-typescript": "^8.0.0", + "typescript": "^4.0.0", + "tslib": "^2.0.0", + "@tsconfig/svelte": "^2.0.0" +}) + +// Add script for checking +packageJSON.scripts = Object.assign(packageJSON.scripts, { + "check": "svelte-check --tsconfig ./tsconfig.json" +}) + +// Write the package JSON +fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) + +// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too +const beforeMainJSPath = path.join(projectRoot, "src", "main.js") +const afterMainTSPath = path.join(projectRoot, "src", "main.ts") +fs.renameSync(beforeMainJSPath, afterMainTSPath) + +// Switch the app.svelte file to use TS +const appSveltePath = path.join(projectRoot, "src", "App.svelte") +let appFile = fs.readFileSync(appSveltePath, "utf8") +appFile = appFile.replace(" + +
+ + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/web/src/AppList/AppGroup.svelte b/web/src/AppList/AppGroup.svelte new file mode 100644 index 00000000..bca31f9f --- /dev/null +++ b/web/src/AppList/AppGroup.svelte @@ -0,0 +1,74 @@ + +{#each group.apps as app} +
+
+ +
+
+ {app.name} + {app.url} +
+
+{/each} + + \ No newline at end of file diff --git a/web/src/AppList/index.svelte b/web/src/AppList/index.svelte new file mode 100644 index 00000000..215f5065 --- /dev/null +++ b/web/src/AppList/index.svelte @@ -0,0 +1,66 @@ + + +{#if apps.length === 0} +
+

Applications

+

No apps here...yet

+
+{:else} +
+

Applications

+
+ {#each apps as group} + {#if config.groupApps === true} + + {:else} + + {/if} + {/each} +
+
+{/if} + + \ No newline at end of file diff --git a/web/src/BookmarkList/BookmarkGroup.svelte b/web/src/BookmarkList/BookmarkGroup.svelte new file mode 100644 index 00000000..0e632b13 --- /dev/null +++ b/web/src/BookmarkList/BookmarkGroup.svelte @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/web/src/BookmarkList/index.svelte b/web/src/BookmarkList/index.svelte new file mode 100644 index 00000000..76076245 --- /dev/null +++ b/web/src/BookmarkList/index.svelte @@ -0,0 +1,68 @@ + + +{#if bookmarks.length === 0} + +{:else} + +{/if} + + \ No newline at end of file diff --git a/web/src/header.svelte b/web/src/header.svelte new file mode 100644 index 00000000..c66f7d0f --- /dev/null +++ b/web/src/header.svelte @@ -0,0 +1,16 @@ + + +
+

{greeting}

+

{date}

+
+ + \ No newline at end of file diff --git a/web/src/main.js b/web/src/main.js new file mode 100644 index 00000000..d80e9a35 --- /dev/null +++ b/web/src/main.js @@ -0,0 +1,7 @@ +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +export default app; \ No newline at end of file diff --git a/web/src/store.js b/web/src/store.js new file mode 100644 index 00000000..110e4558 --- /dev/null +++ b/web/src/store.js @@ -0,0 +1,20 @@ +import { writable, derived } from 'svelte/store'; + +/** Store for your data. +This assumes the data you're pulling back will be an array. +If it's going to be an object, default this to an empty object. +**/ +export const apiData = writable({}); + +/** Data transformation. +**/ +export const name = derived(apiData, ($apiData) => { + if ($apiData.name){ + return $apiData.name; + } + return "You"; +}); + +export const apps = writable([]); + +export const bookmarks = writable([]); \ No newline at end of file diff --git a/web/static/js/main.js b/web/static/js/main.js deleted file mode 100644 index 19cbe76a..00000000 --- a/web/static/js/main.js +++ /dev/null @@ -1,46 +0,0 @@ -document.addEventListener('DOMContentLoaded', () => { - var editor = CodeMirror.fromTextArea(document.getElementById("editor"), { - mode: "yaml", - theme: "dracula", - lineNumbers: true, - tabsize: 2, - indentWithTabs: false, - foldGutter: true, - gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"], - lint: { - "getAnnotations": self.yaml_validator - } - }); - - editor.setOption("extraKeys", { - Tab: function(cm) { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }); - - fetch(location.href.replace(location.hash, "").replace(/\/$/, "") + '/config') - .then(response => response.json()) - .then(data => editor.setValue(jsyaml.dump(data))) - - var saveButton = document.getElementById('save-config'); - - saveButton.addEventListener('click', function() { - console.log(JSON.stringify(jsyaml.load(editor.getValue()))); - var method = location.pathname == "/" ? 'post' : 'put'; - fetch(location.href.replace(location.hash,""), { - method: method, - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(jsyaml.load(editor.getValue())) - }).then(response => response.json()) - .then(function(data) { - if (data.error) { - - } else { - location.assign(location.origin + "/" + data.id); - } - }); - }, false); -}); \ No newline at end of file diff --git a/web/static/js/search.js b/web/static/js/search.js deleted file mode 100755 index 76f6cda9..00000000 --- a/web/static/js/search.js +++ /dev/null @@ -1,95 +0,0 @@ -var sindex = 0; -var cycle = false; - -function start() { - var query = getParameterByName('q'); - if (query) search(query.replaceAll("+", "%2B")); - - document.getElementById('keywords').focus(); - - window.setInterval(function () { - updatetime(); - }, 200); -} - -function handleKeyPress(e) { - var key = e.keyCode || e.which; - var text = document.getElementById("keywords").value.replaceAll("+", "%2B"); - var option = text.substr(1, text.indexOf(' ') - 1) || text.substr(1); - var subtext = text.substr(2 + option.length); - if (key == 13) { // Search functions - search(text); - } - if(key == 32){ //Space to go to search - document.getElementById("keywords").focus(); - } - sindex = 0; - cycle = false; -} - -function search(text) { - var option = text.substr(1, text.indexOf(' ') - 1) || text.substr(1); - var subtext = text.substr(2 + option.length); - if (text[0] === '/') { - if (text.indexOf(' ') > -1) { - switch (option) { - case "d": - window.location = "https://duckduckgo.com/?q=" + subtext; - break; - case "i": - window.location = "https://www.imdb.com/find?q=" + subtext; - break; - case "r": - window.location = "https://www.reddit.com/search?q=" + subtext; - break; - case "y": - window.location = "https://www.youtube.com/results?search_query=" + subtext; - break; - } - } else { - var option = text.substr(1); - switch (option) { - case "d": - window.location = "https://www.duckduckgo.com"; - break; - case "y": - window.location = "https://www.youtube.com"; - break; - case "r": - window.location = "https://reddit.com"; - break; - case "s": - window.location = "https://open.spotify.com"; - break; - } - } - } else if (validURL(text)) { - if (containsProtocol(text)) - window.location = text; - else - window.location = "https://" + text; - } else { - window.location = "https://www.google.com/search?q=" + text; - } -} - -// Source: https://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-a-url -function validURL(str) { - var pattern = new RegExp('^(https?:\\/\\/)?' + // protocol - '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name - '((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address - '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path - '(\\?[;&a-z\\d%_.~+=-]*)?' + // query string - '(\\#[-a-z\\d_]*)?$', 'i'); // fragment locator - return !!pattern.test(str); -} - -function containsProtocol(str) { - var pattern = new RegExp('^(https?:\\/\\/){1}.*', 'i'); - return !!pattern.test(str); -} - -String.prototype.replaceAll = function(search, replacement) { - var target = this; - return target.split(search).join(replacement); -}; diff --git a/web/static/js/themer.js b/web/static/js/themer.js deleted file mode 100755 index 9c19380d..00000000 --- a/web/static/js/themer.js +++ /dev/null @@ -1,139 +0,0 @@ -const setValue = (property, value) => { - if (value) { - document.documentElement.style.setProperty(`--${property}`, value); - - const input = document.querySelector(`#${property}`); - if (input) { - value = value.replace('px', ''); - input.value = value; - } - } -}; - -const setValueFromLocalStorage = property => { - let value = localStorage.getItem(property); - setValue(property, value); -}; - -const setTheme = options => { - for (let option of Object.keys(options)) { - const property = option; - const value = options[option]; - - setValue(property, value); - localStorage.setItem(property, value); - } -} - -document.addEventListener('DOMContentLoaded', () => { - setValueFromLocalStorage('color-background'); - setValueFromLocalStorage('color-text-pri'); - setValueFromLocalStorage('color-text-acc'); -}); - -const dataThemeButtons = document.querySelectorAll('[data-theme]'); - -for (let i = 0; i < dataThemeButtons.length; i++) { - dataThemeButtons[i].addEventListener('click', () => { - const theme = dataThemeButtons[i].dataset.theme; - - switch (theme) { - case 'blackboard': - setTheme({ - 'color-background': '#1a1a1a', - 'color-text-pri': '#FFFDEA', - 'color-text-acc': '#5c5c5c' - }); - return; - - case 'gazette': - setTheme({ - 'color-background': '#F2F7FF', - 'color-text-pri': '#000000', - 'color-text-acc': '#5c5c5c' - }); - return; - - case 'espresso': - setTheme({ - 'color-background': '#21211F', - 'color-text-pri': '#D1B59A', - 'color-text-acc': '#4E4E4E' - }); - return; - - case 'cab': - setTheme({ - 'color-background': '#F6D305', - 'color-text-pri': '#1F1F1F', - 'color-text-acc': '#424242' - }); - return; - - case 'cloud': - setTheme({ - 'color-background': '#f1f2f0', - 'color-text-pri': '#35342f', - 'color-text-acc': '#37bbe4' - }); - return; - - case 'lime': - setTheme({ - 'color-background': '#263238', - 'color-text-pri': '#AABBC3', - 'color-text-acc': '#aeea00' - }); - return; - - case 'white': - setTheme({ - 'color-background': '#ffffff', - 'color-text-pri': '#222222', - 'color-text-acc': '#dddddd' - }); - return; - - case 'tron': - setTheme({ - 'color-background': '#242B33', - 'color-text-pri': '#EFFBFF', - 'color-text-acc': '#6EE2FF' - }); - return; - - case 'blues': - setTheme({ - 'color-background': '#2B2C56', - 'color-text-pri': '#EFF1FC', - 'color-text-acc': '#6677EB' - }); - return; - - case 'passion': - setTheme({ - 'color-background': '#f5f5f5', - 'color-text-pri': '#12005e', - 'color-text-acc': '#8e24aa' - }); - return; - - case 'chalk': - setTheme({ - 'color-background': '#263238', - 'color-text-pri': '#AABBC3', - 'color-text-acc': '#FF869A' - }); - return; - - case 'paper': - setTheme({ - 'color-background': '#F8F6F1', - 'color-text-pri': '#4C432E', - 'color-text-acc': '#AA9A73' - }); - return; - - } - }) -} \ No newline at end of file diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl deleted file mode 100644 index 17994b15..00000000 --- a/web/template/index.html.tmpl +++ /dev/null @@ -1,141 +0,0 @@ - - - - {{or .Title "Hajimari"}} - - - - - - - - - - - - - - - - -
- - - - - - -
-

Applications

-
- {{range .Apps}} -
-
- -
-
- {{.Name}} - {{.URL}} -
-
- {{end}} -
-
- - -
- - - - - - - - - - - - - - - - \ No newline at end of file From b540c194ee135542a9c06bb8ab0d98b21a1b3f83 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sat, 5 Feb 2022 16:34:33 -0500 Subject: [PATCH 02/46] Initial commit --- internal/annotations/annotations.go | 2 + internal/hajimari/hajimari.go | 1 + internal/kube/lists/services/services.go | 64 ++++++++++++++++++++++++ internal/kube/wrappers/ingress.go | 10 ++++ internal/util/tplutil/tplutil.go | 16 +++++- web/static/css/styles.css | 13 +++-- web/static/js/themer.js | 58 ++++++++++++++------- web/template/index.html.tmpl | 6 ++- 8 files changed, 147 insertions(+), 23 deletions(-) create mode 100644 internal/kube/lists/services/services.go diff --git a/internal/annotations/annotations.go b/internal/annotations/annotations.go index 5c2ef79b..2c47adfb 100644 --- a/internal/annotations/annotations.go +++ b/internal/annotations/annotations.go @@ -13,4 +13,6 @@ const ( HajimariInstanceAnnotation = "hajimari.io/instance" // HajimariURLAnnotation const used for specifying the URL for the hajimari app HajimariURLAnnotation = "hajimari.io/url" + // HajimariStatusCheckAnnotation boolean used for enabling status indicators. + HajimariStatusCheckEnabledAnnotation = "hajimari.io/statusCheckEnabled" ) diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go index d1bc0821..ea24ebe3 100644 --- a/internal/hajimari/hajimari.go +++ b/internal/hajimari/hajimari.go @@ -6,4 +6,5 @@ type App struct { Icon string Group string URL string + Status bool } diff --git a/internal/kube/lists/services/services.go b/internal/kube/lists/services/services.go new file mode 100644 index 00000000..f8b9ec86 --- /dev/null +++ b/internal/kube/lists/services/services.go @@ -0,0 +1,64 @@ +package services + +import ( + "context" + + "github.com/toboshii/hajimari/internal/config" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// List struct is used to list services +type List struct { + appConfig config.Config + err error // Used for bubbling errors + items []v1.Service + kubeClient kubernetes.Interface +} + +// FilterFunc defined for creating functions that comply with the filtering ingresses +type FilterFunc func(v1.Service, config.Config) bool + +// NewList creates an List object that you can use to query services +func NewList(kubeClient kubernetes.Interface, appConfig config.Config, items ...v1.Service) *List { + return &List{ + kubeClient: kubeClient, + appConfig: appConfig, + items: items, + } +} + +// Populate function returns a list of servicees +func (il *List) Populate(namespaces ...string) *List { + for _, namespace := range namespaces { + services, err := il.kubeClient.CoreV1().Services(namespace).List(context.Background(), metav1.ListOptions{}) + if err != nil { + il.err = err + } + il.items = append(il.items, services.Items...) + } + + return il +} + +// Filter function applies a filter func that is passed as a parameter to the list of services +func (il *List) Filter(filterFunc FilterFunc) *List { + + var filtered []v1.Service + + for _, ingress := range il.items { + if filterFunc(ingress, il.appConfig) { + filtered = append(filtered, ingress) + } + } + + // Replace original services with filtered + il.items = filtered + return il +} + +// Get function returns the services currently present in List +func (il *List) Get() ([]v1.Service, error) { + return il.items, il.err +} diff --git a/internal/kube/wrappers/ingress.go b/internal/kube/wrappers/ingress.go index b1f0d119..8c96cf5f 100644 --- a/internal/kube/wrappers/ingress.go +++ b/internal/kube/wrappers/ingress.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/toboshii/hajimari/internal/annotations" + utilStrings "github.com/toboshii/hajimari/internal/util/strings" "github.com/toboshii/hajimari/internal/log" v1 "k8s.io/api/networking/v1" ) @@ -54,6 +55,15 @@ func (iw *IngressWrapper) GetGroup() string { return iw.GetNamespace() } +// GetStatusCheckEnabled func extracts statusCheck feature gate from the ingress +// @default false +func (iw *IngressWrapper) GetStatusCheckEnabled() bool { + if statusCheckEnabledFromAnnotation := iw.GetAnnotationValue(annotations.HajimariStatusCheckEnabledAnnotation); statusCheckEnabledFromAnnotation != "" { + return utilStrings.ParseBool(statusCheckEnabledFromAnnotation) + } + return false +} + // GetURL func extracts url of the ingress wrapped by the object func (iw *IngressWrapper) GetURL() string { diff --git a/internal/util/tplutil/tplutil.go b/internal/util/tplutil/tplutil.go index a1a6a42b..5698e0f6 100644 --- a/internal/util/tplutil/tplutil.go +++ b/internal/util/tplutil/tplutil.go @@ -1,6 +1,9 @@ package tplutil -import "fmt" +import ( + "fmt" + "reflect" +) // greet returns the greeting to be used in the h1 heading func Greet(name string, currentHour int) (greet string) { @@ -21,3 +24,14 @@ func Greet(name string, currentHour int) (greet string) { return fmt.Sprintf("%s!", greet) } + +func IsStatusCheckEnabled(app interface{}) bool { + rv := reflect.ValueOf(app) + if rv.Kind() == reflect.Ptr { + rv = rv.Elem() + } + if rv.Kind() != reflect.Struct { + return false + } + return rv.FieldByName("Status").IsValid() +} diff --git a/web/static/css/styles.css b/web/static/css/styles.css index b2f68447..42e212c6 100755 --- a/web/static/css/styles.css +++ b/web/static/css/styles.css @@ -62,7 +62,7 @@ h1{ h2{ font-size: 16px; height: 30px; - + } h3{ @@ -251,6 +251,13 @@ table a{ text-transform: uppercase; } +.apps_status#online hr{ + border-bottom: 3px solid var(--color-status-online); +} + +.apps_status#offline hr{ + border-bottom: 3px solid var(--color-status-offline); +} #links_loop{ display: grid; @@ -513,7 +520,7 @@ table a{ margin-right: auto; width: 90%; } - + #apps_loop{ grid-template-columns: 1fr 1fr 1fr; width: 90vw; @@ -582,7 +589,7 @@ table a{ font-size: 2em; line-height: 2.5rem; } - + #links_loop{ display: grid; flex-wrap: nowrap; diff --git a/web/static/js/themer.js b/web/static/js/themer.js index 9c19380d..0c58cbf9 100755 --- a/web/static/js/themer.js +++ b/web/static/js/themer.js @@ -42,7 +42,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#1a1a1a', 'color-text-pri': '#FFFDEA', - 'color-text-acc': '#5c5c5c' + 'color-text-acc': '#5c5c5c', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -50,7 +52,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#F2F7FF', 'color-text-pri': '#000000', - 'color-text-acc': '#5c5c5c' + 'color-text-acc': '#5c5c5c', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -58,7 +62,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#21211F', 'color-text-pri': '#D1B59A', - 'color-text-acc': '#4E4E4E' + 'color-text-acc': '#4E4E4E', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -66,7 +72,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#F6D305', 'color-text-pri': '#1F1F1F', - 'color-text-acc': '#424242' + 'color-text-acc': '#424242', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -74,7 +82,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#f1f2f0', 'color-text-pri': '#35342f', - 'color-text-acc': '#37bbe4' + 'color-text-acc': '#37bbe4', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -82,7 +92,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#263238', 'color-text-pri': '#AABBC3', - 'color-text-acc': '#aeea00' + 'color-text-acc': '#aeea00', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -90,7 +102,9 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#ffffff', 'color-text-pri': '#222222', - 'color-text-acc': '#dddddd' + 'color-text-acc': '#dddddd', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; @@ -98,42 +112,52 @@ for (let i = 0; i < dataThemeButtons.length; i++) { setTheme({ 'color-background': '#242B33', 'color-text-pri': '#EFFBFF', - 'color-text-acc': '#6EE2FF' + 'color-text-acc': '#6EE2FF', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; - + case 'blues': setTheme({ 'color-background': '#2B2C56', 'color-text-pri': '#EFF1FC', - 'color-text-acc': '#6677EB' + 'color-text-acc': '#6677EB', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; - + case 'passion': setTheme({ 'color-background': '#f5f5f5', 'color-text-pri': '#12005e', - 'color-text-acc': '#8e24aa' + 'color-text-acc': '#8e24aa', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; - + case 'chalk': setTheme({ 'color-background': '#263238', 'color-text-pri': '#AABBC3', - 'color-text-acc': '#FF869A' + 'color-text-acc': '#FF869A', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; - + case 'paper': setTheme({ 'color-background': '#F8F6F1', 'color-text-pri': '#4C432E', - 'color-text-acc': '#AA9A73' + 'color-text-acc': '#AA9A73', + 'color-status-online': '#00FF00', + 'color-status-offline': '#FF0000' }); return; } }) -} \ No newline at end of file +} diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl index 17994b15..60e4b75d 100644 --- a/web/template/index.html.tmpl +++ b/web/template/index.html.tmpl @@ -4,7 +4,7 @@ {{or .Title "Hajimari"}} - + @@ -95,6 +95,8 @@
+ {{if .IsStatusCheckEnabled(.)}} +
{{.Name}} @@ -138,4 +140,4 @@ - \ No newline at end of file + From 8214073ff0ba103ccd98a1c4947b355a1f9cb505 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sun, 6 Feb 2022 11:43:02 -0500 Subject: [PATCH 03/46] First sort of draft --- config.yaml.example | 76 ----------------------- internal/hajimari/hajimari.go | 8 +-- internal/hajimari/ingressapps/apps.go | 30 ++++++--- internal/kube/lists/services/services.go | 64 ------------------- internal/kube/util/serviceStatusGetter.go | 47 ++++++++++++++ internal/kube/wrappers/ingress.go | 2 +- web/template/index.html.tmpl | 3 +- 7 files changed, 76 insertions(+), 154 deletions(-) delete mode 100644 config.yaml.example delete mode 100644 internal/kube/lists/services/services.go create mode 100644 internal/kube/util/serviceStatusGetter.go diff --git a/config.yaml.example b/config.yaml.example deleted file mode 100644 index d72db3f7..00000000 --- a/config.yaml.example +++ /dev/null @@ -1,76 +0,0 @@ -instanceName: null -defaultEnable: false -namespaceSelector: - matchNames: - - downloads -title: null -name: "you" -customApps: -- name: Test - url: https://example.com - icon: test-tube -groups: -- name: Communicate - links: - - name: Discord - url: 'https://discord.com' - - name: Gmail - url: 'http://gmail.com' - - name: Slack - url: 'https://slack.com/signin' -- name: Cloud - links: - - name: Box - url: 'https://box.com' - - name: Dropbox - url: 'https://dropbox.com' - - name: Drive - url: 'https://drive.google.com' -- name: Design - links: - - name: Awwwards - url: 'https://awwwards.com' - - name: Dribbble - url: 'https://dribbble.com' - - name: Muz.li - url: 'https://medium.muz.li/' -- name: Dev - links: - - name: Codepen - url: 'https://codepen.io/' - - name: Devdocs - url: 'https://devdocs.io' - - name: Devhints - url: 'https://devhints.io' -- name: Lifestyle - links: - - name: Design Milk - url: 'https://design-milk.com/category/interior-design/' - - name: Dwell - url: 'https://www.dwell.com/' - - name: Freshome - url: 'https://www.mymove.com/freshome/' -- name: Media - links: - - name: Spotify - url: 'http://browse.spotify.com' - - name: Trakt - url: 'http://trakt.tv' - - name: YouTube - url: 'https://youtube.com/feed/subscriptions' -- name: Reading - links: - - name: Instapaper - url: 'https://www.instapaper.com/u' - - name: Medium - url: 'http://medium.com' - - name: Reddit - url: 'http://reddit.com' -- name: Tech - links: - - name: TheNextWeb - url: 'https://thenextweb.com/' - - name: The Verge - url: 'https://theverge.com/' - - name: MIT Technology Review - url: 'https://www.technologyreview.com/' diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go index ea24ebe3..869ef3a1 100644 --- a/internal/hajimari/hajimari.go +++ b/internal/hajimari/hajimari.go @@ -2,9 +2,9 @@ package hajimari // App struct that contains information about an app that is enabled in hajimari type App struct { - Name string - Icon string - Group string - URL string + Name string + Icon string + Group string + URL string Status bool } diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index b7c329ec..d6385851 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -1,10 +1,13 @@ package ingressapps import ( + "strings" + "github.com/toboshii/hajimari/internal/annotations" "github.com/toboshii/hajimari/internal/config" "github.com/toboshii/hajimari/internal/hajimari" "github.com/toboshii/hajimari/internal/kube/lists/ingresses" + "github.com/toboshii/hajimari/internal/kube/util" "github.com/toboshii/hajimari/internal/kube/wrappers" "github.com/toboshii/hajimari/internal/log" v1 "k8s.io/api/networking/v1" @@ -47,7 +50,7 @@ func (al *List) Populate(namespaces ...string) *List { al.err = err } - al.items = convertIngressesToHajimariApps(ingressList) + al.items = convertIngressesToHajimariApps(ingressList, *util.NewServiceStatusGetter(al.kubeClient)) return al } @@ -57,17 +60,28 @@ func (al *List) Get() ([]hajimari.App, error) { return al.items, al.err } -func convertIngressesToHajimariApps(ingresses []v1.Ingress) (apps []hajimari.App) { +func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.ServiceStatusGetter) (apps []hajimari.App) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) wrapper := wrappers.NewIngressWrapper(&ingress) - apps = append(apps, hajimari.App{ - Name: wrapper.GetName(), - Group: wrapper.GetGroup(), - Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), - URL: wrapper.GetURL(), - }) + if wrapper.GetStatusCheckEnabled() { + apps = append(apps, hajimari.App{ + Name: wrapper.GetName(), + Group: wrapper.GetGroup(), + Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), + URL: wrapper.GetURL(), + Status: strings.EqualFold(ssg.GetServiceStatus(ingress).Get(), "Healthy"), + }) + } else { + apps = append(apps, hajimari.App{ + Name: wrapper.GetName(), + Group: wrapper.GetGroup(), + Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), + URL: wrapper.GetURL(), + }) + } + } return } diff --git a/internal/kube/lists/services/services.go b/internal/kube/lists/services/services.go deleted file mode 100644 index f8b9ec86..00000000 --- a/internal/kube/lists/services/services.go +++ /dev/null @@ -1,64 +0,0 @@ -package services - -import ( - "context" - - "github.com/toboshii/hajimari/internal/config" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -// List struct is used to list services -type List struct { - appConfig config.Config - err error // Used for bubbling errors - items []v1.Service - kubeClient kubernetes.Interface -} - -// FilterFunc defined for creating functions that comply with the filtering ingresses -type FilterFunc func(v1.Service, config.Config) bool - -// NewList creates an List object that you can use to query services -func NewList(kubeClient kubernetes.Interface, appConfig config.Config, items ...v1.Service) *List { - return &List{ - kubeClient: kubeClient, - appConfig: appConfig, - items: items, - } -} - -// Populate function returns a list of servicees -func (il *List) Populate(namespaces ...string) *List { - for _, namespace := range namespaces { - services, err := il.kubeClient.CoreV1().Services(namespace).List(context.Background(), metav1.ListOptions{}) - if err != nil { - il.err = err - } - il.items = append(il.items, services.Items...) - } - - return il -} - -// Filter function applies a filter func that is passed as a parameter to the list of services -func (il *List) Filter(filterFunc FilterFunc) *List { - - var filtered []v1.Service - - for _, ingress := range il.items { - if filterFunc(ingress, il.appConfig) { - filtered = append(filtered, ingress) - } - } - - // Replace original services with filtered - il.items = filtered - return il -} - -// Get function returns the services currently present in List -func (il *List) Get() ([]v1.Service, error) { - return il.items, il.err -} diff --git a/internal/kube/util/serviceStatusGetter.go b/internal/kube/util/serviceStatusGetter.go new file mode 100644 index 00000000..a1b3b19a --- /dev/null +++ b/internal/kube/util/serviceStatusGetter.go @@ -0,0 +1,47 @@ +package util + +import ( + "context" + + "github.com/toboshii/hajimari/internal/log" + networkingV1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +var ( + logger = log.New() +) + +type ServiceStatusGetter struct { + err error + status string + kubeClient kubernetes.Interface +} + +func NewServiceStatusGetter(kubeClient kubernetes.Interface) *ServiceStatusGetter { + return &ServiceStatusGetter{ + kubeClient: kubeClient, + } +} + +func (ssg *ServiceStatusGetter) GetServiceStatus(ingress networkingV1.Ingress) *ServiceStatusGetter { + service, err := ssg.kubeClient.CoreV1().Services(ingress.Namespace).Get(context.Background(), ingress.Name, metav1.GetOptions{}) + + if err != nil { + ssg.err = err + } + + ssg.status = service.Status.String() + + return ssg +} + +func (ssg *ServiceStatusGetter) Get() string { + if ssg.err != nil { + logger.Warn(ssg.err) + return "" + } + + return ssg.status +} diff --git a/internal/kube/wrappers/ingress.go b/internal/kube/wrappers/ingress.go index 8c96cf5f..9bfdcc7a 100644 --- a/internal/kube/wrappers/ingress.go +++ b/internal/kube/wrappers/ingress.go @@ -5,8 +5,8 @@ import ( "strings" "github.com/toboshii/hajimari/internal/annotations" - utilStrings "github.com/toboshii/hajimari/internal/util/strings" "github.com/toboshii/hajimari/internal/log" + utilStrings "github.com/toboshii/hajimari/internal/util/strings" v1 "k8s.io/api/networking/v1" ) diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl index 60e4b75d..d2002f43 100644 --- a/web/template/index.html.tmpl +++ b/web/template/index.html.tmpl @@ -95,8 +95,9 @@
- {{if .IsStatusCheckEnabled(.)}} +
+
{{.Name}} From bd14b65623d702aa96c227640c1d447a825cafa9 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sun, 6 Feb 2022 15:10:03 -0500 Subject: [PATCH 04/46] Almost MVP --- internal/hajimari/hajimari.go | 2 +- internal/hajimari/ingressapps/apps.go | 8 ++-- internal/kube/util/serviceStatusGetter.go | 47 ----------------------- internal/kube/wrappers/ingress.go | 4 +- web/static/css/styles.css | 4 +- 5 files changed, 8 insertions(+), 57 deletions(-) delete mode 100644 internal/kube/util/serviceStatusGetter.go diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go index 869ef3a1..01b3d0c0 100644 --- a/internal/hajimari/hajimari.go +++ b/internal/hajimari/hajimari.go @@ -6,5 +6,5 @@ type App struct { Icon string Group string URL string - Status bool + Status string } diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index d6385851..fc32a99a 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -1,8 +1,6 @@ package ingressapps import ( - "strings" - "github.com/toboshii/hajimari/internal/annotations" "github.com/toboshii/hajimari/internal/config" "github.com/toboshii/hajimari/internal/hajimari" @@ -50,7 +48,7 @@ func (al *List) Populate(namespaces ...string) *List { al.err = err } - al.items = convertIngressesToHajimariApps(ingressList, *util.NewServiceStatusGetter(al.kubeClient)) + al.items = convertIngressesToHajimariApps(ingressList, *util.NewStatusGetter(al.kubeClient)) return al } @@ -60,7 +58,7 @@ func (al *List) Get() ([]hajimari.App, error) { return al.items, al.err } -func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.ServiceStatusGetter) (apps []hajimari.App) { +func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGetter) (apps []hajimari.App) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) @@ -71,7 +69,7 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.ServiceStat Group: wrapper.GetGroup(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Status: strings.EqualFold(ssg.GetServiceStatus(ingress).Get(), "Healthy"), + Status: ssg.GetDeploymentStatus(ingress).Get(), }) } else { apps = append(apps, hajimari.App{ diff --git a/internal/kube/util/serviceStatusGetter.go b/internal/kube/util/serviceStatusGetter.go deleted file mode 100644 index a1b3b19a..00000000 --- a/internal/kube/util/serviceStatusGetter.go +++ /dev/null @@ -1,47 +0,0 @@ -package util - -import ( - "context" - - "github.com/toboshii/hajimari/internal/log" - networkingV1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -var ( - logger = log.New() -) - -type ServiceStatusGetter struct { - err error - status string - kubeClient kubernetes.Interface -} - -func NewServiceStatusGetter(kubeClient kubernetes.Interface) *ServiceStatusGetter { - return &ServiceStatusGetter{ - kubeClient: kubeClient, - } -} - -func (ssg *ServiceStatusGetter) GetServiceStatus(ingress networkingV1.Ingress) *ServiceStatusGetter { - service, err := ssg.kubeClient.CoreV1().Services(ingress.Namespace).Get(context.Background(), ingress.Name, metav1.GetOptions{}) - - if err != nil { - ssg.err = err - } - - ssg.status = service.Status.String() - - return ssg -} - -func (ssg *ServiceStatusGetter) Get() string { - if ssg.err != nil { - logger.Warn(ssg.err) - return "" - } - - return ssg.status -} diff --git a/internal/kube/wrappers/ingress.go b/internal/kube/wrappers/ingress.go index 9bfdcc7a..9fd58208 100644 --- a/internal/kube/wrappers/ingress.go +++ b/internal/kube/wrappers/ingress.go @@ -56,12 +56,12 @@ func (iw *IngressWrapper) GetGroup() string { } // GetStatusCheckEnabled func extracts statusCheck feature gate from the ingress -// @default false +// @default true func (iw *IngressWrapper) GetStatusCheckEnabled() bool { if statusCheckEnabledFromAnnotation := iw.GetAnnotationValue(annotations.HajimariStatusCheckEnabledAnnotation); statusCheckEnabledFromAnnotation != "" { return utilStrings.ParseBool(statusCheckEnabledFromAnnotation) } - return false + return true } // GetURL func extracts url of the ingress wrapped by the object diff --git a/web/static/css/styles.css b/web/static/css/styles.css index 42e212c6..12be0837 100755 --- a/web/static/css/styles.css +++ b/web/static/css/styles.css @@ -251,11 +251,11 @@ table a{ text-transform: uppercase; } -.apps_status#online hr{ +hr.apps_status#True{ border-bottom: 3px solid var(--color-status-online); } -.apps_status#offline hr{ +hr.apps_status#False{ border-bottom: 3px solid var(--color-status-offline); } From 7b7d6b5e25f22ae0494c6737d639755330033531 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sun, 6 Feb 2022 15:10:15 -0500 Subject: [PATCH 05/46] Almost MVP --- internal/kube/util/statusgetter.go | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 internal/kube/util/statusgetter.go diff --git a/internal/kube/util/statusgetter.go b/internal/kube/util/statusgetter.go new file mode 100644 index 00000000..ee4ce3b0 --- /dev/null +++ b/internal/kube/util/statusgetter.go @@ -0,0 +1,66 @@ +package util + +import ( + "context" + + "github.com/toboshii/hajimari/internal/log" + v1 "k8s.io/api/apps/v1" + networkingV1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +var ( + logger = log.New() +) + +type StatusGetter struct { + err error + status string + kubeClient kubernetes.Interface +} + +func NewStatusGetter(kubeClient kubernetes.Interface) *StatusGetter { + return &StatusGetter{ + kubeClient: kubeClient, + } +} + +func (ssg *StatusGetter) GetDeploymentStatus(ingress networkingV1.Ingress) *StatusGetter { + deployment, err := ssg.kubeClient.AppsV1().Deployments(ingress.ObjectMeta.GetNamespace()).Get(context.Background(), ingress.ObjectMeta.GetName(), metav1.GetOptions{}) + + if err != nil { + ssg.err = err + } + + conditions := deployment.Status.Conditions + + for _, c := range conditions { + if (c.Type==v1.DeploymentAvailable) { + ssg.status = string(c.Status) + } + } + + return ssg +} + +func (ssg *StatusGetter) GetServiceStatus(ingress networkingV1.Ingress) *StatusGetter { + service, err := ssg.kubeClient.CoreV1().Services(ingress.Namespace).Get(context.Background(), ingress.Name, metav1.GetOptions{}) + + if err != nil { + ssg.err = err + } + + ssg.status = service.Status.String() + + return ssg +} + +func (ssg *StatusGetter) Get() string { + if ssg.err != nil { + logger.Warn(ssg.err) + return "" + } + + return ssg.status +} From 87037c9981fff413f72a9627e7c20871f84dc1c2 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Mon, 7 Feb 2022 19:12:15 -0500 Subject: [PATCH 06/46] MVP --- internal/hajimari/ingressapps/apps.go | 6 +++-- internal/kube/util/namespaces.go | 2 +- internal/kube/util/statusgetter.go | 36 ++++++++++++++------------- internal/log/log.go | 2 +- web/static/css/styles.css | 12 ++++++--- web/static/js/themer.js | 2 ++ web/template/index.html.tmpl | 6 ++--- 7 files changed, 38 insertions(+), 28 deletions(-) diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index fc32a99a..900693cc 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -61,15 +61,17 @@ func (al *List) Get() ([]hajimari.App, error) { func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGetter) (apps []hajimari.App) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) + logger.Debug(ingress.Labels) + status := ssg.GetDeploymentStatus(ingress).Get() wrapper := wrappers.NewIngressWrapper(&ingress) - if wrapper.GetStatusCheckEnabled() { + if wrapper.GetStatusCheckEnabled() && len(status)>0 { apps = append(apps, hajimari.App{ Name: wrapper.GetName(), Group: wrapper.GetGroup(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Status: ssg.GetDeploymentStatus(ingress).Get(), + Status: status, }) } else { apps = append(apps, hajimari.App{ diff --git a/internal/kube/util/namespaces.go b/internal/kube/util/namespaces.go index 4192a375..6a54db91 100644 --- a/internal/kube/util/namespaces.go +++ b/internal/kube/util/namespaces.go @@ -44,7 +44,7 @@ func removeDuplicates(elements []string) []string { result := []string{} for v := range elements { - if encountered[elements[v]] == true { + if encountered[elements[v]] { // Do not add duplicate. } else { // Record this element as an encountered element. diff --git a/internal/kube/util/statusgetter.go b/internal/kube/util/statusgetter.go index ee4ce3b0..dc4abaf3 100644 --- a/internal/kube/util/statusgetter.go +++ b/internal/kube/util/statusgetter.go @@ -2,6 +2,8 @@ package util import ( "context" + // "fmt" + "strings" "github.com/toboshii/hajimari/internal/log" v1 "k8s.io/api/apps/v1" @@ -10,52 +12,52 @@ import ( "k8s.io/client-go/kubernetes" ) +// Initializes logger var ( logger = log.New() ) +// struct for the StatusGetter object type StatusGetter struct { err error status string kubeClient kubernetes.Interface } +// Initializes a StatusGetter func NewStatusGetter(kubeClient kubernetes.Interface) *StatusGetter { return &StatusGetter{ kubeClient: kubeClient, } } +// GetDeploymentStatus gets the status conditions of the deployment and sets the status to match the Available status reported func (ssg *StatusGetter) GetDeploymentStatus(ingress networkingV1.Ingress) *StatusGetter { + + if ssg.err != nil { + ssg.err = nil + } + deployment, err := ssg.kubeClient.AppsV1().Deployments(ingress.ObjectMeta.GetNamespace()).Get(context.Background(), ingress.ObjectMeta.GetName(), metav1.GetOptions{}) if err != nil { ssg.err = err - } + } else { - conditions := deployment.Status.Conditions + conditions := deployment.Status.Conditions - for _, c := range conditions { - if (c.Type==v1.DeploymentAvailable) { - ssg.status = string(c.Status) + for _, c := range conditions { + logger.Debug(c.String()) + if (c.Type==v1.DeploymentAvailable) { + ssg.status = strings.ToLower(string(c.Status)) + } } } return ssg } -func (ssg *StatusGetter) GetServiceStatus(ingress networkingV1.Ingress) *StatusGetter { - service, err := ssg.kubeClient.CoreV1().Services(ingress.Namespace).Get(context.Background(), ingress.Name, metav1.GetOptions{}) - - if err != nil { - ssg.err = err - } - - ssg.status = service.Status.String() - - return ssg -} - +// Gets the current value of status func (ssg *StatusGetter) Get() string { if ssg.err != nil { logger.Warn(ssg.err) diff --git a/internal/log/log.go b/internal/log/log.go index 550a5080..07ff1460 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -19,7 +19,7 @@ func New() *logrus.Logger { Hooks: make(logrus.LevelHooks), Out: os.Stdout, Formatter: &logrus.TextFormatter{}, - Level: logrus.InfoLevel, + Level: logrus.DebugLevel, } log.Hooks.Add(filenameHook) diff --git a/web/static/css/styles.css b/web/static/css/styles.css index 12be0837..c7747dcd 100755 --- a/web/static/css/styles.css +++ b/web/static/css/styles.css @@ -251,12 +251,16 @@ table a{ text-transform: uppercase; } -hr.apps_status#True{ - border-bottom: 3px solid var(--color-status-online); +hr.apps_status.available{ + border-width: 0 0 3px 0; + border-style: solid; + border-color: var(--color-status-online); } -hr.apps_status#False{ - border-bottom: 3px solid var(--color-status-offline); +hr.apps_status.notready{ + border-width: 0 0 3px 0; + border-style: solid; + border-color: var(--color-status-offline); } #links_loop{ diff --git a/web/static/js/themer.js b/web/static/js/themer.js index 0c58cbf9..5935e1c5 100755 --- a/web/static/js/themer.js +++ b/web/static/js/themer.js @@ -29,6 +29,8 @@ document.addEventListener('DOMContentLoaded', () => { setValueFromLocalStorage('color-background'); setValueFromLocalStorage('color-text-pri'); setValueFromLocalStorage('color-text-acc'); + setValueFromLocalStorage('color-status-online'); + setValueFromLocalStorage('color-status-offline'); }); const dataThemeButtons = document.querySelectorAll('[data-theme]'); diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl index d2002f43..552f7f77 100644 --- a/web/template/index.html.tmpl +++ b/web/template/index.html.tmpl @@ -95,12 +95,12 @@
- -
+ +
From 926b669abbdf04e40fd30579a24cc38bc6fa233d Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Mon, 7 Feb 2022 21:45:41 -0500 Subject: [PATCH 07/46] Bookmark --- internal/hajimari/hajimari.go | 2 +- internal/hajimari/ingressapps/apps.go | 5 +++-- internal/kube/util/statusgetter.go | 1 - internal/util/tplutil/tplutil.go | 14 ++++---------- main.go | 3 ++- web/template/index.html.tmpl | 8 ++++---- 6 files changed, 14 insertions(+), 19 deletions(-) diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go index 01b3d0c0..d7f79e47 100644 --- a/internal/hajimari/hajimari.go +++ b/internal/hajimari/hajimari.go @@ -6,5 +6,5 @@ type App struct { Icon string Group string URL string - Status string + Status *string } diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index 900693cc..57f48255 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -61,8 +61,8 @@ func (al *List) Get() ([]hajimari.App, error) { func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGetter) (apps []hajimari.App) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) - logger.Debug(ingress.Labels) status := ssg.GetDeploymentStatus(ingress).Get() + var emptyStatus *string wrapper := wrappers.NewIngressWrapper(&ingress) if wrapper.GetStatusCheckEnabled() && len(status)>0 { @@ -71,7 +71,7 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGette Group: wrapper.GetGroup(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Status: status, + Status: &status, }) } else { apps = append(apps, hajimari.App{ @@ -79,6 +79,7 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGette Group: wrapper.GetGroup(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), + Status: emptyStatus, }) } diff --git a/internal/kube/util/statusgetter.go b/internal/kube/util/statusgetter.go index dc4abaf3..0202b353 100644 --- a/internal/kube/util/statusgetter.go +++ b/internal/kube/util/statusgetter.go @@ -2,7 +2,6 @@ package util import ( "context" - // "fmt" "strings" "github.com/toboshii/hajimari/internal/log" diff --git a/internal/util/tplutil/tplutil.go b/internal/util/tplutil/tplutil.go index 5698e0f6..bf983da6 100644 --- a/internal/util/tplutil/tplutil.go +++ b/internal/util/tplutil/tplutil.go @@ -2,7 +2,7 @@ package tplutil import ( "fmt" - "reflect" + "github.com/toboshii/hajimari/internal/hajimari" ) // greet returns the greeting to be used in the h1 heading @@ -25,13 +25,7 @@ func Greet(name string, currentHour int) (greet string) { return fmt.Sprintf("%s!", greet) } -func IsStatusCheckEnabled(app interface{}) bool { - rv := reflect.ValueOf(app) - if rv.Kind() == reflect.Ptr { - rv = rv.Elem() - } - if rv.Kind() != reflect.Struct { - return false - } - return rv.FieldByName("Status").IsValid() +// Checks if status is null indicating disabled status check +func IsStatusCheckEnabled(app hajimari.App) bool { + return app.Status != nil } diff --git a/main.go b/main.go index 7c6ad78e..22507dd1 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,7 @@ import ( "github.com/toboshii/hajimari/internal/log" "github.com/toboshii/hajimari/internal/services" "github.com/toboshii/hajimari/internal/stores" + "github.com/toboshii/hajimari/internal/util/tplutil" ) var ( @@ -40,7 +41,7 @@ var indexHTML embed.FS //go:embed web/static var staticFiles embed.FS -var tpl = template.Must(template.ParseFS(indexHTML, "web/template/index.html.tmpl")) +var tpl = template.Must(template.New("").Funcs(tplutil.TplfuncMap).ParseFS(indexHTML, "web/template/index.html.tmpl")) func main() { diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl index 552f7f77..243ac44c 100644 --- a/web/template/index.html.tmpl +++ b/web/template/index.html.tmpl @@ -95,12 +95,12 @@
- -
- + {{/* {{if (Deref .Status) ne nil}} +
+ {{end}} */}}
From 12e41ba89c9257c01ec4f3cceecf16602ff10d6f Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Mon, 7 Feb 2022 21:45:48 -0500 Subject: [PATCH 08/46] Bookmark --- internal/util/tplutil/tplfuncmap.go | 12 ++++++++ internal/util/tplutil/tplutil_test.go | 40 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 internal/util/tplutil/tplfuncmap.go create mode 100644 internal/util/tplutil/tplutil_test.go diff --git a/internal/util/tplutil/tplfuncmap.go b/internal/util/tplutil/tplfuncmap.go new file mode 100644 index 00000000..d77e0070 --- /dev/null +++ b/internal/util/tplutil/tplfuncmap.go @@ -0,0 +1,12 @@ +package tplutil + +import ( + "text/template" +) + +// Map of Utility functions for use in the template +var ( + TplfuncMap = template.FuncMap { + "deref": func(s *string) string{ return *s }, + } +) diff --git a/internal/util/tplutil/tplutil_test.go b/internal/util/tplutil/tplutil_test.go new file mode 100644 index 00000000..96867282 --- /dev/null +++ b/internal/util/tplutil/tplutil_test.go @@ -0,0 +1,40 @@ +package tplutil + +import ( + "testing" + "github.com/toboshii/hajimari/internal/hajimari" +) + +// IsStatusCheckEnabled works when Status is set +func TestIsStatusCheckEnabled(t *testing.T) { + status := "true" + app := hajimari.App { + Name : "myApp", + Icon : "mdi:flower", + Group : "myGroup", + URL : "www", + Status : &status, + } + want := true + check := IsStatusCheckEnabled(app) + + if want != check { + t.Fail() + } +} + +// IsStatusCheckEnabled works when Status is not set +func TestIsStatusCheckEnabledOnEmpty(t *testing.T) { + app := hajimari.App { + Name : "myApp", + Icon : "mdi:flower", + Group : "myGroup", + URL : "www", + } + want := false + check := IsStatusCheckEnabled(app) + + if want != check { + t.Fail() + } +} From f7aef72c5ca2dc74b14a1c0ec2d4a310567df976 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Mon, 7 Feb 2022 21:51:28 -0500 Subject: [PATCH 09/46] Minimum viable product --- internal/hajimari/hajimari.go | 2 +- internal/hajimari/ingressapps/apps.go | 4 ++-- internal/util/tplutil/tplutil.go | 2 +- internal/util/tplutil/tplutil_test.go | 3 ++- main.go | 3 +-- web/template/index.html.tmpl | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go index d7f79e47..01b3d0c0 100644 --- a/internal/hajimari/hajimari.go +++ b/internal/hajimari/hajimari.go @@ -6,5 +6,5 @@ type App struct { Icon string Group string URL string - Status *string + Status string } diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index 57f48255..44c814b2 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -62,7 +62,7 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGette for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) status := ssg.GetDeploymentStatus(ingress).Get() - var emptyStatus *string + var emptyStatus string = "undefined" wrapper := wrappers.NewIngressWrapper(&ingress) if wrapper.GetStatusCheckEnabled() && len(status)>0 { @@ -71,7 +71,7 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGette Group: wrapper.GetGroup(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Status: &status, + Status: status, }) } else { apps = append(apps, hajimari.App{ diff --git a/internal/util/tplutil/tplutil.go b/internal/util/tplutil/tplutil.go index bf983da6..ae52a92b 100644 --- a/internal/util/tplutil/tplutil.go +++ b/internal/util/tplutil/tplutil.go @@ -27,5 +27,5 @@ func Greet(name string, currentHour int) (greet string) { // Checks if status is null indicating disabled status check func IsStatusCheckEnabled(app hajimari.App) bool { - return app.Status != nil + return app.Status != "undefined" } diff --git a/internal/util/tplutil/tplutil_test.go b/internal/util/tplutil/tplutil_test.go index 96867282..b3ca7558 100644 --- a/internal/util/tplutil/tplutil_test.go +++ b/internal/util/tplutil/tplutil_test.go @@ -13,7 +13,7 @@ func TestIsStatusCheckEnabled(t *testing.T) { Icon : "mdi:flower", Group : "myGroup", URL : "www", - Status : &status, + Status : status, } want := true check := IsStatusCheckEnabled(app) @@ -30,6 +30,7 @@ func TestIsStatusCheckEnabledOnEmpty(t *testing.T) { Icon : "mdi:flower", Group : "myGroup", URL : "www", + Status: "undefined", } want := false check := IsStatusCheckEnabled(app) diff --git a/main.go b/main.go index 22507dd1..7c6ad78e 100644 --- a/main.go +++ b/main.go @@ -16,7 +16,6 @@ import ( "github.com/toboshii/hajimari/internal/log" "github.com/toboshii/hajimari/internal/services" "github.com/toboshii/hajimari/internal/stores" - "github.com/toboshii/hajimari/internal/util/tplutil" ) var ( @@ -41,7 +40,7 @@ var indexHTML embed.FS //go:embed web/static var staticFiles embed.FS -var tpl = template.Must(template.New("").Funcs(tplutil.TplfuncMap).ParseFS(indexHTML, "web/template/index.html.tmpl")) +var tpl = template.Must(template.ParseFS(indexHTML, "web/template/index.html.tmpl")) func main() { diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl index 243ac44c..a380c5ff 100644 --- a/web/template/index.html.tmpl +++ b/web/template/index.html.tmpl @@ -95,9 +95,9 @@
- {{/* {{if (Deref .Status) ne nil}} -
- {{end}} */}} + {{if ne .Status "undefined"}} +
+ {{end}}
{{.Name}} From 0230e20acb7d77468353997cde9835e7bb14ed3b Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Tue, 8 Feb 2022 20:00:12 -0500 Subject: [PATCH 10/46] Reset log level back to info --- internal/log/log.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/log/log.go b/internal/log/log.go index 07ff1460..550a5080 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -19,7 +19,7 @@ func New() *logrus.Logger { Hooks: make(logrus.LevelHooks), Out: os.Stdout, Formatter: &logrus.TextFormatter{}, - Level: logrus.DebugLevel, + Level: logrus.InfoLevel, } log.Hooks.Add(filenameHook) From 88d7b4513c6ebd28b50e72802dc454ad1cdf03ac Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Mon, 21 Feb 2022 13:18:11 -0500 Subject: [PATCH 11/46] Add rudimentary replicaStatusGetter --- internal/config/config.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/internal/config/config.go b/internal/config/config.go index 8233761f..0d79bc1a 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -23,6 +23,7 @@ type Config struct { Groups []Group Providers []Provider Modules []Module + Experimental []ExperimentalFeature } // CustomApp struct for specifying apps that are not generated using ingresses @@ -63,6 +64,13 @@ type NamespaceSelector struct { LabelSelector *metav1.LabelSelector } +// ExperimentalFeature struct for featureGating new experiments +type ExperimentalFeature struct { + Enabled bool + Name string + Properties map[string]bool +} + // GetConfig returns hajimari configuration func GetConfig() (*Config, error) { var c Config From 2bc291df7dcc6be492cb7a4d16be8be70babc254 Mon Sep 17 00:00:00 2001 From: Toboshii Nakama <63410334+toboshii@users.noreply.github.com> Date: Wed, 17 Aug 2022 14:24:36 -0500 Subject: [PATCH 12/46] fix: update deps and target go 1.19 --- .air.toml | 4 +- .dockerignore | 1 + Dockerfile | 4 +- Makefile | 26 -- {docs/static/img => assets}/logo-black.svg | 0 {docs/static/img => assets}/logo-white.svg | 0 {docs/static/img => assets}/logo.png | Bin {docs/static/img => assets}/screen01.png | Bin {docs/static/img => assets}/screen02.png | Bin main.go => cmd/hajimari/main.go | 0 go.mod | 72 ++++- go.sum | 321 +++++++++++---------- internal/handlers/handler.go | 2 +- internal/modules/utils.go | 28 -- internal/modules/weather.go | 34 --- 15 files changed, 235 insertions(+), 257 deletions(-) delete mode 100644 Makefile rename {docs/static/img => assets}/logo-black.svg (100%) rename {docs/static/img => assets}/logo-white.svg (100%) rename {docs/static/img => assets}/logo.png (100%) rename {docs/static/img => assets}/screen01.png (100%) rename {docs/static/img => assets}/screen02.png (100%) rename main.go => cmd/hajimari/main.go (100%) delete mode 100644 internal/modules/utils.go delete mode 100644 internal/modules/weather.go diff --git a/.air.toml b/.air.toml index d5ee9275..334744b8 100644 --- a/.air.toml +++ b/.air.toml @@ -2,8 +2,8 @@ root = "." tmp_dir = "tmp" [build] - bin = "./tmp/main" - cmd = "go build -o ./tmp/main ." + bin = "./tmp/hajimari" + cmd = "go build -o ./tmp/hajimari ./cmd/hajimari/main.go" delay = 1000 exclude_dir = ["web", "docs", "charts", "tmp", "vendor"] exclude_file = [] diff --git a/.dockerignore b/.dockerignore index 2d1fdc04..6ca8ff95 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,7 @@ .git .github/ .gitignore +assets/ docs/ Dockerfile LICENSE diff --git a/Dockerfile b/Dockerfile index 40feba34..38dfc827 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.16-alpine as build +FROM golang:1.19-alpine as build ARG TARGETPLATFORM ENV TARGETPLATFORM=${TARGETPLATFORM:-linux/amd64} @@ -23,7 +23,7 @@ RUN \ && \ chmod +x hajimari -FROM alpine:3.14 +FROM alpine:3.16 RUN \ apk add --no-cache \ diff --git a/Makefile b/Makefile deleted file mode 100644 index 2b4f0f5b..00000000 --- a/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -.DEFAULT_GOAL := help - -.PHONY: help -# From: http://disq.us/p/16327nq -help: ## This help. - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) - -.PHONY: build -build: ## Build the Go project. - go build -ldflags="-s -w" -trimpath -v -o hajimari - -.PHONY: run -run: build ## Run the program - ./hajimari - -.PHONY: fmt -fmt: ## Format the project with gofmt - gofmt -l -w -s . - -.PHONY: lint -lint: ## Lint code with golangci-lint - golangci-lint run - -.PHONY: test -test: ## Run the tests - go test -cover ./... diff --git a/docs/static/img/logo-black.svg b/assets/logo-black.svg similarity index 100% rename from docs/static/img/logo-black.svg rename to assets/logo-black.svg diff --git a/docs/static/img/logo-white.svg b/assets/logo-white.svg similarity index 100% rename from docs/static/img/logo-white.svg rename to assets/logo-white.svg diff --git a/docs/static/img/logo.png b/assets/logo.png similarity index 100% rename from docs/static/img/logo.png rename to assets/logo.png diff --git a/docs/static/img/screen01.png b/assets/screen01.png similarity index 100% rename from docs/static/img/screen01.png rename to assets/screen01.png diff --git a/docs/static/img/screen02.png b/assets/screen02.png similarity index 100% rename from docs/static/img/screen02.png rename to assets/screen02.png diff --git a/main.go b/cmd/hajimari/main.go similarity index 100% rename from main.go rename to cmd/hajimari/main.go diff --git a/go.mod b/go.mod index f63a3a3f..ff6f33fd 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,68 @@ module github.com/toboshii/hajimari -go 1.16 +go 1.19 require ( github.com/chi-middleware/logrus-logger v0.2.0 - github.com/go-chi/chi v1.5.4 - github.com/go-chi/chi/v5 v5.0.3 - github.com/go-chi/cors v1.2.0 - github.com/go-chi/render v1.0.1 + github.com/go-chi/chi/v5 v5.0.7 + github.com/go-chi/cors v1.2.1 + github.com/go-chi/render v1.0.2 github.com/matoous/go-nanoid/v2 v2.0.0 github.com/onrik/logrus v0.9.0 - github.com/sirupsen/logrus v1.8.1 - github.com/spf13/viper v1.8.1 - github.com/tidwall/gjson v1.8.1 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - k8s.io/api v0.22.0 - k8s.io/apimachinery v0.22.0 - k8s.io/client-go v0.22.0 + github.com/sirupsen/logrus v1.9.0 + github.com/spf13/viper v1.12.0 + gopkg.in/yaml.v3 v3.0.1 + k8s.io/api v0.24.3 + k8s.io/apimachinery v0.24.3 + k8s.io/client-go v0.24.3 +) + +require ( + github.com/ajg/form v1.5.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful/v3 v3.9.0 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.22.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.6.9 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.3 // indirect + github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.4.0 // indirect + github.com/tidwall/gjson v1.14.3 // indirect + golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect + golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7 // indirect + golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 // indirect + golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/klog/v2 v2.70.1 // indirect + k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea // indirect + k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect + sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 78c47ee6..30dd5c1b 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT 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= @@ -15,6 +16,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY 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= @@ -26,7 +28,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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= @@ -36,6 +37,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo 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/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= @@ -47,16 +49,17 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp 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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= 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/chi-middleware/logrus-logger v0.2.0 h1:Do3vcVSRsLh7zSRKxsVg5Kr5//rTqytwprCR1HzVqT8= github.com/chi-middleware/logrus-logger v0.2.0/go.mod h1:ie/rvKsXrtqqsnJd3qtSEnLxgCs1I758WYmHdv6CRt0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -66,8 +69,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk 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/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 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= @@ -75,40 +77,53 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= +github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= -github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= -github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= -github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= -github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= -github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= +github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= +github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= +github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg= +github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= 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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.1 h1:S6xFhsBKAtvfphnJwRzeCh3OEGsTL/crXdEetSxLs0Q= +github.com/go-openapi/swag v0.22.1/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -145,6 +160,9 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu 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/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0= +github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E= 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= @@ -155,11 +173,12 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.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= @@ -172,93 +191,69 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf 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/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/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/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/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/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 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/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +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/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= github.com/matoous/go-nanoid/v2 v2.0.0 h1:d19kur2QuLeHmJBkvYkFdhFBzLoo1XVm2GgTpL+9Tj0= github.com/matoous/go-nanoid/v2 v2.0.0/go.mod h1:FtS4aGPVfEkxKxhdWPAspZpZSh1cOjtM7Ej/So3hR0g= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -267,68 +262,69 @@ github.com/onrik/logrus v0.9.0/go.mod h1:qfe9NeZVAJfIxviw3cYkZo3kvBtLoPRJriAO8zl github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.3 h1:h9JoA60e1dVEOpp0PFwJSmt1Htu057NUq9/bUwaO61s= +github.com/pelletier/go-toml/v2 v2.0.3/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= +github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= 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/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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU= -github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= -github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= -github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= -github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/subosito/gotenv v1.4.0 h1:yAzM1+SmVcz5R4tXGsNMu1jUl2aOJXoiWUCEwwnGrvs= +github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7vWWGaGo= +github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= +github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= 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= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= 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= @@ -336,18 +332,16 @@ 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.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -371,7 +365,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu 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= @@ -386,8 +379,6 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/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= @@ -418,12 +409,16 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/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-20220812174116-3211cb980234 h1:RDqmgfe7SvlMWoqC3xwQ2blLO3fcWcxMa3eBLRdRW7E= +golang.org/x/net v0.0.0-20220812174116-3211cb980234/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= 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= @@ -435,8 +430,9 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/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-20220808172628-8227340efae7 h1:dtndE8FcEta75/4kHF3AbpuWzV6f1LjnLrM4pe2SZrw= +golang.org/x/oauth2 v0.0.0-20220808172628-8227340efae7/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= 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= @@ -448,10 +444,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ 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/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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -488,20 +482,26 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/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-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220209214540-3681064d5158/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2 h1:fqTvyMIIj+HRzMmnzr9NtpHP6uVpvB5fkHcgPDC4nu8= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc= +golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= @@ -509,20 +509,21 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ= +golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -532,7 +533,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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= @@ -552,6 +552,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs 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-20200505023115-26f46d2f7ef8/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= @@ -565,12 +566,12 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f 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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -593,7 +594,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q 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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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= @@ -638,12 +638,14 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D 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-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 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= @@ -663,7 +665,7 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 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.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 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= @@ -675,8 +677,10 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= 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.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -687,8 +691,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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= @@ -700,8 +704,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 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 h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= 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= @@ -709,24 +715,35 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= -k8s.io/api v0.22.0 h1:elCpMZ9UE8dLdYxr55E06TmSeji9I3KH494qH70/y+c= -k8s.io/api v0.22.0/go.mod h1:0AoXXqst47OI/L0oGKq9DG61dvGRPXs7X4/B7KyjBCU= -k8s.io/apimachinery v0.22.0 h1:CqH/BdNAzZl+sr3tc0D3VsK3u6ARVSo3GWyLmfIjbP0= -k8s.io/apimachinery v0.22.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/client-go v0.22.0 h1:sD6o9O6tCwUKCENw8v+HFsuAbq2jCu8cWC61/ydwA50= -k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY= +k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= +k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= +k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/client-go v0.24.3 h1:Nl1840+6p4JqkFWEW2LnMKU667BUxw03REfLAVhuKQY= +k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9 h1:imL9YgXQ9p7xmPzHFm/vVd/cF78jad+n4wK1ABwYtMM= -k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= +k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= +k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea h1:3QOH5+2fGsY8e1qf+GIFpg+zw/JGNrgyZRQR7/m6uWg= +k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 h1:XmRqFcQlCy/lKRZ39j+RVpokYNroHPqV3mcBRfnhT5o= +k8s.io/utils v0.0.0-20220812165043-ad590609e2e5/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 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/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/internal/handlers/handler.go b/internal/handlers/handler.go index 82890683..7cb3165a 100644 --- a/internal/handlers/handler.go +++ b/internal/handlers/handler.go @@ -5,8 +5,8 @@ import ( "time" loggerMiddleware "github.com/chi-middleware/logrus-logger" - "github.com/go-chi/chi/middleware" "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/cors" "github.com/go-chi/render" "github.com/toboshii/hajimari/internal/log" diff --git a/internal/modules/utils.go b/internal/modules/utils.go deleted file mode 100644 index 3c7940e1..00000000 --- a/internal/modules/utils.go +++ /dev/null @@ -1,28 +0,0 @@ -package modules - -import ( - "fmt" - "io" - "net/http" - "time" -) - -func updatedAt() string { - return fmt.Sprintf("(Last update at %s)", time.Now().Format("15:04")) -} - -func actualFetch(url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - return body, nil -} diff --git a/internal/modules/weather.go b/internal/modules/weather.go deleted file mode 100644 index 9f7f998b..00000000 --- a/internal/modules/weather.go +++ /dev/null @@ -1,34 +0,0 @@ -package modules - -import ( - "fmt" - - "github.com/tidwall/gjson" - "github.com/toboshii/hajimari/internal/log" -) - -var ( - logger = log.New() -) - -// GetWeather fetches weather information from http://wttr.in -func GetWeather(data map[string]string) string { - body, err := fetchWeather("http://wttr.in/" + data["city"] + "?format=j1") - if err != nil { - return "" - } - - info := gjson.GetManyBytes(body, "current_condition.0.temp_F", "current_condition.0.weatherDesc.0.value") - if info[0].String() == "" || info[1].String() == "" { - return "" - } - - return fmt.Sprintf("Temperature in %s: %s degrees, current condition is: %s %s", - data["city"], - info[0].String(), - info[1].String(), - updatedAt(), - ) -} - -var fetchWeather = actualFetch From 51a84d7deb3f7e9f00be4db54a41c2032e4b5bf6 Mon Sep 17 00:00:00 2001 From: Toboshii Nakama <63410334+toboshii@users.noreply.github.com> Date: Mon, 29 Aug 2022 11:12:01 -0500 Subject: [PATCH 13/46] feat: finalized backend rework --- cmd/hajimari/main.go | 13 +- go.mod | 11 +- go.sum | 18 +- internal/config/config.go | 57 ++- internal/hajimari/customapps/customapps.go | 49 +-- internal/hajimari/ingressapps/apps.go | 6 +- internal/handlers/apps.go | 24 +- internal/handlers/bookmarks.go | 22 +- internal/handlers/handler.go | 11 +- internal/handlers/startpage.go | 392 +++++++++------------ internal/models/app_group.go | 4 +- internal/models/bookmark_group.go | 2 +- internal/models/startpage.go | 13 +- internal/services/startpage.go | 167 ++++----- internal/stores/memory.go | 162 ++++----- internal/util/pointer/pointer.go | 5 + internal/util/tplutil/tplutil.go | 23 -- 17 files changed, 432 insertions(+), 547 deletions(-) create mode 100644 internal/util/pointer/pointer.go delete mode 100644 internal/util/tplutil/tplutil.go diff --git a/cmd/hajimari/main.go b/cmd/hajimari/main.go index 861f85b4..66d7fad2 100644 --- a/cmd/hajimari/main.go +++ b/cmd/hajimari/main.go @@ -4,6 +4,7 @@ import ( "errors" "net/http" + "github.com/fsnotify/fsnotify" "github.com/spf13/viper" "github.com/toboshii/hajimari/internal/handlers" "github.com/toboshii/hajimari/internal/log" @@ -19,10 +20,20 @@ func init() { viper.AddConfigPath("$HOME/.hajimari") // call multiple times to add many search paths viper.AddConfigPath(".") // optionally look for config in the working directory viper.AutomaticEnv() + err := viper.ReadInConfig() // Find and read the config file - if err != nil { // Handle errors reading the config file + + if err != nil { // Handle errors reading the config file panic(errors.New("Fatal error config file: " + err.Error())) } + + logger.Info("Using config file: ", viper.ConfigFileUsed()) + + viper.OnConfigChange(func(e fsnotify.Event) { + logger.Info("Reloading config: ", e.Name) + }) + + viper.WatchConfig() } // //go:embed web/template diff --git a/go.mod b/go.mod index ff6f33fd..cce73e6f 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,8 @@ go 1.19 require ( github.com/chi-middleware/logrus-logger v0.2.0 + github.com/creasty/defaults v1.6.0 + github.com/fsnotify/fsnotify v1.5.4 github.com/go-chi/chi/v5 v5.0.7 github.com/go-chi/cors v1.2.1 github.com/go-chi/render v1.0.2 @@ -12,20 +14,19 @@ require ( github.com/sirupsen/logrus v1.9.0 github.com/spf13/viper v1.12.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.24.3 - k8s.io/apimachinery v0.24.3 - k8s.io/client-go v0.24.3 + k8s.io/api v0.24.4 + k8s.io/apimachinery v0.24.4 + k8s.io/client-go v0.24.4 ) require ( github.com/ajg/form v1.5.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emicklei/go-restful/v3 v3.9.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/swag v0.22.1 // indirect + github.com/go-openapi/swag v0.22.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.6.9 // indirect diff --git a/go.sum b/go.sum index 30dd5c1b..9f70efc9 100644 --- a/go.sum +++ b/go.sum @@ -71,6 +71,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creasty/defaults v1.6.0 h1:ltuE9cfphUtlrBeomuu8PEyISTXnxqkBIoQfXgv7BSc= +github.com/creasty/defaults v1.6.0/go.mod h1:iGzKe6pbEHnpMPtfDXZEr0NVxWnPTjb1bbDy08fPzYM= 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= @@ -122,8 +124,8 @@ github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZ github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/swag v0.22.1 h1:S6xFhsBKAtvfphnJwRzeCh3OEGsTL/crXdEetSxLs0Q= -github.com/go-openapi/swag v0.22.1/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -715,12 +717,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= -k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY= -k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= -k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg= -k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/client-go v0.24.3 h1:Nl1840+6p4JqkFWEW2LnMKU667BUxw03REfLAVhuKQY= -k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= +k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk= +k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M= +k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ= +k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg= +k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y= k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= diff --git a/internal/config/config.go b/internal/config/config.go index 902d664f..8a92707d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,42 +3,33 @@ package config import ( "time" + "github.com/creasty/defaults" "github.com/spf13/viper" - "github.com/toboshii/hajimari/internal/log" + "github.com/toboshii/hajimari/internal/models" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -var ( - logger = log.New() -) - // Config struct for hajimari type Config struct { - NamespaceSelector NamespaceSelector - DefaultEnable bool - Title string - InstanceName string - Name string - CustomApps []CustomApp - Groups []Group - Providers []Provider - Modules []Module -} - -// CustomApp struct for specifying apps that are not generated using ingresses -type CustomApp struct { - Name string - Icon string - URL string - Group string -} - -type Group struct { - Name string `json:"name"` - Links []Link `json:"links"` -} - -type Provider struct { + NamespaceSelector NamespaceSelector `json:"namespaceSelector"` + DefaultEnable bool `default:"false" json:"defaultEnable"` + InstanceName string `default:"" json:"instanceName"` + Title string `default:"Hajimari" json:"title"` + Name string `default:"You" json:"name"` + Theme string `default:"" json:"theme"` + LightTheme string `default:"gazette" json:"lightTheme"` + DarkTheme string `default:"blackboard" json:"darkTheme"` + ShowGreeting bool `default:"true" json:"showGreeting"` + ShowAppGroups bool `default:"false" json:"showAppGroups"` + ShowBookmarkGroups bool `default:"true" json:"showBookmarkGroups"` + ShowGlobalBookmarks bool `default:"false" json:"showGlobalBookmarks"` + CustomApps []models.AppGroup `default:"[]" json:"customApps"` + GlobalBookmarks []models.BookmarkGroup `default:"[]" json:"globalBookmarks"` + SearchProviders []SearchProvider `default:"[]" json:"searchProviders"` + Modules []Module `default:"[]" json:"modules"` +} + +type SearchProvider struct { Name string URL string Prefix string @@ -51,11 +42,6 @@ type Module struct { Output string } -type Link struct { - Name string `json:"name"` - URL string `json:"url"` -} - // NamespaceSelector struct for selecting namespaces based on labels and names type NamespaceSelector struct { Any bool @@ -66,6 +52,7 @@ type NamespaceSelector struct { // GetConfig returns hajimari configuration func GetConfig() (*Config, error) { var c Config + defaults.Set(&c) err := viper.Unmarshal(&c) if err != nil { return nil, err diff --git a/internal/hajimari/customapps/customapps.go b/internal/hajimari/customapps/customapps.go index 3bc1aba7..392b4dc8 100644 --- a/internal/hajimari/customapps/customapps.go +++ b/internal/hajimari/customapps/customapps.go @@ -1,15 +1,12 @@ package customapps import ( + "strings" + "github.com/toboshii/hajimari/internal/config" - "github.com/toboshii/hajimari/internal/log" "github.com/toboshii/hajimari/internal/models" ) -var ( - logger = log.New() -) - // List struct is used for listing hajimari apps type List struct { appConfig config.Config @@ -26,7 +23,15 @@ func NewList(appConfig config.Config) *List { // Populate function that populates a list of custom apps func (al *List) Populate() *List { - al.items = convertCustomAppsToHajimariApps(al.appConfig.CustomApps) + + var customApps []models.AppGroup + + for _, v := range al.appConfig.CustomApps { + v.Group = strings.ToLower(v.Group) + customApps = append(customApps, v) + } + + al.items = customApps return al } @@ -35,35 +40,3 @@ func (al *List) Populate() *List { func (al *List) Get() ([]models.AppGroup, error) { return al.items, al.err } - -func convertCustomAppsToHajimariApps(customApps []config.CustomApp) (appGroups []models.AppGroup) { - for _, customApp := range customApps { - logger.Debugf("Found custom app with Name '%v'", customApp.Name) - - groupMap := make(map[string]int, len(appGroups)) - for i, v := range appGroups { - groupMap[v.Name] = i - } - - if _, ok := groupMap[customApp.Group]; !ok { - appGroups = append(appGroups, models.AppGroup{ - Name: customApp.Group, - }) - } - - appMap := make(map[string]int, len(appGroups)) - for i, v := range appGroups { - appMap[v.Name] = i - } - - if i, ok := appMap[customApp.Group]; ok { - appGroups[i].Apps = append(appGroups[i].Apps, models.App{ - Name: customApp.Name, - Icon: customApp.Icon, - URL: customApp.URL, - }) - } - } - - return -} diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index d3f12358..aeb8b7d4 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -65,18 +65,18 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress) (appGroups []models. groupMap := make(map[string]int, len(appGroups)) for i, v := range appGroups { - groupMap[v.Name] = i + groupMap[v.Group] = i } if _, ok := groupMap[wrapper.GetGroup()]; !ok { appGroups = append(appGroups, models.AppGroup{ - Name: wrapper.GetGroup(), + Group: wrapper.GetGroup(), }) } appMap := make(map[string]int, len(appGroups)) for i, v := range appGroups { - appMap[v.Name] = i + appMap[v.Group] = i } if i, ok := appMap[wrapper.GetGroup()]; ok { diff --git a/internal/handlers/apps.go b/internal/handlers/apps.go index 6e872a8c..b3132a0a 100644 --- a/internal/handlers/apps.go +++ b/internal/handlers/apps.go @@ -31,20 +31,18 @@ func (rs *appResource) AppRoutes() chi.Router { func (rs *appResource) ListApps(w http.ResponseWriter, r *http.Request) { appConfig, err := config.GetConfig() if err != nil { - logger.Error("Failed to read configuration for hajimari", err) + logger.Error("Failed to read configuration for hajimari: ", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } kubeClient := kube.GetClient() - var ingressApps []models.AppGroup - ingressAppsList := ingressapps.NewList(kubeClient, *appConfig) namespaces, err := util.PopulateNamespaceList(kubeClient, appConfig.NamespaceSelector) if err != nil { - logger.Error("An error occurred while populating namespaces", err) + logger.Error("An error occurred while populating namespaces: ", err) render.Render(w, r, ErrServerError(err)) return } @@ -57,9 +55,9 @@ func (rs *appResource) ListApps(w http.ResponseWriter, r *http.Request) { namespacesString = strings.Join(namespaces, ", ") } - logger.Info("Looking for hajimari apps in the following namespaces: " + namespacesString) + logger.Debug("Looking for hajimari apps in the following namespaces: ", namespacesString) - ingressApps, err = ingressAppsList.Populate(namespaces...).Get() + ingressApps, err := ingressAppsList.Populate(namespaces...).Get() if err != nil { logger.Error("An error occurred while looking for hajimari apps", err) render.Render(w, r, ErrServerError(err)) @@ -70,23 +68,15 @@ func (rs *appResource) ListApps(w http.ResponseWriter, r *http.Request) { customApps, err := customAppsList.Populate().Get() if err != nil { - logger.Error("An error occured while populating custom hajimari apps", err) + logger.Error("An error occured while populating custom hajimari apps: ", err) render.Render(w, r, ErrServerError(err)) } - // logger.Info(apps) - // logger.Info(customApps) - // // Append both generated and custom apps - //mergo.Merge(&apps, customApps) - // logger.Info(apps) - - // apps = append(apps, customApps...) - var apps []models.AppGroup - for i, appGroup := range ingressApps { + for i, ingressAppGroup := range ingressApps { for x, customAppGroup := range customApps { - if customAppGroup.Name == appGroup.Name { + if customAppGroup.Group == ingressAppGroup.Group { ingressApps[i].Apps = append(ingressApps[i].Apps, customAppGroup.Apps...) customApps = append(customApps[:x], customApps[x+1:]...) } diff --git a/internal/handlers/bookmarks.go b/internal/handlers/bookmarks.go index 352ddb4a..48437fd3 100644 --- a/internal/handlers/bookmarks.go +++ b/internal/handlers/bookmarks.go @@ -30,27 +30,9 @@ func (rs *bookmarkResource) ListBookmarks(w http.ResponseWriter, r *http.Request return } - defaultBookmarkGroups := appConfig.Groups + globalBookmarks := appConfig.GlobalBookmarks - bookmarkGroups := []models.BookmarkGroup{} - - for _, bookmarkGroup := range defaultBookmarkGroups { - bookmarks := []models.Bookmark{} - - for _, bookmark := range bookmarkGroup.Links { - bookmarks = append(bookmarks, models.Bookmark{ - Name: bookmark.Name, - URL: bookmark.URL, - }) - } - - bookmarkGroups = append(bookmarkGroups, models.BookmarkGroup{ - Name: bookmarkGroup.Name, - Bookmarks: bookmarks, - }) - } - - if err := render.RenderList(w, r, NewBookmarkListResponse(bookmarkGroups)); err != nil { + if err := render.RenderList(w, r, NewBookmarkListResponse(globalBookmarks)); err != nil { render.Render(w, r, ErrServerError(err)) return } diff --git a/internal/handlers/handler.go b/internal/handlers/handler.go index 7cb3165a..db9abcd2 100644 --- a/internal/handlers/handler.go +++ b/internal/handlers/handler.go @@ -10,6 +10,8 @@ import ( "github.com/go-chi/cors" "github.com/go-chi/render" "github.com/toboshii/hajimari/internal/log" + "github.com/toboshii/hajimari/internal/services" + "github.com/toboshii/hajimari/internal/stores" ) var ( @@ -25,9 +27,7 @@ func NewHandler() http.Handler { router.Use(middleware.Recoverer) router.Use(middleware.Timeout(60 * time.Second)) router.Use(cors.Handler(cors.Options{ - // AllowedOrigins: []string{"https://foo.com"}, // Use this to allow specific origin hosts - AllowedOrigins: []string{"https://*", "http://*"}, - // AllowOriginFunc: func(r *http.Request, origin string) bool { return true }, + AllowedOrigins: []string{"https://*", "http://*"}, AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"}, ExposedHeaders: []string{"Link"}, @@ -38,11 +38,12 @@ func NewHandler() http.Handler { router.MethodNotAllowed(methodNotAllowedHandler) router.NotFound(notFoundHandler) - // startpageService := services.NewStartpageService(stores.NewFileStore(), logger) + startpageService := services.NewStartpageService(stores.NewMemoryStore(), logger) - // router.Mount("/", NewStartpageResource(startpageService).StartpageRoutes()) + // router.Mount("/config", NewConfigResource().ConfigRoutes()) router.Mount("/apps", NewAppResource().AppRoutes()) router.Mount("/bookmarks", NewBookmarkResource().BookmarkRoutes()) + router.Mount("/startpage", NewStartpageResource(startpageService).StartpageRoutes()) return router } diff --git a/internal/handlers/startpage.go b/internal/handlers/startpage.go index 23d04515..71114f6a 100644 --- a/internal/handlers/startpage.go +++ b/internal/handlers/startpage.go @@ -1,229 +1,167 @@ package handlers -// import ( -// "context" -// "encoding/json" -// "errors" -// "net/http" -// "time" - -// "github.com/go-chi/chi/v5" -// "github.com/go-chi/render" -// "github.com/toboshii/hajimari/internal/config" -// "github.com/toboshii/hajimari/internal/models" -// "github.com/toboshii/hajimari/internal/services" -// "github.com/toboshii/hajimari/internal/util/tplutil" -// ) - -// type startpageResource struct { -// service services.StartpageService -// } - -// func NewStartpageResource(service services.StartpageService) *startpageResource { -// return &startpageResource{service: service} -// } - -// func (rs *startpageResource) StartpageRoutes() chi.Router { -// router := chi.NewRouter() -// router.Get("/", rs.GetStartpage) -// router.Get("/config", rs.GetDefaultConfig) -// router.Post("/", rs.CreateStartpage) - -// router.Route("/{startpageID}", func(r chi.Router) { -// r.Use(rs.StartpageCtx) -// r.Get("/", rs.GetStartpage) -// r.Get("/config", rs.GetStartpageConfig) -// r.Put("/", rs.UpdateStartpage) -// r.Delete("/", rs.DeleteStartpage) -// }) - -// return router -// } - -// // StartpageCtx middleware is used to load a Startpage object from -// // the URL parameters passed through as the request. In case -// // the Startpage could not be found, we stop here and return a 404. -// func (sr *startpageResource) StartpageCtx(next http.Handler) http.Handler { -// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { -// var startpage *models.Startpage -// var err error - -// if startpageID := chi.URLParam(r, "startpageID"); startpageID != "" { -// startpage, err = sr.service.GetStartpage(startpageID) -// } else { -// http.Error(w, err.Error(), http.StatusNotFound) -// return -// } -// if err != nil { -// render.Render(w, r, ErrNotFound) -// return -// } - -// ctx := context.WithValue(r.Context(), "startpage", startpage) -// next.ServeHTTP(w, r.WithContext(ctx)) -// }) -// } - -// func (sr *startpageResource) GetStartpage(w http.ResponseWriter, r *http.Request) { -// appConfig, err := config.GetConfig() -// if err != nil { -// logger.Error("Failed to read configuration for hajimari", err) -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } - -// if r.Context().Value("startpage") != nil { -// startpage := r.Context().Value("startpage").(*models.Startpage) - -// sr.service.ConvertStartpageToConfig(appConfig, startpage) -// } - -// w.Header().Add("Content-Type", "application/json") - -// js, err := json.Marshal(struct { -// Title string `json:"title"` -// Greeting string `json:"greeting"` -// Date string `json:"date"` -// Groups []config.Group `json:"groups"` -// Providers []config.Provider `json:"providers"` -// Modules []config.Module `json:"modules"` -// }{ -// Title: appConfig.Title, -// Greeting: tplutil.Greet(appConfig.Name, time.Now().Hour()), -// Date: time.Now().Format("Mon, Jan 02"), -// Groups: appConfig.Groups, -// Providers: appConfig.Providers, -// Modules: appConfig.Modules, -// }) -// if err != nil { -// logger.Error("An error occurred while marshalling apps to json: ", err) -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } - -// _, err = w.Write(js) -// if err != nil { -// logger.Error("An error occurred while rendering json to output: ", err) -// http.Error(w, err.Error(), http.StatusInternalServerError) -// } - -// // err = sr.tpl.Execute(w, struct { -// // Title string -// // Greeting string -// // Date string -// // Apps []hajimari.App -// // Groups []config.Group -// // Providers []config.Provider -// // Modules []config.Module -// // }{ -// // Title: appConfig.Title, -// // Greeting: tplutil.Greet(appConfig.Name, time.Now().Hour()), -// // Date: time.Now().Format("Mon, Jan 02"), -// // Apps: hajimariApps, -// // Groups: appConfig.Groups, -// // Providers: appConfig.Providers, -// // Modules: appConfig.Modules, -// // }) - -// // if err != nil { -// // http.Error(w, err.Error(), http.StatusInternalServerError) -// // return -// // } -// } - -// func (sr *startpageResource) GetDefaultConfig(w http.ResponseWriter, r *http.Request) { -// startpage := models.Startpage{} - -// appConfig, err := config.GetConfig() -// if err != nil { -// logger.Error("Failed to read configuration for hajimari", err) -// http.Error(w, err.Error(), http.StatusInternalServerError) -// return -// } - -// sr.service.ConvertConfigToStartpage(appConfig, &startpage) - -// if err := render.Render(w, r, NewStartpageResponse(&startpage)); err != nil { -// render.Render(w, r, ErrServerError(err)) -// return -// } -// } - -// func (sr *startpageResource) GetStartpageConfig(w http.ResponseWriter, r *http.Request) { -// startpage := r.Context().Value("startpage").(*models.Startpage) - -// if err := render.Render(w, r, NewStartpageResponse(startpage)); err != nil { -// render.Render(w, r, ErrServerError(err)) -// return -// } -// } - -// func (sr *startpageResource) CreateStartpage(w http.ResponseWriter, r *http.Request) { -// data := &StartpageRequest{} -// if err := render.Bind(r, data); err != nil { -// render.Render(w, r, ErrInvalidRequest(err)) -// return -// } - -// startpage := data.Startpage -// _, _ = sr.service.NewStartpage(startpage) - -// render.Status(r, http.StatusCreated) -// render.Render(w, r, NewStartpageResponse(startpage)) -// } - -// func (sr *startpageResource) UpdateStartpage(w http.ResponseWriter, r *http.Request) { -// startpage := r.Context().Value("startpage").(*models.Startpage) - -// data := &StartpageRequest{Startpage: startpage} -// if err := render.Bind(r, data); err != nil { -// render.Render(w, r, ErrInvalidRequest(err)) -// return -// } -// startpage = data.Startpage -// _, _ = sr.service.UpdateStartpage(startpage.ID, startpage) - -// render.Render(w, r, NewStartpageResponse(startpage)) -// } - -// func (sr *startpageResource) DeleteStartpage(w http.ResponseWriter, r *http.Request) { -// var err error - -// startpage := r.Context().Value("startpage").(*models.Startpage) - -// startpage, err = sr.service.RemoveStartpage(startpage.ID) -// if err != nil { -// render.Render(w, r, ErrInvalidRequest(err)) -// return -// } - -// render.Render(w, r, NewStartpageResponse(startpage)) -// } - -// type StartpageRequest struct { -// *models.Startpage - -// ProtectedID string `json:"id"` -// } - -// func (s *StartpageRequest) Bind(r *http.Request) error { -// if s.Startpage == nil { -// return errors.New("missing required Startpage fields") -// } - -// return nil -// } - -// type StartpageResponse struct { -// *models.Startpage -// } - -// func NewStartpageResponse(startpage *models.Startpage) *StartpageResponse { -// resp := &StartpageResponse{Startpage: startpage} - -// return resp -// } - -// func (rd *StartpageResponse) Render(w http.ResponseWriter, r *http.Request) error { -// return nil -// } +import ( + "context" + "errors" + "net/http" + + "github.com/go-chi/chi/v5" + "github.com/go-chi/render" + "github.com/toboshii/hajimari/internal/config" + "github.com/toboshii/hajimari/internal/models" + "github.com/toboshii/hajimari/internal/services" +) + +type startpageResource struct { + service services.StartpageService +} + +func NewStartpageResource(service services.StartpageService) *startpageResource { + return &startpageResource{service: service} +} + +func (rs *startpageResource) StartpageRoutes() chi.Router { + router := chi.NewRouter() + router.Get("/", rs.GetDefaultStartpage) + router.Post("/", rs.CreateStartpage) + + router.Route("/{startpageID}", func(r chi.Router) { + r.Use(rs.StartpageCtx) + r.Get("/", rs.GetStartpage) + r.Put("/", rs.UpdateStartpage) + r.Delete("/", rs.DeleteStartpage) + }) + + return router +} + +// StartpageCtx middleware is used to load a Startpage object from +// the URL parameters passed through as the request. In case +// the Startpage could not be found, we stop here and return a 404. +func (sr *startpageResource) StartpageCtx(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var startpage *models.Startpage + var err error + + if startpageID := chi.URLParam(r, "startpageID"); startpageID != "" { + startpage, err = sr.service.GetStartpage(startpageID) + } else { + http.Error(w, err.Error(), http.StatusNotFound) + return + } + if err != nil { + render.Render(w, r, ErrNotFound) + return + } + + ctx := context.WithValue(r.Context(), "startpage", startpage) + next.ServeHTTP(w, r.WithContext(ctx)) + }) +} + +func (sr *startpageResource) GetStartpage(w http.ResponseWriter, r *http.Request) { + startpage := r.Context().Value("startpage").(*models.Startpage) + appConfig, err := config.GetConfig() + if err != nil { + logger.Error("Failed to read configuration for hajimari", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + sr.service.ConvertConfigToStartpage(appConfig, startpage) + + if err := render.Render(w, r, NewStartpageResponse(startpage)); err != nil { + render.Render(w, r, ErrServerError(err)) + return + } +} + +func (sr *startpageResource) GetDefaultStartpage(w http.ResponseWriter, r *http.Request) { + startpage := models.Startpage{} + + appConfig, err := config.GetConfig() + if err != nil { + logger.Error("Failed to read configuration for hajimari", err) + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + sr.service.ConvertConfigToStartpage(appConfig, &startpage) + + startpage.Bookmarks = appConfig.GlobalBookmarks + + if err := render.Render(w, r, NewStartpageResponse(&startpage)); err != nil { + render.Render(w, r, ErrServerError(err)) + return + } +} + +func (sr *startpageResource) CreateStartpage(w http.ResponseWriter, r *http.Request) { + data := &StartpageRequest{} + if err := render.Bind(r, data); err != nil { + render.Render(w, r, ErrInvalidRequest(err)) + return + } + + startpage := data.Startpage + _, _ = sr.service.NewStartpage(startpage) + + render.Status(r, http.StatusCreated) + render.Render(w, r, NewStartpageResponse(startpage)) +} + +func (sr *startpageResource) UpdateStartpage(w http.ResponseWriter, r *http.Request) { + startpage := r.Context().Value("startpage").(*models.Startpage) + + data := &StartpageRequest{Startpage: startpage} + if err := render.Bind(r, data); err != nil { + render.Render(w, r, ErrInvalidRequest(err)) + return + } + startpage = data.Startpage + _, _ = sr.service.UpdateStartpage(startpage.ID, startpage) + + render.Render(w, r, NewStartpageResponse(startpage)) +} + +func (sr *startpageResource) DeleteStartpage(w http.ResponseWriter, r *http.Request) { + var err error + + startpage := r.Context().Value("startpage").(*models.Startpage) + + startpage, err = sr.service.RemoveStartpage(startpage.ID) + if err != nil { + render.Render(w, r, ErrInvalidRequest(err)) + return + } + + render.Render(w, r, NewStartpageResponse(startpage)) +} + +type StartpageRequest struct { + *models.Startpage + + ProtectedID string `json:"id"` +} + +func (s *StartpageRequest) Bind(r *http.Request) error { + if s.Startpage == nil { + return errors.New("missing required Startpage fields") + } + + return nil +} + +type StartpageResponse struct { + *models.Startpage +} + +func NewStartpageResponse(startpage *models.Startpage) *StartpageResponse { + resp := &StartpageResponse{Startpage: startpage} + + return resp +} + +func (rd *StartpageResponse) Render(w http.ResponseWriter, r *http.Request) error { + return nil +} diff --git a/internal/models/app_group.go b/internal/models/app_group.go index 5db0a269..e31ae4f3 100644 --- a/internal/models/app_group.go +++ b/internal/models/app_group.go @@ -1,6 +1,6 @@ package models type AppGroup struct { - Name string `json:"name"` - Apps []App `json:"apps"` + Group string `json:"group"` + Apps []App `json:"apps"` } diff --git a/internal/models/bookmark_group.go b/internal/models/bookmark_group.go index f3dccc8a..e6854a82 100644 --- a/internal/models/bookmark_group.go +++ b/internal/models/bookmark_group.go @@ -1,6 +1,6 @@ package models type BookmarkGroup struct { - Name string `json:"name"` + Group string `json:"group"` Bookmarks []Bookmark `json:"bookmarks"` } diff --git a/internal/models/startpage.go b/internal/models/startpage.go index e2fff408..968b8d08 100644 --- a/internal/models/startpage.go +++ b/internal/models/startpage.go @@ -1,6 +1,15 @@ package models type Startpage struct { - ID string `json:"id,omitempty"` - Name string `json:"name"` + ID string `json:"id,omitempty"` + Name string `json:"name"` + Title string `json:"title"` + Theme string `json:"theme"` + LightTheme string `json:"lightTheme"` + DarkTheme string `json:"darkTheme"` + ShowGreeting *bool `json:"showGreeting"` + ShowAppGroups *bool `json:"showAppGroups"` + ShowBookmarkGroups *bool `json:"showBookmarkGroups"` + ShowGlobalBookmarks *bool `json:"showGlobalBookmarks"` + Bookmarks []BookmarkGroup `json:"bookmarks"` } diff --git a/internal/services/startpage.go b/internal/services/startpage.go index 1366fd90..df008c2b 100644 --- a/internal/services/startpage.go +++ b/internal/services/startpage.go @@ -1,82 +1,89 @@ package services -// import ( -// "github.com/sirupsen/logrus" -// "github.com/toboshii/hajimari/internal/config" -// "github.com/toboshii/hajimari/internal/models" -// "github.com/toboshii/hajimari/internal/stores" -// ) - -// type StartpageService interface { -// NewStartpage(startpage *models.Startpage) (string, error) -// GetStartpage(id string) (*models.Startpage, error) -// UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) -// RemoveStartpage(id string) (*models.Startpage, error) -// ConvertStartpageToConfig(appConfig *config.Config, startpage *models.Startpage) -// ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) -// } - -// type startpageService struct { -// store stores.StartpageStore -// logger *logrus.Logger -// } - -// func NewStartpageService(store stores.StartpageStore, logger *logrus.Logger) *startpageService { -// return &startpageService{store: store, logger: logger} -// } - -// func (s *startpageService) NewStartpage(startpage *models.Startpage) (string, error) { -// return s.store.NewStartpage(startpage) -// } - -// func (s *startpageService) GetStartpage(id string) (*models.Startpage, error) { -// log := s.logger.WithFields(logrus.Fields{ -// "startpageId": id, -// }) -// log.Info("GetStartpage") -// return s.store.GetStartpage(id) -// } - -// func (s *startpageService) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { -// return s.store.UpdateStartpage(id, startpage) -// } - -// func (s *startpageService) RemoveStartpage(id string) (*models.Startpage, error) { -// return s.store.RemoveStartpage(id) -// } - -// func (s *startpageService) ConvertStartpageToConfig(appConfig *config.Config, startpage *models.Startpage) { -// appConfig.Name = startpage.Name -// appConfig.Groups = []config.Group{} - -// for _, g := range startpage.Groups { -// links := []config.Link{} - -// for _, l := range g.Links { -// links = append(links, config.Link(l)) -// } - -// appConfig.Groups = append(appConfig.Groups, config.Group{ -// Name: g.Name, -// Links: links, -// }) -// } -// } - -// func (s *startpageService) ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) { -// startpage.Name = appConfig.Name -// startpage.Groups = []models.Group{} - -// for _, g := range appConfig.Groups { -// links := []models.Link{} - -// for _, l := range g.Links { -// links = append(links, models.Link(l)) -// } - -// startpage.Groups = append(startpage.Groups, models.Group{ -// Name: g.Name, -// Links: links, -// }) -// } -// } +import ( + "encoding/json" + + "github.com/sirupsen/logrus" + "github.com/toboshii/hajimari/internal/config" + "github.com/toboshii/hajimari/internal/log" + "github.com/toboshii/hajimari/internal/models" + "github.com/toboshii/hajimari/internal/stores" +) + +var ( + logger = log.New() +) + +type StartpageService interface { + NewStartpage(startpage *models.Startpage) (string, error) + GetStartpage(id string) (*models.Startpage, error) + UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) + RemoveStartpage(id string) (*models.Startpage, error) + ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) +} + +type startpageService struct { + store stores.StartpageStore + logger *logrus.Logger +} + +func NewStartpageService(store stores.StartpageStore, logger *logrus.Logger) *startpageService { + return &startpageService{store: store, logger: logger} +} + +func (s *startpageService) NewStartpage(startpage *models.Startpage) (string, error) { + return s.store.NewStartpage(startpage) +} + +func (s *startpageService) GetStartpage(id string) (*models.Startpage, error) { + return s.store.GetStartpage(id) +} + +func (s *startpageService) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { + return s.store.UpdateStartpage(id, startpage) +} + +func (s *startpageService) RemoveStartpage(id string) (*models.Startpage, error) { + return s.store.RemoveStartpage(id) +} + +func (s *startpageService) ConvertConfigToStartpage(appConfig *config.Config, startpage *models.Startpage) { + var configInterface map[string]interface{} + var startpageInterface map[string]interface{} + + configJson, _ := json.Marshal(appConfig) + json.Unmarshal(configJson, &configInterface) + + startpageJson, _ := json.Marshal(startpage) + json.Unmarshal(startpageJson, &startpageInterface) + + for k, v := range startpageInterface { + switch v := v.(type) { + case string: + if v == "" && startpageInterface[k] != configInterface[k] { + startpageInterface[k] = configInterface[k] + } + case int: + if v == 0 && startpageInterface[k] != configInterface[k] { + startpageInterface[k] = configInterface[k] + } + case nil: + startpageInterface[k] = configInterface[k] + } + } + + mergedJson, _ := json.Marshal(startpageInterface) + json.Unmarshal(mergedJson, &startpage) + + // // TODO: make this inherit defaults from global config + // startpage.Name = appConfig.Name + // startpage.Title = appConfig.Title + // startpage.Theme = appConfig.Theme + // startpage.LightTheme = appConfig.LightTheme + // startpage.DarkTheme = appConfig.DarkTheme + // startpage.Bookmarks = appConfig.GlobalBookmarks + // startpage.ShowGreeting = appConfig.ShowGreeting + // startpage.ShowAppGroups = appConfig.ShowAppGroups + // startpage.ShowBookmarkGroups = appConfig.ShowBookmarkGroups + // startpage.ShowGlobalBookmarks = false +} diff --git a/internal/stores/memory.go b/internal/stores/memory.go index 598ae3d0..b400bab0 100644 --- a/internal/stores/memory.go +++ b/internal/stores/memory.go @@ -1,90 +1,92 @@ package stores -// import ( -// "errors" +import ( + "errors" -// gonanoid "github.com/matoous/go-nanoid/v2" -// "github.com/toboshii/hajimari/internal/models" -// ) + gonanoid "github.com/matoous/go-nanoid/v2" + "github.com/toboshii/hajimari/internal/models" + "github.com/toboshii/hajimari/internal/util/pointer" +) -// var startpages = []*models.Startpage{ -// { -// ID: "108ZTGB77K09P4QJfu4vG", -// Name: "Adam", -// Groups: []models.Group{ -// { -// Name: "Media", -// Links: []models.Link{ -// { -// Name: "Youtube", -// URL: "https://youtube.com", -// }, -// { -// Name: "Netflix", -// URL: "https://netflix.com", -// }, -// }, -// }, -// { -// Name: "Code", -// Links: []models.Link{ -// { -// Name: "Github", -// URL: "https://github.com", -// }, -// }, -// }, -// }, -// }, -// {ID: "r1NqSpS1C0z3cMHyzX-Y5", Name: "Bob"}, -// {ID: "NmcvYTdRozUDNpbjAxFTO", Name: "Carol"}, -// {ID: "3OG1X_GuRS_TrCcWb5YjK", Name: "Derrick"}, -// {ID: "Qq4EF6MaSKaYZpEldtLTn", Name: "Emily"}, -// } +var startpages = []*models.Startpage{ + { + ID: "108ZTGB77K09P4QJfu4vG", + Name: "Adam", + ShowBookmarkGroups: pointer.Of(true), + Bookmarks: []models.BookmarkGroup{ + { + Group: "Media", + Bookmarks: []models.Bookmark{ + { + Name: "Youtube", + URL: "https://youtube.com", + }, + { + Name: "Netflix", + URL: "https://netflix.com", + }, + }, + }, + { + Group: "Code", + Bookmarks: []models.Bookmark{ + { + Name: "Github", + URL: "https://github.com", + }, + }, + }, + }, + }, + {ID: "r1NqSpS1C0z3cMHyzX-Y5", Name: "Bob"}, + {ID: "NmcvYTdRozUDNpbjAxFTO", Name: "Carol"}, + {ID: "3OG1X_GuRS_TrCcWb5YjK", Name: "Derrick"}, + {ID: "Qq4EF6MaSKaYZpEldtLTn", Name: "Emily"}, +} -// type memoryStore struct { -// StartpageStore -// } +type memoryStore struct { + StartpageStore +} -// func NewMemoryStore() StartpageStore { -// return &memoryStore{} -// } +func NewMemoryStore() StartpageStore { + return &memoryStore{} +} -// func (s *memoryStore) NewStartpage(startpage *models.Startpage) (string, error) { -// id, err := gonanoid.New() -// if err != nil { -// return "", err -// } -// startpage.ID = id -// startpages = append(startpages, startpage) -// return startpage.ID, nil -// } +func (s *memoryStore) NewStartpage(startpage *models.Startpage) (string, error) { + id, err := gonanoid.New() + if err != nil { + return "", err + } + startpage.ID = id + startpages = append(startpages, startpage) + return startpage.ID, nil +} -// func (s *memoryStore) GetStartpage(id string) (*models.Startpage, error) { -// for _, s := range startpages { -// if s.ID == id { -// return s, nil -// } -// } -// return nil, errors.New("startpage not found") -// } +func (s *memoryStore) GetStartpage(id string) (*models.Startpage, error) { + for _, s := range startpages { + if s.ID == id { + return s, nil + } + } + return nil, errors.New("startpage not found") +} -// func (s *memoryStore) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { -// for i, s := range startpages { -// if s.ID == id { -// startpages[i] = startpage -// return startpage, nil -// } -// } -// return nil, errors.New("startpage not found") -// } +func (s *memoryStore) UpdateStartpage(id string, startpage *models.Startpage) (*models.Startpage, error) { + for i, s := range startpages { + if s.ID == id { + startpages[i] = startpage + return startpage, nil + } + } + return nil, errors.New("startpage not found") +} -// func (s *memoryStore) RemoveStartpage(id string) (*models.Startpage, error) { -// for i, s := range startpages { -// if s.ID == id { -// startpages = append((startpages)[:i], (startpages)[i+1:]...) -// return s, nil -// } -// } -// return nil, errors.New("startpage not found") -// } +func (s *memoryStore) RemoveStartpage(id string) (*models.Startpage, error) { + for i, s := range startpages { + if s.ID == id { + startpages = append((startpages)[:i], (startpages)[i+1:]...) + return s, nil + } + } + return nil, errors.New("startpage not found") +} diff --git a/internal/util/pointer/pointer.go b/internal/util/pointer/pointer.go new file mode 100644 index 00000000..66d90c72 --- /dev/null +++ b/internal/util/pointer/pointer.go @@ -0,0 +1,5 @@ +package pointer + +func Of[Value any](v Value) *Value { + return &v +} diff --git a/internal/util/tplutil/tplutil.go b/internal/util/tplutil/tplutil.go deleted file mode 100644 index a1a6a42b..00000000 --- a/internal/util/tplutil/tplutil.go +++ /dev/null @@ -1,23 +0,0 @@ -package tplutil - -import "fmt" - -// greet returns the greeting to be used in the h1 heading -func Greet(name string, currentHour int) (greet string) { - switch currentHour / 6 { - case 0: - greet = "Good night" - case 1: - greet = "Good morning" - case 2: - greet = "Good afternoon" - default: - greet = "Good evening" - } - - if name != "" { - return fmt.Sprintf("%s, %s!", greet, name) - } - - return fmt.Sprintf("%s!", greet) -} From 000298fa495b9bd5735d0323e80966bfa7d5308e Mon Sep 17 00:00:00 2001 From: Toboshii Nakama <63410334+toboshii@users.noreply.github.com> Date: Mon, 29 Aug 2022 11:14:07 -0500 Subject: [PATCH 14/46] refactor: remove completed todo --- internal/services/startpage.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/internal/services/startpage.go b/internal/services/startpage.go index df008c2b..463e50c3 100644 --- a/internal/services/startpage.go +++ b/internal/services/startpage.go @@ -74,16 +74,4 @@ func (s *startpageService) ConvertConfigToStartpage(appConfig *config.Config, st mergedJson, _ := json.Marshal(startpageInterface) json.Unmarshal(mergedJson, &startpage) - - // // TODO: make this inherit defaults from global config - // startpage.Name = appConfig.Name - // startpage.Title = appConfig.Title - // startpage.Theme = appConfig.Theme - // startpage.LightTheme = appConfig.LightTheme - // startpage.DarkTheme = appConfig.DarkTheme - // startpage.Bookmarks = appConfig.GlobalBookmarks - // startpage.ShowGreeting = appConfig.ShowGreeting - // startpage.ShowAppGroups = appConfig.ShowAppGroups - // startpage.ShowBookmarkGroups = appConfig.ShowBookmarkGroups - // startpage.ShowGlobalBookmarks = false } From 71d4b2e124205d0443362be7b9cdece8a306bce4 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Tue, 30 Aug 2022 22:57:28 -0400 Subject: [PATCH 15/46] More merging --- internal/hajimari/hajimari.go | 10 -- internal/hajimari/ingressapps/apps.go | 51 +++----- internal/models/app.go | 7 +- internal/modules/utils.go | 28 ----- internal/modules/weather.go | 34 ------ internal/util/tplutil/tplutil.go | 31 ----- internal/util/tplutil/tplutil_test.go | 72 +++++------ main.go | 48 -------- web/static/js/themer.js | 165 -------------------------- web/template/index.html.tmpl | 144 ---------------------- 10 files changed, 58 insertions(+), 532 deletions(-) delete mode 100644 internal/hajimari/hajimari.go delete mode 100644 internal/modules/utils.go delete mode 100644 internal/modules/weather.go delete mode 100644 internal/util/tplutil/tplutil.go delete mode 100644 main.go delete mode 100755 web/static/js/themer.js delete mode 100644 web/template/index.html.tmpl diff --git a/internal/hajimari/hajimari.go b/internal/hajimari/hajimari.go deleted file mode 100644 index 01b3d0c0..00000000 --- a/internal/hajimari/hajimari.go +++ /dev/null @@ -1,10 +0,0 @@ -package hajimari - -// App struct that contains information about an app that is enabled in hajimari -type App struct { - Name string - Icon string - Group string - URL string - Status string -} diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index 8f2c10fc..79cccf64 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -7,12 +7,8 @@ import ( "github.com/toboshii/hajimari/internal/kube/util" "github.com/toboshii/hajimari/internal/kube/wrappers" "github.com/toboshii/hajimari/internal/log" -<<<<<<< HEAD - v1 "k8s.io/api/networking/v1" -======= + "k8s.io/api/networking/v1" "github.com/toboshii/hajimari/internal/models" - "k8s.io/api/extensions/v1beta1" ->>>>>>> 97467966a4db33a45732f6f5d967b7ec5cb7a754 "k8s.io/client-go/kubernetes" ) @@ -62,34 +58,14 @@ func (al *List) Get() ([]models.AppGroup, error) { return al.items, al.err } -<<<<<<< HEAD -func convertIngressesToHajimariApps(ingresses []v1.Ingress, ssg util.StatusGetter) (apps []hajimari.App) { -======= -func convertIngressesToHajimariApps(ingresses []v1beta1.Ingress) (appGroups []models.AppGroup) { ->>>>>>> 97467966a4db33a45732f6f5d967b7ec5cb7a754 + +func convertIngressesToHajimariApps(ingresses []v1.Ingress , ssg util.StatusGetter) (appGroups []models.AppGroup) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) status := ssg.GetDeploymentStatus(ingress).Get() var emptyStatus string = "undefined" wrapper := wrappers.NewIngressWrapper(&ingress) -<<<<<<< HEAD - if wrapper.GetStatusCheckEnabled() && len(status)>0 { - apps = append(apps, hajimari.App{ - Name: wrapper.GetName(), - Group: wrapper.GetGroup(), - Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), - URL: wrapper.GetURL(), - Status: status, - }) - } else { - apps = append(apps, hajimari.App{ - Name: wrapper.GetName(), - Group: wrapper.GetGroup(), - Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), - URL: wrapper.GetURL(), - Status: emptyStatus, -======= groupMap := make(map[string]int, len(appGroups)) for i, v := range appGroups { @@ -108,12 +84,21 @@ func convertIngressesToHajimariApps(ingresses []v1beta1.Ingress) (appGroups []mo } if i, ok := appMap[wrapper.GetGroup()]; ok { - appGroups[i].Apps = append(appGroups[i].Apps, models.App{ - Name: wrapper.GetName(), - Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), - URL: wrapper.GetURL(), ->>>>>>> 97467966a4db33a45732f6f5d967b7ec5cb7a754 - }) + if wrapper.GetStatusCheckEnabled() && len(status)>0 { + appGroups[i].Apps = append(appGroups[i].Apps, models.App{ + Name: wrapper.GetName(), + Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), + URL: wrapper.GetURL(), + Status: status, + }) + } else { + appGroups[i].Apps = append(appGroups[i].Apps, models.App{ + Name: wrapper.GetName(), + Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), + URL: wrapper.GetURL(), + Status: emptyStatus, + }) + } } } diff --git a/internal/models/app.go b/internal/models/app.go index 9c545518..821e70d4 100644 --- a/internal/models/app.go +++ b/internal/models/app.go @@ -1,7 +1,8 @@ package models type App struct { - Name string `json:"name"` - Icon string `json:"icon"` - URL string `json:"url"` + Name string `json:"name"` + Icon string `json:"icon"` + URL string `json:"url"` + Status string `json:"status"` } diff --git a/internal/modules/utils.go b/internal/modules/utils.go deleted file mode 100644 index 3c7940e1..00000000 --- a/internal/modules/utils.go +++ /dev/null @@ -1,28 +0,0 @@ -package modules - -import ( - "fmt" - "io" - "net/http" - "time" -) - -func updatedAt() string { - return fmt.Sprintf("(Last update at %s)", time.Now().Format("15:04")) -} - -func actualFetch(url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - return body, nil -} diff --git a/internal/modules/weather.go b/internal/modules/weather.go deleted file mode 100644 index 9f7f998b..00000000 --- a/internal/modules/weather.go +++ /dev/null @@ -1,34 +0,0 @@ -package modules - -import ( - "fmt" - - "github.com/tidwall/gjson" - "github.com/toboshii/hajimari/internal/log" -) - -var ( - logger = log.New() -) - -// GetWeather fetches weather information from http://wttr.in -func GetWeather(data map[string]string) string { - body, err := fetchWeather("http://wttr.in/" + data["city"] + "?format=j1") - if err != nil { - return "" - } - - info := gjson.GetManyBytes(body, "current_condition.0.temp_F", "current_condition.0.weatherDesc.0.value") - if info[0].String() == "" || info[1].String() == "" { - return "" - } - - return fmt.Sprintf("Temperature in %s: %s degrees, current condition is: %s %s", - data["city"], - info[0].String(), - info[1].String(), - updatedAt(), - ) -} - -var fetchWeather = actualFetch diff --git a/internal/util/tplutil/tplutil.go b/internal/util/tplutil/tplutil.go deleted file mode 100644 index ae52a92b..00000000 --- a/internal/util/tplutil/tplutil.go +++ /dev/null @@ -1,31 +0,0 @@ -package tplutil - -import ( - "fmt" - "github.com/toboshii/hajimari/internal/hajimari" -) - -// greet returns the greeting to be used in the h1 heading -func Greet(name string, currentHour int) (greet string) { - switch currentHour / 6 { - case 0: - greet = "Good night" - case 1: - greet = "Good morning" - case 2: - greet = "Good afternoon" - default: - greet = "Good evening" - } - - if name != "" { - return fmt.Sprintf("%s, %s!", greet, name) - } - - return fmt.Sprintf("%s!", greet) -} - -// Checks if status is null indicating disabled status check -func IsStatusCheckEnabled(app hajimari.App) bool { - return app.Status != "undefined" -} diff --git a/internal/util/tplutil/tplutil_test.go b/internal/util/tplutil/tplutil_test.go index b3ca7558..a684e915 100644 --- a/internal/util/tplutil/tplutil_test.go +++ b/internal/util/tplutil/tplutil_test.go @@ -1,41 +1,41 @@ -package tplutil +// package tplutil -import ( - "testing" - "github.com/toboshii/hajimari/internal/hajimari" -) +// import ( +// "testing" +// "github.com/toboshii/hajimari/internal/hajimari" +// ) -// IsStatusCheckEnabled works when Status is set -func TestIsStatusCheckEnabled(t *testing.T) { - status := "true" - app := hajimari.App { - Name : "myApp", - Icon : "mdi:flower", - Group : "myGroup", - URL : "www", - Status : status, - } - want := true - check := IsStatusCheckEnabled(app) +// // IsStatusCheckEnabled works when Status is set +// func TestIsStatusCheckEnabled(t *testing.T) { +// status := "true" +// app := hajimari.App { +// Name : "myApp", +// Icon : "mdi:flower", +// Group : "myGroup", +// URL : "www", +// Status : status, +// } +// want := true +// check := IsStatusCheckEnabled(app) - if want != check { - t.Fail() - } -} +// if want != check { +// t.Fail() +// } +// } -// IsStatusCheckEnabled works when Status is not set -func TestIsStatusCheckEnabledOnEmpty(t *testing.T) { - app := hajimari.App { - Name : "myApp", - Icon : "mdi:flower", - Group : "myGroup", - URL : "www", - Status: "undefined", - } - want := false - check := IsStatusCheckEnabled(app) +// // IsStatusCheckEnabled works when Status is not set +// func TestIsStatusCheckEnabledOnEmpty(t *testing.T) { +// app := hajimari.App { +// Name : "myApp", +// Icon : "mdi:flower", +// Group : "myGroup", +// URL : "www", +// Status: "undefined", +// } +// want := false +// check := IsStatusCheckEnabled(app) - if want != check { - t.Fail() - } -} +// if want != check { +// t.Fail() +// } +// } diff --git a/main.go b/main.go deleted file mode 100644 index 861f85b4..00000000 --- a/main.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "errors" - "net/http" - - "github.com/spf13/viper" - "github.com/toboshii/hajimari/internal/handlers" - "github.com/toboshii/hajimari/internal/log" -) - -var ( - logger = log.New() -) - -func init() { - viper.SetConfigName("config") // name of config file (without extension) - viper.AddConfigPath("/config") // path to look for the config file in - viper.AddConfigPath("$HOME/.hajimari") // call multiple times to add many search paths - viper.AddConfigPath(".") // optionally look for config in the working directory - viper.AutomaticEnv() - err := viper.ReadInConfig() // Find and read the config file - if err != nil { // Handle errors reading the config file - panic(errors.New("Fatal error config file: " + err.Error())) - } -} - -// //go:embed web/template -// var indexHTML embed.FS - -// //go:embed web/static -// var staticFiles embed.FS - -// var tpl = template.Must(template.ParseFS(indexHTML, "web/template/index.html.tmpl")) - -func main() { - - // appConfig, err := config.GetConfig() - // if err != nil { - // logger.Fatal("Failed to read configuration for hajimari", err) - // return - // } - - httpHandler := handlers.NewHandler() - - logger.Printf("Listening on :%d\n", 3000) - logger.Fatal(http.ListenAndServe(":3000", httpHandler)) -} diff --git a/web/static/js/themer.js b/web/static/js/themer.js deleted file mode 100755 index 5935e1c5..00000000 --- a/web/static/js/themer.js +++ /dev/null @@ -1,165 +0,0 @@ -const setValue = (property, value) => { - if (value) { - document.documentElement.style.setProperty(`--${property}`, value); - - const input = document.querySelector(`#${property}`); - if (input) { - value = value.replace('px', ''); - input.value = value; - } - } -}; - -const setValueFromLocalStorage = property => { - let value = localStorage.getItem(property); - setValue(property, value); -}; - -const setTheme = options => { - for (let option of Object.keys(options)) { - const property = option; - const value = options[option]; - - setValue(property, value); - localStorage.setItem(property, value); - } -} - -document.addEventListener('DOMContentLoaded', () => { - setValueFromLocalStorage('color-background'); - setValueFromLocalStorage('color-text-pri'); - setValueFromLocalStorage('color-text-acc'); - setValueFromLocalStorage('color-status-online'); - setValueFromLocalStorage('color-status-offline'); -}); - -const dataThemeButtons = document.querySelectorAll('[data-theme]'); - -for (let i = 0; i < dataThemeButtons.length; i++) { - dataThemeButtons[i].addEventListener('click', () => { - const theme = dataThemeButtons[i].dataset.theme; - - switch (theme) { - case 'blackboard': - setTheme({ - 'color-background': '#1a1a1a', - 'color-text-pri': '#FFFDEA', - 'color-text-acc': '#5c5c5c', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'gazette': - setTheme({ - 'color-background': '#F2F7FF', - 'color-text-pri': '#000000', - 'color-text-acc': '#5c5c5c', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'espresso': - setTheme({ - 'color-background': '#21211F', - 'color-text-pri': '#D1B59A', - 'color-text-acc': '#4E4E4E', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'cab': - setTheme({ - 'color-background': '#F6D305', - 'color-text-pri': '#1F1F1F', - 'color-text-acc': '#424242', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'cloud': - setTheme({ - 'color-background': '#f1f2f0', - 'color-text-pri': '#35342f', - 'color-text-acc': '#37bbe4', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'lime': - setTheme({ - 'color-background': '#263238', - 'color-text-pri': '#AABBC3', - 'color-text-acc': '#aeea00', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'white': - setTheme({ - 'color-background': '#ffffff', - 'color-text-pri': '#222222', - 'color-text-acc': '#dddddd', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'tron': - setTheme({ - 'color-background': '#242B33', - 'color-text-pri': '#EFFBFF', - 'color-text-acc': '#6EE2FF', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'blues': - setTheme({ - 'color-background': '#2B2C56', - 'color-text-pri': '#EFF1FC', - 'color-text-acc': '#6677EB', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'passion': - setTheme({ - 'color-background': '#f5f5f5', - 'color-text-pri': '#12005e', - 'color-text-acc': '#8e24aa', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'chalk': - setTheme({ - 'color-background': '#263238', - 'color-text-pri': '#AABBC3', - 'color-text-acc': '#FF869A', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - case 'paper': - setTheme({ - 'color-background': '#F8F6F1', - 'color-text-pri': '#4C432E', - 'color-text-acc': '#AA9A73', - 'color-status-online': '#00FF00', - 'color-status-offline': '#FF0000' - }); - return; - - } - }) -} diff --git a/web/template/index.html.tmpl b/web/template/index.html.tmpl deleted file mode 100644 index a380c5ff..00000000 --- a/web/template/index.html.tmpl +++ /dev/null @@ -1,144 +0,0 @@ - - - - {{or .Title "Hajimari"}} - - - - - - - - - - - - - - - - -
- - - - - - -
-

Applications

-
- {{range .Apps}} -
-
- - {{if ne .Status "undefined"}} -
- {{end}} -
-
- {{.Name}} - {{.URL}} -
-
- {{end}} -
-
- - -
- - - - - - - - - - - - - - - - From 4ac19495be51a6635e909836c6501a149c3d5fd7 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Tue, 30 Aug 2022 22:59:06 -0400 Subject: [PATCH 16/46] remove files to match --- internal/util/tplutil/tplfuncmap.go | 12 -------- internal/util/tplutil/tplutil_test.go | 41 --------------------------- 2 files changed, 53 deletions(-) delete mode 100644 internal/util/tplutil/tplfuncmap.go delete mode 100644 internal/util/tplutil/tplutil_test.go diff --git a/internal/util/tplutil/tplfuncmap.go b/internal/util/tplutil/tplfuncmap.go deleted file mode 100644 index d77e0070..00000000 --- a/internal/util/tplutil/tplfuncmap.go +++ /dev/null @@ -1,12 +0,0 @@ -package tplutil - -import ( - "text/template" -) - -// Map of Utility functions for use in the template -var ( - TplfuncMap = template.FuncMap { - "deref": func(s *string) string{ return *s }, - } -) diff --git a/internal/util/tplutil/tplutil_test.go b/internal/util/tplutil/tplutil_test.go deleted file mode 100644 index a684e915..00000000 --- a/internal/util/tplutil/tplutil_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// package tplutil - -// import ( -// "testing" -// "github.com/toboshii/hajimari/internal/hajimari" -// ) - -// // IsStatusCheckEnabled works when Status is set -// func TestIsStatusCheckEnabled(t *testing.T) { -// status := "true" -// app := hajimari.App { -// Name : "myApp", -// Icon : "mdi:flower", -// Group : "myGroup", -// URL : "www", -// Status : status, -// } -// want := true -// check := IsStatusCheckEnabled(app) - -// if want != check { -// t.Fail() -// } -// } - -// // IsStatusCheckEnabled works when Status is not set -// func TestIsStatusCheckEnabledOnEmpty(t *testing.T) { -// app := hajimari.App { -// Name : "myApp", -// Icon : "mdi:flower", -// Group : "myGroup", -// URL : "www", -// Status: "undefined", -// } -// want := false -// check := IsStatusCheckEnabled(app) - -// if want != check { -// t.Fail() -// } -// } From 8ffc08fca4026c94713f86616a53d79ec20ed103 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Tue, 30 Aug 2022 23:09:36 -0400 Subject: [PATCH 17/46] Add missing updates --- .air.toml | 4 +- Dockerfile | 4 +- cmd/hajimari/main.go | 59 +++++++++ go.mod | 73 +++++++++-- go.sum | 289 ++++++++++++++++++++----------------------- 5 files changed, 261 insertions(+), 168 deletions(-) create mode 100644 cmd/hajimari/main.go diff --git a/.air.toml b/.air.toml index d5ee9275..334744b8 100644 --- a/.air.toml +++ b/.air.toml @@ -2,8 +2,8 @@ root = "." tmp_dir = "tmp" [build] - bin = "./tmp/main" - cmd = "go build -o ./tmp/main ." + bin = "./tmp/hajimari" + cmd = "go build -o ./tmp/hajimari ./cmd/hajimari/main.go" delay = 1000 exclude_dir = ["web", "docs", "charts", "tmp", "vendor"] exclude_file = [] diff --git a/Dockerfile b/Dockerfile index 40feba34..38dfc827 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.16-alpine as build +FROM golang:1.19-alpine as build ARG TARGETPLATFORM ENV TARGETPLATFORM=${TARGETPLATFORM:-linux/amd64} @@ -23,7 +23,7 @@ RUN \ && \ chmod +x hajimari -FROM alpine:3.14 +FROM alpine:3.16 RUN \ apk add --no-cache \ diff --git a/cmd/hajimari/main.go b/cmd/hajimari/main.go new file mode 100644 index 00000000..66d7fad2 --- /dev/null +++ b/cmd/hajimari/main.go @@ -0,0 +1,59 @@ +package main + +import ( + "errors" + "net/http" + + "github.com/fsnotify/fsnotify" + "github.com/spf13/viper" + "github.com/toboshii/hajimari/internal/handlers" + "github.com/toboshii/hajimari/internal/log" +) + +var ( + logger = log.New() +) + +func init() { + viper.SetConfigName("config") // name of config file (without extension) + viper.AddConfigPath("/config") // path to look for the config file in + viper.AddConfigPath("$HOME/.hajimari") // call multiple times to add many search paths + viper.AddConfigPath(".") // optionally look for config in the working directory + viper.AutomaticEnv() + + err := viper.ReadInConfig() // Find and read the config file + + if err != nil { // Handle errors reading the config file + panic(errors.New("Fatal error config file: " + err.Error())) + } + + logger.Info("Using config file: ", viper.ConfigFileUsed()) + + viper.OnConfigChange(func(e fsnotify.Event) { + logger.Info("Reloading config: ", e.Name) + }) + + viper.WatchConfig() +} + +// //go:embed web/template +// var indexHTML embed.FS + +// //go:embed web/static +// var staticFiles embed.FS + +// var tpl = template.Must(template.ParseFS(indexHTML, "web/template/index.html.tmpl")) + +func main() { + + // appConfig, err := config.GetConfig() + // if err != nil { + // logger.Fatal("Failed to read configuration for hajimari", err) + // return + // } + + httpHandler := handlers.NewHandler() + + logger.Printf("Listening on :%d\n", 3000) + logger.Fatal(http.ListenAndServe(":3000", httpHandler)) +} diff --git a/go.mod b/go.mod index f63a3a3f..83dacded 100644 --- a/go.mod +++ b/go.mod @@ -1,20 +1,71 @@ module github.com/toboshii/hajimari -go 1.16 +go 1.19 require ( github.com/chi-middleware/logrus-logger v0.2.0 + github.com/fsnotify/fsnotify v1.5.4 github.com/go-chi/chi v1.5.4 - github.com/go-chi/chi/v5 v5.0.3 - github.com/go-chi/cors v1.2.0 - github.com/go-chi/render v1.0.1 + github.com/go-chi/chi/v5 v5.0.7 + github.com/go-chi/cors v1.2.1 + github.com/go-chi/render v1.0.2 github.com/matoous/go-nanoid/v2 v2.0.0 github.com/onrik/logrus v0.9.0 - github.com/sirupsen/logrus v1.8.1 - github.com/spf13/viper v1.8.1 - github.com/tidwall/gjson v1.8.1 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b - k8s.io/api v0.22.0 - k8s.io/apimachinery v0.22.0 - k8s.io/client-go v0.22.0 + github.com/sirupsen/logrus v1.9.0 + github.com/spf13/viper v1.12.0 + gopkg.in/yaml.v3 v3.0.1 + k8s.io/api v0.24.4 + k8s.io/apimachinery v0.24.4 + k8s.io/client-go v0.24.4 +) + +require ( + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/ajg/form v1.5.1 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emicklei/go-restful v2.9.5+incompatible // indirect + github.com/go-logr/logr v1.2.0 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.5 // indirect + github.com/go-openapi/swag v0.19.14 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/imdario/mergo v0.3.5 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/magiconair/properties v1.8.6 // indirect + github.com/mailru/easyjson v0.7.6 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.1 // indirect + github.com/spf13/afero v1.8.2 // indirect + github.com/spf13/cast v1.5.0 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.3.0 // indirect + github.com/tidwall/gjson v1.14.3 // indirect + golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect + golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.28.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/ini.v1 v1.66.4 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/klog/v2 v2.60.1 // indirect + k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect + k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect + sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index 78c47ee6..f0d8c478 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT 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= @@ -15,6 +16,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY 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= @@ -26,7 +28,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 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.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= 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= @@ -36,6 +37,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo 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/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= @@ -47,15 +49,14 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp 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/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chi-middleware/logrus-logger v0.2.0 h1:Do3vcVSRsLh7zSRKxsVg5Kr5//rTqytwprCR1HzVqT8= github.com/chi-middleware/logrus-logger v0.2.0/go.mod h1:ie/rvKsXrtqqsnJd3qtSEnLxgCs1I758WYmHdv6CRt0= @@ -66,8 +67,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk 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/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= @@ -75,40 +74,49 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 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/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= -github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE= -github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= -github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= -github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= +github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8= +github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= +github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= +github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg= +github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= 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-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= +github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -145,6 +153,8 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu 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/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= 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= @@ -155,8 +165,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -172,138 +182,107 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf 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/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/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/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 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.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/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/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 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/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= +github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 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/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= github.com/matoous/go-nanoid/v2 v2.0.0 h1:d19kur2QuLeHmJBkvYkFdhFBzLoo1XVm2GgTpL+9Tj0= github.com/matoous/go-nanoid/v2 v2.0.0/go.mod h1:FtS4aGPVfEkxKxhdWPAspZpZSh1cOjtM7Ej/So3hR0g= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onrik/logrus v0.9.0 h1:oT7VstCUxWBoX7fswYK61fi9bzRBSpROq5CR2b7wxQo= github.com/onrik/logrus v0.9.0/go.mod h1:qfe9NeZVAJfIxviw3cYkZo3kvBtLoPRJriAO8zl7qTk= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -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/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/afero v1.8.2 h1:xehSyVa0YnHWsJ49JFljMpg1HX19V6NDZ1fkm1Xznbo= +github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= +github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.12.0 h1:CZ7eSOd3kZoaYDLbXnmzgQI5RlciuXBMA+18HwHRfZQ= +github.com/spf13/viper v1.12.0/go.mod h1:b6COn30jlNxbm/V2IqWiNWkJ+vZNiMNksliPCiuKtSI= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -311,24 +290,22 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.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 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU= -github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= -github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= -github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= -github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.3.0 h1:mjC+YW8QpAdXibNi+vNWgzmgBH4+5l5dCXv8cNysBLI= +github.com/subosito/gotenv v1.3.0/go.mod h1:YzJjq/33h7nrwdY+iHMhEOEEbW0ovIz0tB6t6PwAXzs= +github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw= +github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 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= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= 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= @@ -336,18 +313,15 @@ 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.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/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-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= 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= @@ -371,7 +345,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu 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= @@ -386,8 +359,6 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/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= @@ -418,12 +389,15 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY 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-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/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-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y= +golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 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= @@ -435,8 +409,9 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ 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-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/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-20220411215720-9780585627b5 h1:OSnWWcOd/CtWQC2cYSBgbTSJv3ciqd8r54ySIW2y3RE= +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= @@ -448,10 +423,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ 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/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-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -488,20 +461,24 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w 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-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-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/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-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/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-20220209214540-3681064d5158/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-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 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= @@ -509,20 +486,20 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -532,7 +509,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/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= @@ -552,6 +528,7 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs 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-20200505023115-26f46d2f7ef8/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= @@ -565,13 +542,14 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f 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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= 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= @@ -593,7 +571,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q 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.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= 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= @@ -625,7 +602,6 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG 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= @@ -638,12 +614,13 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D 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-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 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= @@ -657,13 +634,11 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji 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.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 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= @@ -675,8 +650,10 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= 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 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -687,12 +664,12 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= +gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -700,8 +677,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 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 h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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= @@ -709,24 +687,29 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh 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= -k8s.io/api v0.22.0 h1:elCpMZ9UE8dLdYxr55E06TmSeji9I3KH494qH70/y+c= -k8s.io/api v0.22.0/go.mod h1:0AoXXqst47OI/L0oGKq9DG61dvGRPXs7X4/B7KyjBCU= -k8s.io/apimachinery v0.22.0 h1:CqH/BdNAzZl+sr3tc0D3VsK3u6ARVSo3GWyLmfIjbP0= -k8s.io/apimachinery v0.22.0/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/client-go v0.22.0 h1:sD6o9O6tCwUKCENw8v+HFsuAbq2jCu8cWC61/ydwA50= -k8s.io/client-go v0.22.0/go.mod h1:GUjIuXR5PiEv/RVK5OODUsm6eZk7wtSWZSaSJbpFdGg= -k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/api v0.24.4 h1:I5Y645gJ8zWKawyr78lVfDQkZrAViSbeRXsPZWTxmXk= +k8s.io/api v0.24.4/go.mod h1:42pVfA0NRxrtJhZQOvRSyZcJihzAdU59WBtTjYcB0/M= +k8s.io/apimachinery v0.24.4 h1:S0Ur3J/PbivTcL43EdSdPhqCqKla2NIuneNwZcTDeGQ= +k8s.io/apimachinery v0.24.4/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/client-go v0.24.4 h1:hIAIJZIPyaw46AkxwyR0FRfM/pRxpUNTd3ysYu9vyRg= +k8s.io/client-go v0.24.4/go.mod h1:+AxlPWw/H6f+EJhRSjIeALaJT4tbeB/8g9BNvXGPd0Y= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9 h1:imL9YgXQ9p7xmPzHFm/vVd/cF78jad+n4wK1ABwYtMM= -k8s.io/utils v0.0.0-20210707171843-4b05e18ac7d9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= +k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 h1:Gii5eqf+GmIEwGNKQYQClCayuJCe2/4fZUvF7VG99sU= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 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/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= From 68126816ecc15f9433ff8dff9781ca2f6cefd432 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sat, 3 Sep 2022 15:42:02 -0400 Subject: [PATCH 18/46] Finish backend work for replicaStatus detection --- README.md | 1 + go.sum | 10 +-- internal/hajimari/ingressapps/apps.go | 13 ++- internal/kube/util/replicastatusgetter.go | 104 ++++++++++++++-------- internal/log/log.go | 2 +- internal/models/app.go | 9 +- package-lock.json | 6 ++ web/src/App.svelte | 5 +- web/src/AppList/AppGroup.svelte | 7 +- 9 files changed, 101 insertions(+), 56 deletions(-) create mode 100644 package-lock.json diff --git a/README.md b/README.md index eb5b20ab..a8bc6bdb 100644 --- a/README.md +++ b/README.md @@ -140,4 +140,5 @@ Hajimari (始まり) is Japanese for `beginnings`. Hajimari's original intended - [Forecastle](https://github.com/stakater/Forecastle) Ideas for integrating k8s ingress ## License + [Apache-2.0](https://choosealicense.com/licenses/apache-2.0/) diff --git a/go.sum b/go.sum index c12e231d..9f70efc9 100644 --- a/go.sum +++ b/go.sum @@ -51,7 +51,6 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= @@ -259,7 +258,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onrik/logrus v0.9.0 h1:oT7VstCUxWBoX7fswYK61fi9bzRBSpROq5CR2b7wxQo= github.com/onrik/logrus v0.9.0/go.mod h1:qfe9NeZVAJfIxviw3cYkZo3kvBtLoPRJriAO8zl7qTk= @@ -271,7 +269,6 @@ github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= @@ -284,6 +281,7 @@ github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qR 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +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/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -577,7 +575,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= 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= @@ -630,6 +627,7 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG 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= @@ -663,6 +661,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji 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= @@ -699,6 +698,7 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -739,8 +739,6 @@ k8s.io/utils v0.0.0-20220812165043-ad590609e2e5/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ 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/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index 79eb4ad6..ea5e421b 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -48,7 +48,7 @@ func (al *List) Populate(namespaces ...string) *List { al.err = err } - al.items = convertIngressesToHajimariApps(ingressList, *util.NewStatusGetter(al.kubeClient)) + al.items = convertIngressesToHajimariApps(ingressList, *util.NewReplicaStatusGetter(al.kubeClient)) return al } @@ -59,11 +59,10 @@ func (al *List) Get() ([]models.AppGroup, error) { } -func convertIngressesToHajimariApps(ingresses []v1.Ingress , ssg util.StatusGetter) (appGroups []models.AppGroup) { +func convertIngressesToHajimariApps(ingresses []v1.Ingress , rsg util.ReplicaStatusGetter) (appGroups []models.AppGroup) { for _, ingress := range ingresses { logger.Debugf("Found ingress with Name '%v' in Namespace '%v'", ingress.Name, ingress.Namespace) - status := ssg.GetDeploymentStatus(ingress).Get() - var emptyStatus string = "undefined" + replicaStatus := rsg.GetEndpointStatuses(ingress) wrapper := wrappers.NewIngressWrapper(&ingress) @@ -84,19 +83,19 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress , ssg util.StatusGett } if i, ok := appMap[wrapper.GetGroup()]; ok { - if wrapper.GetStatusCheckEnabled() && len(status)>0 { + if wrapper.GetStatusCheckEnabled() && (replicaStatus.GetReplicas() != 0) { appGroups[i].Apps = append(appGroups[i].Apps, models.App{ Name: wrapper.GetName(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Status: status, + Replicas: replicaStatus.GetReplicas(), + AvailableReplicas: replicaStatus.GetAvailableReplicas(), }) } else { appGroups[i].Apps = append(appGroups[i].Apps, models.App{ Name: wrapper.GetName(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Status: emptyStatus, }) } } diff --git a/internal/kube/util/replicastatusgetter.go b/internal/kube/util/replicastatusgetter.go index dc06d6bf..b12fc745 100644 --- a/internal/kube/util/replicastatusgetter.go +++ b/internal/kube/util/replicastatusgetter.go @@ -2,22 +2,28 @@ package util import ( "context" + "fmt" "math" // v1 "k8s.io/api/apps/v1" networkingV1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - // "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/selection" "k8s.io/client-go/kubernetes" ) +const ( + appNameLabelKey = "app.kubernetes.io/name" + serviceNameLabelKey = "kubernetes.io/service-name" +) + // struct for the ReplicaStatusGetter object type ReplicaStatusGetter struct { - err error - replicas int32 - availableReplicas int32 - status string - kubeClient kubernetes.Interface + err error + replicas int + availableReplicas int + kubeClient kubernetes.Interface } // Initializes a ReplicaStatusGetter @@ -27,51 +33,61 @@ func NewReplicaStatusGetter(kubeClient kubernetes.Interface) *ReplicaStatusGette } } -// GetDeploymentStatus gets the status conditions of the deployment and sets the status to match the Available status reported -func (rsg *ReplicaStatusGetter) GetDeploymentStatus(ingress networkingV1.Ingress) *ReplicaStatusGetter { +// Gets replicaStatuses using the DiscoveryV1 api +func (rsg *ReplicaStatusGetter) GetEndpointStatuses(ingress networkingV1.Ingress) *ReplicaStatusGetter { + namespace := ingress.ObjectMeta.GetNamespace() + serviceNames := getServiceNames(ingress) + var labelOptions metav1.ListOptions - if rsg.err != nil { - rsg.err = nil + // Set LabelOptions to get labels for service names that the ingress references + labelRequirements, err := labels.NewRequirement(serviceNameLabelKey, selection.In, serviceNames) + if err != nil { + logger.Error("Error setting labelSelector Requirements", err) } + labelOptions.LabelSelector = labels.NewSelector().Add(*labelRequirements).String() - // labelMap := ingress.GetLabels() - - deployment, err := rsg.kubeClient.AppsV1().Deployments(ingress.ObjectMeta.GetNamespace()).Get(context.Background(), ingress.ObjectMeta.GetName(), metav1.GetOptions{}) + epslices, err := rsg.kubeClient.DiscoveryV1().EndpointSlices(namespace).List(context.Background(), labelOptions) if err != nil { + logger.Error("Error Getting EndpointSlices: ", err) rsg.err = err - } else { - // Non-terminated pods targeted by the deployment - rsg.replicas = deployment.Status.Replicas - // Using Available instead of Ready as it would pass the minReadySeconds threshold - rsg.availableReplicas = deployment.Status.AvailableReplicas } - return rsg -} - -// GetDeploymentStatus gets the status conditions of the deployment and sets the status to match the Available status reported -func (rsg *ReplicaStatusGetter) GetDaemonSetStatus(ingress networkingV1.Ingress) *ReplicaStatusGetter { + if len(epslices.Items) > 1 { + // This scenario can happen if the metrics endpointslices are included in the ingress + logger.Info(ingress.Name, " Multiple EndpointSlices found. Will try using all of them.") + } - if rsg.err != nil { - rsg.err = nil + if len(epslices.Items)==0 { + // This is indication that labels are mismatched somewhere + logger.Info(ingress.Name, " No EndpointSlice Found") } - daemonSet, err := rsg.kubeClient.AppsV1().DaemonSets(ingress.ObjectMeta.GetNamespace()).Get(context.Background(), ingress.ObjectMeta.GetName(), metav1.GetOptions{}) + replicas := 0 + availableReplicas := 0 + + for _, epslice := range epslices.Items { + logger.Debug("Checking EndpointSlice: ", epslice.Name) + replicas = replicas + len(epslice.Endpoints) + for _, ep := range epslice.Endpoints { + if *ep.Conditions.Ready == true { + availableReplicas = availableReplicas + 1 + } + } + } - if err != nil { - rsg.err = err + if replicas == 0 { + rsg.err = fmt.Errorf("No endpoints found for %s", ingress.Name) } else { - // Non-terminated pods targeted by the deployment - rsg.replicas = daemonSet.Status.DesiredNumberScheduled - // Using Available instead of Ready as it would pass the minReadySeconds threshold - rsg.availableReplicas = daemonSet.Status.NumberAvailable + rsg.replicas = replicas + rsg.availableReplicas = availableReplicas } return rsg } + // Gets the current value of replicas -func (rsg *ReplicaStatusGetter) GetReplicas() int32 { +func (rsg *ReplicaStatusGetter) GetReplicas() int { if rsg.err != nil { logger.Warn(rsg.err) return 0 @@ -80,7 +96,7 @@ func (rsg *ReplicaStatusGetter) GetReplicas() int32 { } // Gets the current value of replicas -func (rsg *ReplicaStatusGetter) GetAvailableReplicas() int32 { +func (rsg *ReplicaStatusGetter) GetAvailableReplicas() int { if rsg.err != nil { logger.Warn(rsg.err) return 0 @@ -95,5 +111,23 @@ func (rsg *ReplicaStatusGetter) GetRatio() float64 { logger.Warn(rsg.err) return 0 } - return math.Round(float64(rsg.availableReplicas)/float64(rsg.replicas)) + return math.Round(float64(rsg.availableReplicas) / float64(rsg.replicas)) +} + +// Gets Service Names that the Ingress is actually meant for +func getServiceNames(ingress networkingV1.Ingress) []string { + serviceNames := []string{} + + if ingress.Spec.DefaultBackend != nil { + serviceNames = append(serviceNames, ingress.Spec.DefaultBackend.Service.Name) + } + if len(ingress.Spec.Rules)>0 { + for _, rule := range ingress.Spec.Rules { + for _, path := range rule.HTTP.Paths { + serviceNames = append(serviceNames, path.Backend.Service.Name) + } + } + } + + return serviceNames } diff --git a/internal/log/log.go b/internal/log/log.go index 550a5080..07ff1460 100644 --- a/internal/log/log.go +++ b/internal/log/log.go @@ -19,7 +19,7 @@ func New() *logrus.Logger { Hooks: make(logrus.LevelHooks), Out: os.Stdout, Formatter: &logrus.TextFormatter{}, - Level: logrus.InfoLevel, + Level: logrus.DebugLevel, } log.Hooks.Add(filenameHook) diff --git a/internal/models/app.go b/internal/models/app.go index 821e70d4..11ccf910 100644 --- a/internal/models/app.go +++ b/internal/models/app.go @@ -1,8 +1,9 @@ package models type App struct { - Name string `json:"name"` - Icon string `json:"icon"` - URL string `json:"url"` - Status string `json:"status"` + Name string `json:"name"` + Icon string `json:"icon"` + URL string `json:"url"` + Replicas int `json:"replicas"` + AvailableReplicas int `json:"availableReplicas"` } diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..22621d7f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "hajimari", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/web/src/App.svelte b/web/src/App.svelte index 9d8dd981..34d85a15 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -34,11 +34,12 @@
- + @@ -128,4 +129,4 @@ width: 90%; } } - \ No newline at end of file + diff --git a/web/src/AppList/AppGroup.svelte b/web/src/AppList/AppGroup.svelte index bca31f9f..6cbfa964 100644 --- a/web/src/AppList/AppGroup.svelte +++ b/web/src/AppList/AppGroup.svelte @@ -1,10 +1,15 @@ {#each group.apps as app}
+ {#if app?.status === "true"} + {app.status} + {/if}
{app.name} @@ -71,4 +76,4 @@ display: none; } } - \ No newline at end of file + From ee40db0315c477271fc6acedb42aa194e7dbbc3b Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sat, 3 Sep 2022 18:33:45 -0400 Subject: [PATCH 19/46] light refactoring to get apps to display --- internal/hajimari/customapps/customapps.go | 6 ++--- internal/hajimari/ingressapps/apps.go | 6 ++--- internal/handlers/apps.go | 2 +- internal/kube/util/replicastatusgetter.go | 4 +-- internal/models/app.go | 5 ++++ internal/models/app_group.go | 2 +- web/src/AppList/AppGroup.svelte | 24 ++++++++--------- web/src/AppList/index.svelte | 30 ++++++++++------------ 8 files changed, 41 insertions(+), 38 deletions(-) diff --git a/internal/hajimari/customapps/customapps.go b/internal/hajimari/customapps/customapps.go index 392b4dc8..5beb5acb 100644 --- a/internal/hajimari/customapps/customapps.go +++ b/internal/hajimari/customapps/customapps.go @@ -26,9 +26,9 @@ func (al *List) Populate() *List { var customApps []models.AppGroup - for _, v := range al.appConfig.CustomApps { - v.Group = strings.ToLower(v.Group) - customApps = append(customApps, v) + for _, group := range al.appConfig.CustomApps { + group.Name = strings.ToLower(group.Name) + customApps = append(customApps, group) } al.items = customApps diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index ea5e421b..413db434 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -68,18 +68,18 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress , rsg util.ReplicaSta groupMap := make(map[string]int, len(appGroups)) for i, v := range appGroups { - groupMap[v.Group] = i + groupMap[v.Name] = i } if _, ok := groupMap[wrapper.GetGroup()]; !ok { appGroups = append(appGroups, models.AppGroup{ - Group: wrapper.GetGroup(), + Name: wrapper.GetGroup(), }) } appMap := make(map[string]int, len(appGroups)) for i, v := range appGroups { - appMap[v.Group] = i + appMap[v.Name] = i } if i, ok := appMap[wrapper.GetGroup()]; ok { diff --git a/internal/handlers/apps.go b/internal/handlers/apps.go index b3132a0a..f13577e8 100644 --- a/internal/handlers/apps.go +++ b/internal/handlers/apps.go @@ -76,7 +76,7 @@ func (rs *appResource) ListApps(w http.ResponseWriter, r *http.Request) { for i, ingressAppGroup := range ingressApps { for x, customAppGroup := range customApps { - if customAppGroup.Group == ingressAppGroup.Group { + if customAppGroup.Name == ingressAppGroup.Name { ingressApps[i].Apps = append(ingressApps[i].Apps, customAppGroup.Apps...) customApps = append(customApps[:x], customApps[x+1:]...) } diff --git a/internal/kube/util/replicastatusgetter.go b/internal/kube/util/replicastatusgetter.go index b12fc745..b45f342b 100644 --- a/internal/kube/util/replicastatusgetter.go +++ b/internal/kube/util/replicastatusgetter.go @@ -55,12 +55,12 @@ func (rsg *ReplicaStatusGetter) GetEndpointStatuses(ingress networkingV1.Ingress if len(epslices.Items) > 1 { // This scenario can happen if the metrics endpointslices are included in the ingress - logger.Info(ingress.Name, " Multiple EndpointSlices found. Will try using all of them.") + logger.Debug(ingress.Name, " Multiple EndpointSlices found. Will try using all of them.") } if len(epslices.Items)==0 { // This is indication that labels are mismatched somewhere - logger.Info(ingress.Name, " No EndpointSlice Found") + logger.Debug(ingress.Name, " No EndpointSlice Found") } replicas := 0 diff --git a/internal/models/app.go b/internal/models/app.go index 11ccf910..0cd73665 100644 --- a/internal/models/app.go +++ b/internal/models/app.go @@ -7,3 +7,8 @@ type App struct { Replicas int `json:"replicas"` AvailableReplicas int `json:"availableReplicas"` } + +type ReplicaInfo struct { + Total int + Available int +} diff --git a/internal/models/app_group.go b/internal/models/app_group.go index e31ae4f3..1a8153c6 100644 --- a/internal/models/app_group.go +++ b/internal/models/app_group.go @@ -1,6 +1,6 @@ package models type AppGroup struct { - Group string `json:"group"` + Name string `json:"name"` Apps []App `json:"apps"` } diff --git a/web/src/AppList/AppGroup.svelte b/web/src/AppList/AppGroup.svelte index 6cbfa964..da0e8434 100644 --- a/web/src/AppList/AppGroup.svelte +++ b/web/src/AppList/AppGroup.svelte @@ -1,21 +1,21 @@ {#each group.apps as app} -
-
- - {#if app?.status === "true"} - {app.status} - {/if} +
+
+ + {#if app?.replicas > 0} +
+ {/if} +
+
+ {app.name} + {app.url} +
-
- {app.name} - {app.url} -
-
{/each} \ No newline at end of file + From ec7de2049c9fc9baec9e30905aa37ec46a56ef25 Mon Sep 17 00:00:00 2001 From: Zee Aslam Date: Sat, 3 Sep 2022 20:11:18 -0400 Subject: [PATCH 20/46] PoC basics done --- internal/hajimari/ingressapps/apps.go | 15 ++++++++++++--- internal/models/app.go | 8 +------- internal/models/replica_info.go | 7 +++++++ web/src/App.svelte | 1 + web/src/AppList/AppGroup.svelte | 14 +++++++++++--- web/src/AppList/index.svelte | 4 +++- 6 files changed, 35 insertions(+), 14 deletions(-) create mode 100755 internal/models/replica_info.go diff --git a/internal/hajimari/ingressapps/apps.go b/internal/hajimari/ingressapps/apps.go index 413db434..ea662b30 100644 --- a/internal/hajimari/ingressapps/apps.go +++ b/internal/hajimari/ingressapps/apps.go @@ -1,14 +1,16 @@ package ingressapps import ( + "math" + "github.com/toboshii/hajimari/internal/annotations" "github.com/toboshii/hajimari/internal/config" "github.com/toboshii/hajimari/internal/kube/lists/ingresses" "github.com/toboshii/hajimari/internal/kube/util" "github.com/toboshii/hajimari/internal/kube/wrappers" "github.com/toboshii/hajimari/internal/log" - "k8s.io/api/networking/v1" "github.com/toboshii/hajimari/internal/models" + "k8s.io/api/networking/v1" "k8s.io/client-go/kubernetes" ) @@ -88,8 +90,11 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress , rsg util.ReplicaSta Name: wrapper.GetName(), Icon: wrapper.GetAnnotationValue(annotations.HajimariIconAnnotation), URL: wrapper.GetURL(), - Replicas: replicaStatus.GetReplicas(), - AvailableReplicas: replicaStatus.GetAvailableReplicas(), + Replicas: models.ReplicaInfo{ + Total: replicaStatus.GetReplicas(), + Available: replicaStatus.GetAvailableReplicas(), + PctReady: math.Round(replicaStatus.GetRatio()*100), + }, }) } else { appGroups[i].Apps = append(appGroups[i].Apps, models.App{ @@ -103,3 +108,7 @@ func convertIngressesToHajimariApps(ingresses []v1.Ingress , rsg util.ReplicaSta } return } + +func round(f float64, i int) { + panic("unimplemented") +} diff --git a/internal/models/app.go b/internal/models/app.go index 0cd73665..cc05b71c 100644 --- a/internal/models/app.go +++ b/internal/models/app.go @@ -4,11 +4,5 @@ type App struct { Name string `json:"name"` Icon string `json:"icon"` URL string `json:"url"` - Replicas int `json:"replicas"` - AvailableReplicas int `json:"availableReplicas"` -} - -type ReplicaInfo struct { - Total int - Available int + Replicas ReplicaInfo `json:"replicas"` } diff --git a/internal/models/replica_info.go b/internal/models/replica_info.go new file mode 100755 index 00000000..161589e4 --- /dev/null +++ b/internal/models/replica_info.go @@ -0,0 +1,7 @@ +package models + +type ReplicaInfo struct { + Total int `json:"total"` + Available int `json:"available"` + PctReady float64 `json:"pctReady"` +} diff --git a/web/src/App.svelte b/web/src/App.svelte index 34d85a15..82c01bb9 100644 --- a/web/src/App.svelte +++ b/web/src/App.svelte @@ -13,6 +13,7 @@ fetch("http://localhost:3000/apps") .then(response => response.json()) .then(data => { + console.log("in promise then") console.log(data); apps.set(data); }).catch(error => { diff --git a/web/src/AppList/AppGroup.svelte b/web/src/AppList/AppGroup.svelte index da0e8434..a0053ef6 100644 --- a/web/src/AppList/AppGroup.svelte +++ b/web/src/AppList/AppGroup.svelte @@ -3,12 +3,12 @@ export let group; console.log(group); -{#each group.apps as app} +{#each group.apps || [] as app}
- {#if app?.replicas > 0} -
+ {#if app?.replicas} +
{/if}
@@ -16,6 +16,10 @@ {app.url}
+{:else} +
+

No Apps in this Group

+
{/each} \ No newline at end of file diff --git a/web/src/BookmarkList/BookmarkGroup.svelte b/frontend/src/lib/BookmarkList/BookmarkGroup.svelte similarity index 68% rename from web/src/BookmarkList/BookmarkGroup.svelte rename to frontend/src/lib/BookmarkList/BookmarkGroup.svelte index 0e632b13..9e328920 100644 --- a/web/src/BookmarkList/BookmarkGroup.svelte +++ b/frontend/src/lib/BookmarkList/BookmarkGroup.svelte @@ -1,9 +1,10 @@ diff --git a/web/src/BookmarkList/index.svelte b/frontend/src/lib/BookmarkList/index.svelte similarity index 74% rename from web/src/BookmarkList/index.svelte rename to frontend/src/lib/BookmarkList/index.svelte index 76076245..4f39e94f 100644 --- a/web/src/BookmarkList/index.svelte +++ b/frontend/src/lib/BookmarkList/index.svelte @@ -1,28 +1,28 @@ - {#if bookmarks.length === 0} {:else}
{:else} @@ -80,6 +84,10 @@ .app_address { overflow-wrap: break-word; } + + .app_info { + overflow-wrap: break-word; + } .app_status { /* background-image: linear-gradient(to right, black 0 50%, transparent 50% 100%); */ diff --git a/frontend/src/lib/AppList/index.svelte b/frontend/src/lib/AppList/index.svelte index ab80e06f..73029b9f 100644 --- a/frontend/src/lib/AppList/index.svelte +++ b/frontend/src/lib/AppList/index.svelte @@ -5,6 +5,7 @@ export let showGroups: boolean; export let defaultIcon: string = 'mdi:application'; export let showUrls: boolean = true; + export let showInfo: boolean = true;

Applications

@@ -17,11 +18,11 @@ {:else} - + {/if} {/each}
diff --git a/frontend/src/routes/[...slug]/+page.svelte b/frontend/src/routes/[...slug]/+page.svelte index b867a007..249f85e0 100644 --- a/frontend/src/routes/[...slug]/+page.svelte +++ b/frontend/src/routes/[...slug]/+page.svelte @@ -15,7 +15,7 @@ {/if} - + diff --git a/frontend/src/routes/[...slug]/+page.ts b/frontend/src/routes/[...slug]/+page.ts index c1a5d7cd..f4779e7b 100644 --- a/frontend/src/routes/[...slug]/+page.ts +++ b/frontend/src/routes/[...slug]/+page.ts @@ -12,6 +12,7 @@ type Startpage = { showGreeting: boolean; showAppGroups: boolean; showAppUrls: boolean; + showAppInfo: boolean; showBookmarkGroups: boolean; showGlobalBookmarks: boolean; bookmarks: any; diff --git a/internal/config/config.go b/internal/config/config.go index 89b2736a..2d8e2004 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -22,6 +22,7 @@ type Config struct { ShowGreeting bool `default:"true" json:"showGreeting"` ShowAppGroups bool `default:"false" json:"showAppGroups"` ShowAppUrls bool `default:"true" json:"showAppUrls"` + ShowAppInfo bool `default:"true" json:"showAppInfo"` ShowBookmarkGroups bool `default:"true" json:"showBookmarkGroups"` ShowGlobalBookmarks bool `default:"false" json:"showGlobalBookmarks"` CustomApps []models.AppGroup `default:"[]" json:"customApps"` diff --git a/internal/kube/wrappers/ingress.go b/internal/kube/wrappers/ingress.go index 5532308e..b8a8b061 100644 --- a/internal/kube/wrappers/ingress.go +++ b/internal/kube/wrappers/ingress.go @@ -60,8 +60,7 @@ func (iw *IngressWrapper) GetInfo() string { if infoFromAnnotation := iw.GetAnnotationValue(annotations.HajimariInfoAnnotation); infoFromAnnotation != "" { return infoFromAnnotation } - // TODO: Empty instead of listing the URL? - return iw.GetURL() + return "" } // GetStatusCheckEnabled func extracts statusCheck feature gate from the ingress diff --git a/internal/models/startpage.go b/internal/models/startpage.go index 23e74f61..9ef657a3 100644 --- a/internal/models/startpage.go +++ b/internal/models/startpage.go @@ -10,7 +10,7 @@ type Startpage struct { ShowGreeting *bool `json:"showGreeting"` ShowAppGroups *bool `json:"showAppGroups"` ShowAppUrls *bool `json:"showAppUrls"` - ShowAppInfos *bool `json:"showAppInfos"` + ShowAppInfo *bool `json:"showAppInfo"` ShowBookmarkGroups *bool `json:"showBookmarkGroups"` ShowGlobalBookmarks *bool `json:"showGlobalBookmarks"` Bookmarks []BookmarkGroup `json:"bookmarks"` diff --git a/internal/stores/memory.go b/internal/stores/memory.go index 308b6eeb..6095e9ff 100644 --- a/internal/stores/memory.go +++ b/internal/stores/memory.go @@ -15,6 +15,7 @@ var startpages = []*models.Startpage{ ShowAppGroups: pointer.Of(false), ShowGlobalBookmarks: pointer.Of(true), ShowAppUrls: pointer.Of(true), + ShowAppInfo: pointer.Of(true), Bookmarks: []models.BookmarkGroup{ { Group: "Media", From f028b53b7e40f8838273cea7ee1051d988e23ad0 Mon Sep 17 00:00:00 2001 From: Toboshii Nakama <63410334+toboshii@users.noreply.github.com> Date: Fri, 9 Sep 2022 10:10:15 -0500 Subject: [PATCH 27/46] feat: move ingressApp handling to background job (closes #3) --- internal/handlers/apps.go | 42 ++++----------- internal/handlers/handler.go | 3 +- internal/services/app.go | 99 ++++++++++++++++++++++++++++++++++ internal/services/startpage.go | 5 -- 4 files changed, 110 insertions(+), 39 deletions(-) create mode 100644 internal/services/app.go diff --git a/internal/handlers/apps.go b/internal/handlers/apps.go index b3132a0a..4bdcd2ba 100644 --- a/internal/handlers/apps.go +++ b/internal/handlers/apps.go @@ -2,23 +2,21 @@ package handlers import ( "net/http" - "strings" "github.com/go-chi/chi/v5" "github.com/go-chi/render" "github.com/toboshii/hajimari/internal/config" "github.com/toboshii/hajimari/internal/hajimari/customapps" - "github.com/toboshii/hajimari/internal/hajimari/ingressapps" - "github.com/toboshii/hajimari/internal/kube" - "github.com/toboshii/hajimari/internal/kube/util" "github.com/toboshii/hajimari/internal/models" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/toboshii/hajimari/internal/services" ) -type appResource struct{} +type appResource struct { + service services.AppService +} -func NewAppResource() *appResource { - return &appResource{} +func NewAppResource(service services.AppService) *appResource { + return &appResource{service: service} } func (rs *appResource) AppRoutes() chi.Router { @@ -36,33 +34,11 @@ func (rs *appResource) ListApps(w http.ResponseWriter, r *http.Request) { return } - kubeClient := kube.GetClient() + cachedIngressApps := rs.service.GetCachedIngressApps() - ingressAppsList := ingressapps.NewList(kubeClient, *appConfig) + var ingressApps = make([]models.AppGroup, len(cachedIngressApps)) - namespaces, err := util.PopulateNamespaceList(kubeClient, appConfig.NamespaceSelector) - if err != nil { - logger.Error("An error occurred while populating namespaces: ", err) - render.Render(w, r, ErrServerError(err)) - return - } - - var namespacesString string - // All Namespaces are selected - if len(namespaces) == 1 && namespaces[0] == metav1.NamespaceAll { - namespacesString = "* (All Namespaces)" - } else { - namespacesString = strings.Join(namespaces, ", ") - } - - logger.Debug("Looking for hajimari apps in the following namespaces: ", namespacesString) - - ingressApps, err := ingressAppsList.Populate(namespaces...).Get() - if err != nil { - logger.Error("An error occurred while looking for hajimari apps", err) - render.Render(w, r, ErrServerError(err)) - return - } + copy(ingressApps, cachedIngressApps) customAppsList := customapps.NewList(*appConfig) diff --git a/internal/handlers/handler.go b/internal/handlers/handler.go index db9abcd2..15e87ead 100644 --- a/internal/handlers/handler.go +++ b/internal/handlers/handler.go @@ -39,9 +39,10 @@ func NewHandler() http.Handler { router.NotFound(notFoundHandler) startpageService := services.NewStartpageService(stores.NewMemoryStore(), logger) + appService := services.NewAppService(logger) // router.Mount("/config", NewConfigResource().ConfigRoutes()) - router.Mount("/apps", NewAppResource().AppRoutes()) + router.Mount("/apps", NewAppResource(appService).AppRoutes()) router.Mount("/bookmarks", NewBookmarkResource().BookmarkRoutes()) router.Mount("/startpage", NewStartpageResource(startpageService).StartpageRoutes()) diff --git a/internal/services/app.go b/internal/services/app.go new file mode 100644 index 00000000..838a6466 --- /dev/null +++ b/internal/services/app.go @@ -0,0 +1,99 @@ +package services + +import ( + "strings" + "sync" + "time" + + "github.com/sirupsen/logrus" + "github.com/toboshii/hajimari/internal/config" + "github.com/toboshii/hajimari/internal/hajimari/ingressapps" + "github.com/toboshii/hajimari/internal/kube" + "github.com/toboshii/hajimari/internal/kube/util" + "github.com/toboshii/hajimari/internal/log" + "github.com/toboshii/hajimari/internal/models" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var ( + logger = log.New() + mutex sync.RWMutex + ingressAppCache []models.AppGroup +) + +type AppService interface { + GetCachedIngressApps() []models.AppGroup +} + +type appService struct { + logger *logrus.Logger +} + +func NewAppService(logger *logrus.Logger) *appService { + // todo: make time configurable + ticker := time.NewTicker(60 * time.Second) + updaterChan := make(chan struct{}) + mutex = sync.RWMutex{} + + ingressAppCache = getIngressApps() + + go startIngressAppCacheUpdater(ticker, updaterChan) + + return &appService{logger: logger} +} + +func (as *appService) GetCachedIngressApps() []models.AppGroup { + return ingressAppCache +} + +func getIngressApps() []models.AppGroup { + appConfig, err := config.GetConfig() + if err != nil { + logger.Error("Failed to read configuration for hajimari: ", err) + return nil + } + + kubeClient := kube.GetClient() + + ingressAppsList := ingressapps.NewList(kubeClient, *appConfig) + + namespaces, err := util.PopulateNamespaceList(kubeClient, appConfig.NamespaceSelector) + if err != nil { + logger.Error("An error occurred while populating namespaces: ", err) + return nil + } + + var namespacesString string + // All Namespaces are selected + if len(namespaces) == 1 && namespaces[0] == metav1.NamespaceAll { + namespacesString = "* (All Namespaces)" + } else { + namespacesString = strings.Join(namespaces, ", ") + } + + logger.Debug("Looking for hajimari apps in the following namespaces: ", namespacesString) + + ingressApps, err := ingressAppsList.Populate(namespaces...).Get() + if err != nil { + logger.Error("An error occurred while looking for hajimari apps", err) + return nil + } + + return ingressApps +} + +func startIngressAppCacheUpdater(ticker *time.Ticker, updaterChan chan struct{}) { + logger.Info("IngressApp cache daemon started") + for { + select { + case <-ticker.C: + // update cache + mutex.Lock() // lock the cache before writing to it + ingressAppCache = getIngressApps() + mutex.Unlock() // unlock the cache after writing to it + case <-updaterChan: + // stop the daemon + return + } + } +} diff --git a/internal/services/startpage.go b/internal/services/startpage.go index 463e50c3..9fae06e0 100644 --- a/internal/services/startpage.go +++ b/internal/services/startpage.go @@ -5,15 +5,10 @@ import ( "github.com/sirupsen/logrus" "github.com/toboshii/hajimari/internal/config" - "github.com/toboshii/hajimari/internal/log" "github.com/toboshii/hajimari/internal/models" "github.com/toboshii/hajimari/internal/stores" ) -var ( - logger = log.New() -) - type StartpageService interface { NewStartpage(startpage *models.Startpage) (string, error) GetStartpage(id string) (*models.Startpage, error) From bf649f4f037ad038dee4afa72b6bfb1c6b6484e2 Mon Sep 17 00:00:00 2001 From: Toboshii Nakama <63410334+toboshii@users.noreply.github.com> Date: Fri, 9 Sep 2022 11:00:05 -0500 Subject: [PATCH 28/46] feat: support icon urls --- frontend/src/lib/AppList/AppGroup.svelte | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/frontend/src/lib/AppList/AppGroup.svelte b/frontend/src/lib/AppList/AppGroup.svelte index 83e0bc61..36af5bb1 100644 --- a/frontend/src/lib/AppList/AppGroup.svelte +++ b/frontend/src/lib/AppList/AppGroup.svelte @@ -1,5 +1,6 @@ {#each group.apps || [] as app} -
+
{#if app.icon.includes('//')} diff --git a/frontend/src/lib/AppList/index.svelte b/frontend/src/lib/AppList/index.svelte index 73029b9f..77a897db 100644 --- a/frontend/src/lib/AppList/index.svelte +++ b/frontend/src/lib/AppList/index.svelte @@ -1,4 +1,5 @@

Applications

@@ -15,7 +20,7 @@
{#each apps as group} {#if showGroups === true} - {/each} - \ No newline at end of file + diff --git a/frontend/src/lib/BookmarkList/index.svelte b/frontend/src/lib/BookmarkList/index.svelte index 4f39e94f..6f4543bf 100644 --- a/frontend/src/lib/BookmarkList/index.svelte +++ b/frontend/src/lib/BookmarkList/index.svelte @@ -1,8 +1,8 @@ @@ -50,7 +50,7 @@ } @media screen and (max-width: 1260px) { - .links_loop { + .links_loop { grid-template-columns: 1fr 1fr 1fr; } } @@ -65,4 +65,4 @@ grid-template-rows: auto; } } - \ No newline at end of file + diff --git a/frontend/src/lib/CodeMirror/CodeMirror.svelte b/frontend/src/lib/CodeMirror/CodeMirror.svelte new file mode 100644 index 00000000..a3fb0a24 --- /dev/null +++ b/frontend/src/lib/CodeMirror/CodeMirror.svelte @@ -0,0 +1,248 @@ + + + + + + +
+