0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00

ui: initial commit

Signed-off-by: Ramkumar Chinchani <rchincha@cisco.com>
(cherry picked from commit d557da0baba819b7cd7e6b5941528776e125ac6d)
This commit is contained in:
Ramkumar Chinchani 2022-07-22 06:18:54 +00:00
parent f3faae0e09
commit 97f1fc0f98
10 changed files with 134 additions and 16 deletions

View file

@ -45,7 +45,7 @@ build-metadata:
go list -tags $(EXTENSIONS) -f '{{ join .GoFiles "\n" }}' ./... | sort -u
.PHONY: binary
binary: modcheck swagger create-name build-metadata
binary: modcheck swagger create-name build-metadata ui
env CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -o bin/zot-$(OS)-$(ARCH) -buildmode=pie -tags $(EXTENSIONS),containers_image_openpgp -v -trimpath -ldflags "-X zotregistry.io/zot/pkg/api/config.Commit=${COMMIT} -X zotregistry.io/zot/pkg/api/config.BinaryType=$(extended-name) -X zotregistry.io/zot/pkg/api/config.GoVersion=${GO_VERSION} -s -w" ./cmd/zot
.PHONY: binary-debug
@ -134,7 +134,7 @@ $(GOLINTER):
$(GOLINTER) version
.PHONY: check
check: ./golangcilint.yaml $(GOLINTER)
check: ./golangcilint.yaml $(GOLINTER) ui
$(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags containers_image_openpgp ./...
$(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags $(EXTENSIONS),containers_image_openpgp ./...
$(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags dev,containers_image_openpgp ./...
@ -187,6 +187,7 @@ clean:
rm -rf hack
rm -rf test/data/zot-test
rm -rf test/data/zot-cve-test
rm -rf pkg/extensions/build
.PHONY: run
run: binary test
@ -323,3 +324,16 @@ fuzz-all:
.PHONY: anonymous-push-pull
anonymous-push-pull: binary check-skopeo $(BATS)
$(BATS) --trace --print-output-on-failure test/blackbox/anonymous_policiy.bats
.PHONY: ui
ui:
pwd=$$(pwd);\
tdir=$$(mktemp -d);\
cd $$tdir;\
git clone https://github.com/project-zot/zui.git;\
cd zui;\
npm install;\
npm run build;\
cd $$pwd;\
rm -rf ./pkg/extensions/build;\
cp -R $$tdir/zui/build ./pkg/extensions/;

23
examples/config-ui.json Normal file
View file

@ -0,0 +1,23 @@
{
"distSpecVersion": "1.0.1-dev",
"storage": {
"rootDirectory": "/tmp/zot"
},
"http": {
"address": "127.0.0.1",
"port": "8080"
},
"log": {
"level": "debug"
},
"extensions": {
"search": {
"cve": {
"updateInterval": "2h"
}
},
"ui": {
"enable": true
}
}
}

View file

@ -58,7 +58,8 @@ func allowedMethods(method string) []string {
// nolint: contextcheck
func (rh *RouteHandler) SetupRoutes() {
rh.c.Router.Use(AuthHandler(rh.c))
prefixedRouter := rh.c.Router.PathPrefix(constants.RoutePrefix).Subrouter()
prefixedRouter.Use(AuthHandler(rh.c))
// authz is being enabled if AccessControl is specified
// if Authn is not present AccessControl will have only default policies
if rh.c.Config.AccessControl != nil && !isBearerAuthEnabled(rh.c.Config) {
@ -68,11 +69,10 @@ func (rh *RouteHandler) SetupRoutes() {
rh.c.Log.Info().Msg("default policy only access control is being enabled")
}
rh.c.Router.Use(AuthzHandler(rh.c))
prefixedRouter.Use(AuthzHandler(rh.c))
}
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#endpoints
prefixedRouter := rh.c.Router.PathPrefix(constants.RoutePrefix).Subrouter()
{
prefixedRouter.HandleFunc(fmt.Sprintf("/{name:%s}/tags/list", NameRegexp.String()),
rh.ListTags).Methods(allowedMethods("GET")...)
@ -113,7 +113,10 @@ func (rh *RouteHandler) SetupRoutes() {
constants.ArtifactSpecRoutePrefix, NameRegexp.String()), rh.GetReferrers).Methods("GET")
// swagger swagger "/swagger/v2/index.html"
rh.c.Router.PathPrefix("/swagger/v2/").Methods("GET").Handler(httpSwagger.WrapHandler)
swgRouter := rh.c.Router.PathPrefix("/swagger/v2/").Subrouter()
swgRouter.Use(AuthHandler(rh.c))
swgRouter.Methods("GET").Handler(httpSwagger.WrapHandler)
// Setup Extensions Routes
if rh.c.Config != nil {
if rh.c.Config.Extensions == nil {
@ -121,8 +124,9 @@ func (rh *RouteHandler) SetupRoutes() {
prefixedRouter.HandleFunc("/metrics", rh.GetMetrics).Methods("GET")
} else {
// extended build
ext.SetupMetricsRoutes(rh.c.Config, rh.c.Router, rh.c.StoreController, rh.c.Log)
ext.SetupSearchRoutes(rh.c.Config, rh.c.Router, rh.c.StoreController, rh.c.Log)
ext.SetupMetricsRoutes(rh.c.Config, rh.c.Router, rh.c.StoreController, AuthHandler(rh.c), rh.c.Log)
ext.SetupSearchRoutes(rh.c.Config, rh.c.Router, rh.c.StoreController, AuthHandler(rh.c), rh.c.Log)
ext.SetupUIRoutes(rh.c.Config, rh.c.Router, rh.c.StoreController, rh.c.Log)
}
}
}

View file

@ -12,6 +12,7 @@ type ExtensionConfig struct {
Metrics *MetricsConfig
Scrub *ScrubConfig
Lint *LintConfig
UI *UIConfig
}
type LintConfig struct {
@ -41,3 +42,7 @@ type PrometheusConfig struct {
type ScrubConfig struct {
Interval time.Duration
}
type UIConfig struct {
Enable *bool
}

View file

@ -0,0 +1,18 @@
//go:build !search && !ui_base
// +build !search,!ui_base
package extensions
import (
"github.com/gorilla/mux"
"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/storage"
)
func SetupUIRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
log log.Logger,
) {
log.Warn().Msg("skipping setting up ui routes because given zot binary doesn't include this feature," +
"please build a binary that does so")
}

View file

@ -0,0 +1,52 @@
//go:build search || ui_base
// +build search ui_base
package extensions
import (
"embed"
"io/fs"
"net/http"
"github.com/gorilla/mux"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/storage"
"zotregistry.io/zot/pkg/api/config"
)
// content is our static web server content.
//go:embed build/*
var content embed.FS
func SetupUIRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
l log.Logger,
) {
// fork a new zerolog child to avoid data race
log := log.Logger{Logger: l.With().Caller().Timestamp().Logger()}
if config.Extensions.UI != nil {
fsub, _ := fs.Sub(content, "build")
router.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
buf, _ := content.ReadFile("build/index.html")
_, err := w.Write(buf)
if err != nil {
log.Error().Err(err).Msg("unable to serve index.html")
}
})
router.HandleFunc("/home", func(w http.ResponseWriter, r *http.Request) {
buf, _ := content.ReadFile("build/index.html")
_, err := w.Write(buf)
if err != nil {
log.Error().Err(err).Msg("unable to serve index.html")
}
})
router.PathPrefix("/").Handler(http.FileServer(http.FS(fsub)))
log.Info().Msg("setting up ui routes")
}
}

View file

@ -26,14 +26,14 @@ func EnableMetricsExtension(config *config.Config, log log.Logger, rootDir strin
}
func SetupMetricsRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
l log.Logger,
authFunc mux.MiddlewareFunc, l log.Logger,
) {
// fork a new zerolog child to avoid data race
log := log.Logger{Logger: l.With().Caller().Timestamp().Logger()}
log.Info().Msg("setting up metrics routes")
if config.Extensions.Metrics != nil && *config.Extensions.Metrics.Enable {
router.PathPrefix(config.Extensions.Metrics.Prometheus.Path).
Handler(promhttp.Handler())
extRouter := router.PathPrefix(config.Extensions.Metrics.Prometheus.Path).Handler(promhttp.Handler()).Subrouter()
extRouter.Use(authFunc)
}
}

View file

@ -18,7 +18,7 @@ func EnableMetricsExtension(config *config.Config, log log.Logger, rootDir strin
// SetupMetricsRoutes ...
func SetupMetricsRoutes(conf *config.Config, router *mux.Router,
storeController storage.StoreController, log log.Logger,
storeController storage.StoreController, authFunc mux.MiddlewareFunc, log log.Logger,
) {
log.Warn().Msg("skipping setting up metrics routes because given zot binary doesn't include this feature," +
"please build a binary that does so")

View file

@ -56,7 +56,7 @@ func downloadTrivyDB(dbDir string, log log.Logger, updateInterval time.Duration)
}
func SetupSearchRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
l log.Logger,
authFunc mux.MiddlewareFunc, l log.Logger,
) {
// fork a new zerolog child to avoid data race
log := log.Logger{Logger: l.With().Caller().Timestamp().Logger()}
@ -71,8 +71,10 @@ func SetupSearchRoutes(config *config.Config, router *mux.Router, storeControlle
resConfig = search.GetResolverConfig(log, storeController, false)
}
graphqlPrefix := router.PathPrefix(constants.ExtSearchPrefix).Methods("OPTIONS", "GET", "POST")
graphqlPrefix.Handler(gqlHandler.NewDefaultServer(gql_generated.NewExecutableSchema(resConfig)))
extRouter := router.PathPrefix(constants.ExtSearchPrefix).Subrouter()
extRouter.Use(authFunc)
extRouter.Methods("GET", "POST", "OPTIONS").
Handler(gqlHandler.NewDefaultServer(gql_generated.NewExecutableSchema(resConfig)))
}
}

View file

@ -19,7 +19,7 @@ func EnableSearchExtension(config *config.Config, log log.Logger, rootDir string
// SetupSearchRoutes ...
func SetupSearchRoutes(conf *config.Config, router *mux.Router,
storeController storage.StoreController, log log.Logger,
storeController storage.StoreController, authFunc mux.MiddlewareFunc, log log.Logger,
) {
log.Warn().Msg("skipping setting up search routes because given zot binary doesn't include this feature," +
"please build a binary that does so")