From ed4954ab0d4949c13746861318e3e8c7d0724c08 Mon Sep 17 00:00:00 2001 From: Andrei Aaron Date: Thu, 23 Feb 2023 22:28:08 +0200 Subject: [PATCH] build(ui): the ui is now included in the zot binary by default (#1202) Update the default value of the EXTENSIONS variable in the makefile. Also cleanup binary-ui and other make targets assuming the UI was not included by default. Enable the ui by default in the zot container image Swith back to using the distroless images, as c3 only has amd64 images. Fix updating security events in github (permission issue) Add an integration test for the UI extension Rename ui extension files to use _ instead of - feat(ui): upgrade to zui v2.0.0-rc3 Signed-off-by: Andrei Aaron --- .github/workflows/ci-cd.yml | 8 +- Makefile | 12 +- build/stacker-minimal.yaml | 62 ++++++++++ build/stacker.yaml | 13 ++- .../{extension-ui.go => extension_ui.go} | 0 ...i-disabled.go => extension_ui_disabled.go} | 0 pkg/extensions/extension_ui_test.go | 106 ++++++++++++++++++ 7 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 build/stacker-minimal.yaml rename pkg/extensions/{extension-ui.go => extension_ui.go} (100%) rename pkg/extensions/{extension-ui-disabled.go => extension_ui_disabled.go} (100%) create mode 100644 pkg/extensions/extension_ui_test.go diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 55eae48d..5f907d67 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -106,7 +106,7 @@ jobs: make OS=$OS ARCH=$ARCH sudo env "PATH=$PATH" make privileged-test else - make OS=$OS ARCH=$ARCH binary binary-minimal binary-debug binary-ui cli bench exporter-minimal + make OS=$OS ARCH=$ARCH binary binary-minimal binary-debug cli bench exporter-minimal fi env: S3MOCK_ENDPOINT: localhost:4566 @@ -142,6 +142,10 @@ jobs: if: github.event_name == 'release' && github.event.action== 'published' name: Push OCI images to GitHub Packages runs-on: ubuntu-latest + permissions: + contents: read + security-events: write + packages: write strategy: matrix: os: [linux, darwin] @@ -204,7 +208,7 @@ jobs: - name: Build and push zot-minimal container image uses: project-stacker/stacker-build-push-action@main with: - file: 'build/stacker.yaml' + file: 'build/stacker-minimal.yaml' build-args: | RELEASE_TAG=${{ github.event.release.tag_name }} COMMIT=${{ github.event.release.tag_name }}-${{ github.sha }} diff --git a/Makefile b/Makefile index 21e90948..e1293a9b 100644 --- a/Makefile +++ b/Makefile @@ -21,20 +21,20 @@ REGCLIENT := $(TOOLSDIR)/bin/regctl REGCLIENT_VERSION := v0.4.5 ACTION_VALIDATOR := $(TOOLSDIR)/bin/action-validator ACTION_VALIDATOR_VERSION := v0.2.1 -ZUI_VERSION := v2.0.0-rc2 +ZUI_VERSION := v2.0.0-rc3 STACKER := $(TOOLSDIR)/bin/stacker BATS := $(TOOLSDIR)/bin/bats TESTDATA := $(TOP_LEVEL)/test/data OS ?= linux ARCH ?= amd64 BENCH_OUTPUT ?= stdout -EXTENSIONS ?= sync,search,scrub,metrics,lint +EXTENSIONS ?= sync,search,scrub,metrics,lint,ui comma:= , hyphen:= - extended-name:= .PHONY: all -all: modcheck swagger binary binary-minimal binary-debug binary-ui cli bench exporter-minimal verify-config test covhtml check check-gh-actions +all: modcheck swagger binary binary-minimal binary-debug cli bench exporter-minimal verify-config test covhtml check check-gh-actions .PHONY: modcheck modcheck: @@ -68,10 +68,6 @@ binary-debug: $(if $(findstring ui,$(EXTENSIONS)), ui) binary-debug: modcheck swagger create-name build-metadata env CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -o bin/zot-$(OS)-$(ARCH)-debug -buildmode=pie -tags $(EXTENSIONS),debug,containers_image_openpgp -v -gcflags all='-N -l' -ldflags "-X zotregistry.io/zot/pkg/api/config.ReleaseTag=${RELEASE_TAG} -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}" ./cmd/zot -.PHONY: binary-ui -binary-ui: modcheck create-name build-metadata ui - env CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -o bin/zot-$(OS)-$(ARCH)-ui -buildmode=pie -tags $(EXTENSIONS),ui,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: cli cli: modcheck create-name build-metadata env CGO_ENABLED=0 GOOS=$(OS) GOARCH=$(ARCH) go build -o bin/zli-$(OS)-$(ARCH) -buildmode=pie -tags $(EXTENSIONS),search,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/zli @@ -166,7 +162,7 @@ check: ./golangcilint.yaml $(GOLINTER) mkdir -p pkg/extensions/build; touch pkg/extensions/build/.empty $(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 $(EXTENSIONS),containers_image_openpgp,ui,debug ./... + $(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags $(EXTENSIONS),containers_image_openpgp,debug ./... $(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags dev,containers_image_openpgp ./... $(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags dev,$(EXTENSIONS),containers_image_openpgp ./... $(GOLINTER) --config ./golangcilint.yaml run --enable-all --out-format=colored-line-number --build-tags stress,$(EXTENSIONS),containers_image_openpgp ./... diff --git a/build/stacker-minimal.yaml b/build/stacker-minimal.yaml new file mode 100644 index 00000000..279d23bf --- /dev/null +++ b/build/stacker-minimal.yaml @@ -0,0 +1,62 @@ +build: + from: + type: docker + url: docker://ghcr.io/project-zot/golang:1.19 + binds: + - ../. -> /zotcopy + run: | + export GO111MODULE=on + export GOPATH='/go' + export HOME='/root' + export PATH='/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' + mkdir -p /go/src/github.com/project-zot + cd /go/src/github.com/project-zot + git clone /zotcopy zot + cd /go/src/github.com/project-zot/zot + make COMMIT=${{COMMIT}} OS=${{OS}} ARCH=${{ARCH}} RELEASE_TAG=${{RELEASE_TAG}} clean binary${{EXT:}} + cat > config.json << EOF + { + "storage":{ + "rootDirectory":"/var/lib/registry" + }, + "http":{ + "address":"0.0.0.0", + "port":"5000" + }, + "log":{ + "level":"debug" + } + } + EOF + + cat config.json + mkdir -p /zotcopy/.build/${{REPO_NAME}} + cd /zotcopy/.build/${{REPO_NAME}} + + mkdir -p binary/ cert/ config/ + + cp /go/src/github.com/project-zot/zot/bin/zot-${{OS}}-${{ARCH}}${{EXT:}} binary/ + cp /go/src/github.com/project-zot/zot/config.json config/ + cp /etc/ssl/certs/ca-certificates.crt cert/ + build_only: true + +"${{REPO_NAME:zot}}": + os: ${{OS}} + arch: ${{ARCH}} + from: + type: docker + url: docker://gcr.io/distroless/base:latest-${{ARCH}} + overlay_dirs: + - source: ../.build/${{REPO_NAME}}/binary + dest: /usr/local/bin + - source: ../.build/${{REPO_NAME}}/cert + dest: /etc/ssl/certs + - source: ../.build/${{REPO_NAME}}/config + dest: /etc/zot + entrypoint: + - /usr/local/bin/zot-${{OS}}-${{ARCH}}${{EXT:}} + volumes: + - /var/lib/registry + cmd: + - serve + - /etc/zot/config.json diff --git a/build/stacker.yaml b/build/stacker.yaml index 65a26ef3..6a10ed8a 100644 --- a/build/stacker.yaml +++ b/build/stacker.yaml @@ -25,6 +25,17 @@ build: }, "log":{ "level":"debug" + }, + "extensions": { + "search": { + "enable": true, + "cve": { + "updateInterval": "2h" + } + }, + "ui": { + "enable": true + } } } EOF @@ -45,7 +56,7 @@ build: arch: ${{ARCH}} from: type: docker - url: docker://zothub.io/c3/base:jammy + url: docker://gcr.io/distroless/base:latest-${{ARCH}} overlay_dirs: - source: ../.build/${{REPO_NAME}}/binary dest: /usr/local/bin diff --git a/pkg/extensions/extension-ui.go b/pkg/extensions/extension_ui.go similarity index 100% rename from pkg/extensions/extension-ui.go rename to pkg/extensions/extension_ui.go diff --git a/pkg/extensions/extension-ui-disabled.go b/pkg/extensions/extension_ui_disabled.go similarity index 100% rename from pkg/extensions/extension-ui-disabled.go rename to pkg/extensions/extension_ui_disabled.go diff --git a/pkg/extensions/extension_ui_test.go b/pkg/extensions/extension_ui_test.go new file mode 100644 index 00000000..82df5c84 --- /dev/null +++ b/pkg/extensions/extension_ui_test.go @@ -0,0 +1,106 @@ +//go:build search && ui +// +build search,ui + +package extensions_test + +import ( + "io" + "net/http" + "os" + "testing" + "time" + + . "github.com/smartystreets/goconvey/convey" + "gopkg.in/resty.v1" + + "zotregistry.io/zot/pkg/api" + "zotregistry.io/zot/pkg/api/config" + extconf "zotregistry.io/zot/pkg/extensions/config" + "zotregistry.io/zot/pkg/test" +) + +func TestUIExtension(t *testing.T) { + Convey("Verify zot with UI extension starts successfully", t, func() { + conf := config.New() + port := test.GetFreePort() + baseURL := test.GetBaseURL(port) + conf.HTTP.Port = port + + // we won't use the logging config feature as we want logs in both + // stdout and a file + logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") + So(err, ShouldBeNil) + logPath := logFile.Name() + defer os.Remove(logPath) + + writers := io.MultiWriter(os.Stdout, logFile) + + defaultValue := true + + conf.Extensions = &extconf.ExtensionConfig{} + conf.Extensions.UI = &extconf.UIConfig{ + BaseConfig: extconf.BaseConfig{Enable: &defaultValue}, + } + conf.Storage.RootDirectory = t.TempDir() + + ctlr := api.NewController(conf) + ctlr.Log.Logger = ctlr.Log.Output(writers) + + ctlrManager := test.NewControllerManager(ctlr) + ctlrManager.StartAndWait(port) + + found, err := test.ReadLogFileAndSearchString(logPath, "\"UI\":{\"Enable\":true}", 2*time.Minute) + So(found, ShouldBeTrue) + So(err, ShouldBeNil) + + found, err = test.ReadLogFileAndSearchString(logPath, "setting up ui routes", 2*time.Minute) + So(found, ShouldBeTrue) + So(err, ShouldBeNil) + + cfg, layers, manifest, err := test.GetImageComponents(1) + So(err, ShouldBeNil) + + repoName := "test-repo" + tagName := "test-tag" + + // Upload a test image + err = test.UploadImage( + test.Image{ + Config: cfg, + Layers: layers, + Manifest: manifest, + Tag: tagName, + }, baseURL, repoName) + So(err, ShouldBeNil) + + resp, err := resty.R().Get(baseURL + "/home") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + resp, err = resty.R().Get(baseURL + "/image/") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + resp, err = resty.R().Get(baseURL + "/image/" + repoName) + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + resp, err = resty.R().Get(baseURL + "/image/" + repoName + "/tag/") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + resp, err = resty.R().Get(baseURL + "/image/" + repoName + "/tag/" + tagName) + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + resp, err = resty.R().Get(baseURL + "/badurl/") + So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + }) +}