Skip to content

Commit

Permalink
feat(userprefs): update documentation and list extensions endpoint (#…
Browse files Browse the repository at this point in the history
…1456)

Signed-off-by: Laurentiu Niculae <[email protected]>
  • Loading branch information
laurentiuNiculae authored May 25, 2023
1 parent 970997f commit 2b8479f
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 56 deletions.
18 changes: 8 additions & 10 deletions pkg/api/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7249,11 +7249,12 @@ func TestDistSpecExtensions(t *testing.T) {
err = json.Unmarshal(resp.Body(), &extensionList)
So(err, ShouldBeNil)
So(len(extensionList.Extensions), ShouldEqual, 1)
So(len(extensionList.Extensions[0].Endpoints), ShouldEqual, 1)
So(len(extensionList.Extensions[0].Endpoints), ShouldEqual, 2)
So(extensionList.Extensions[0].Name, ShouldEqual, "_zot")
So(extensionList.Extensions[0].URL, ShouldContainSubstring, "_zot.md")
So(extensionList.Extensions[0].Description, ShouldNotBeEmpty)
So(extensionList.Extensions[0].Endpoints[0], ShouldEqual, constants.FullSearchPrefix)
So(extensionList.Extensions[0].Endpoints, ShouldContain, constants.FullSearchPrefix)
So(extensionList.Extensions[0].Endpoints, ShouldContain, constants.FullUserPreferencesPrefix)
})

Convey("start zot server with search and mgmt extensions", t, func(c C) {
Expand Down Expand Up @@ -7297,17 +7298,14 @@ func TestDistSpecExtensions(t *testing.T) {
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), &extensionList)
So(err, ShouldBeNil)
So(len(extensionList.Extensions), ShouldEqual, 2)
So(len(extensionList.Extensions[0].Endpoints), ShouldEqual, 1)
So(len(extensionList.Extensions[1].Endpoints), ShouldEqual, 1)
So(len(extensionList.Extensions), ShouldEqual, 1)
So(len(extensionList.Extensions[0].Endpoints), ShouldEqual, 3)
So(extensionList.Extensions[0].Name, ShouldEqual, "_zot")
So(extensionList.Extensions[0].URL, ShouldContainSubstring, "_zot.md")
So(extensionList.Extensions[0].Description, ShouldNotBeEmpty)
So(extensionList.Extensions[0].Endpoints[0], ShouldEqual, constants.FullSearchPrefix)
So(extensionList.Extensions[1].Name, ShouldEqual, "_zot")
So(extensionList.Extensions[1].URL, ShouldContainSubstring, "_zot.md")
So(extensionList.Extensions[1].Description, ShouldNotBeEmpty)
So(extensionList.Extensions[1].Endpoints[0], ShouldEqual, constants.FullMgmtPrefix)
So(extensionList.Extensions[0].Endpoints, ShouldContain, constants.FullSearchPrefix)
So(extensionList.Extensions[0].Endpoints, ShouldContain, constants.FullUserPreferencesPrefix)
So(extensionList.Extensions[0].Endpoints, ShouldContain, constants.FullMgmtPrefix)
})

Convey("start minimal zot server", t, func(c C) {
Expand Down
1 change: 1 addition & 0 deletions pkg/extensions/_zot.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Component | Endpoint | Description
--- | --- | ---
[`search`](search/search.md) | `/v2/_zot/ext/search` | efficient and enhanced registry search capabilities using graphQL backend
[`mgmt`](mgmt.md) | `/v2/_zot/ext/mgmt` | config management
[`userprefs`](userprefs.md) | `/v2/_zot/ext/userprefs` | change user preferences


# References
Expand Down
4 changes: 4 additions & 0 deletions pkg/extensions/extension_mgmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ type StrippedConfig struct {
} `json:"http" mapstructure:"http"`
}

func IsBuiltWithMGMTExtension() bool {
return true
}

func (auth Auth) MarshalJSON() ([]byte, error) {
type localAuth Auth

Expand Down
4 changes: 4 additions & 0 deletions pkg/extensions/extension_mgmt_disabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"zotregistry.io/zot/pkg/log"
)

func IsBuiltWithMGMTExtension() bool {
return false
}

func SetupMgmtRoutes(config *config.Config, router *mux.Router, log log.Logger) {
log.Warn().Msg("skipping setting up mgmt routes because given zot binary doesn't include this feature," +
"please build a binary that does so")
Expand Down
44 changes: 4 additions & 40 deletions pkg/extensions/extension_search.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

gqlHandler "github.com/99designs/gqlgen/graphql/handler"
"github.com/gorilla/mux"
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"

"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/api/constants"
Expand All @@ -34,6 +33,10 @@ const (
done
)

func IsBuiltWithSearchExtension() bool {
return true
}

func GetCVEInfo(config *config.Config, storeController storage.StoreController,
repoDB repodb.RepoDB, log log.Logger,
) CveInfo {
Expand Down Expand Up @@ -199,42 +202,3 @@ func SearchACHeadersHandler() mux.MiddlewareFunc {
})
}
}

func getExtension(name, url, description string, endpoints []string) distext.Extension {
return distext.Extension{
Name: name,
URL: url,
Description: description,
Endpoints: endpoints,
}
}

func GetExtensions(config *config.Config) distext.ExtensionList {
extensionList := distext.ExtensionList{}

extensions := make([]distext.Extension, 0)

if config.Extensions != nil && config.Extensions.Search != nil {
endpoints := []string{constants.FullSearchPrefix}
searchExt := getExtension("_zot",
"https://github.com/project-zot/zot/blob/"+config.ReleaseTag+"/pkg/extensions/_zot.md",
"zot registry extensions",
endpoints)

extensions = append(extensions, searchExt)
}

if config.Extensions != nil && config.Extensions.Mgmt != nil {
endpoints := []string{constants.FullMgmtPrefix}
mgmtExt := getExtension("_zot",
"https://github.com/project-zot/zot/blob/"+config.ReleaseTag+"/pkg/extensions/_zot.md",
"zot registry extensions",
endpoints)

extensions = append(extensions, mgmtExt)
}

extensionList.Extensions = extensions

return extensionList
}
10 changes: 4 additions & 6 deletions pkg/extensions/extension_search_disabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package extensions

import (
"github.com/gorilla/mux"
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"

"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/log"
Expand All @@ -22,6 +21,10 @@ func GetCVEInfo(config *config.Config, storeController storage.StoreController,
return nil
}

func IsBuiltWithSearchExtension() bool {
return false
}

// EnableSearchExtension ...
func EnableSearchExtension(config *config.Config, storeController storage.StoreController,
repoDB repodb.RepoDB, scheduler *scheduler.Scheduler, cveInfo CveInfo, log log.Logger,
Expand All @@ -37,8 +40,3 @@ func SetupSearchRoutes(config *config.Config, router *mux.Router, storeControlle
log.Warn().Msg("skipping setting up search routes because given zot binary doesn't include this feature," +
"please build a binary that does so")
}

// GetExtensions...
func GetExtensions(config *config.Config) distext.ExtensionList {
return distext.ExtensionList{}
}
4 changes: 4 additions & 0 deletions pkg/extensions/extension_userprefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ const (
ToggleRepoStarAction = "toggleStar"
)

func IsBuiltWithUserPrefsExtension() bool {
return true
}

func SetupUserPreferencesRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
repoDB repodb.RepoDB, cveInfo CveInfo, log log.Logger,
) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/extensions/extension_userprefs_disable.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import (
"zotregistry.io/zot/pkg/storage"
)

func IsBuiltWithUserPrefsExtension() bool {
return false
}

func SetupUserPreferencesRoutes(config *config.Config, router *mux.Router, storeController storage.StoreController,
repoDB repodb.RepoDB, cveInfo CveInfo, log log.Logger,
) {
Expand Down
42 changes: 42 additions & 0 deletions pkg/extensions/get_extensions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package extensions

import (
distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"

"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/api/constants"
)

func GetExtensions(config *config.Config) distext.ExtensionList {
extensionList := distext.ExtensionList{}

endpoints := []string{}
extensions := []distext.Extension{}

if config.Extensions != nil && config.Extensions.Search != nil {
if IsBuiltWithSearchExtension() {
endpoints = append(endpoints, constants.FullSearchPrefix)
}

if IsBuiltWithUserPrefsExtension() {
endpoints = append(endpoints, constants.FullUserPreferencesPrefix)
}
}

if IsBuiltWithMGMTExtension() && config.Extensions != nil && config.Extensions.Mgmt != nil {
endpoints = append(endpoints, constants.FullMgmtPrefix)
}

if len(endpoints) > 0 {
extensions = append(extensions, distext.Extension{
Name: "_zot",
URL: "https://github.com/project-zot/zot/blob/" + config.ReleaseTag + "/pkg/extensions/_zot.md",
Description: "zot registry extensions",
Endpoints: endpoints,
})
}

extensionList.Extensions = extensions

return extensionList
}
76 changes: 76 additions & 0 deletions pkg/extensions/get_extensions_disabled_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//go:build !search && !mgmt && !userprefs

package extensions_test

import (
"encoding/json"
"os"
"testing"

distext "github.com/opencontainers/distribution-spec/specs-go/v1/extensions"
. "github.com/smartystreets/goconvey/convey"
"gopkg.in/resty.v1"

"zotregistry.io/zot/pkg/api"
"zotregistry.io/zot/pkg/api/config"
"zotregistry.io/zot/pkg/api/constants"
extconf "zotregistry.io/zot/pkg/extensions/config"
"zotregistry.io/zot/pkg/test"
)

func TestGetExensionsDisabled(t *testing.T) {
Convey("start zot server with extensions but no extensions built", t, func(c C) {
conf := config.New()
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)

conf.HTTP.Port = port

defaultVal := true

searchConfig := &extconf.SearchConfig{
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
}

mgmtConfg := &extconf.MgmtConfig{
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
}

conf.Extensions = &extconf.ExtensionConfig{
Search: searchConfig,
Mgmt: mgmtConfg,
}

logFile, err := os.CreateTemp("", "zot-log*.txt")
So(err, ShouldBeNil)
conf.Log.Output = logFile.Name()
defer os.Remove(logFile.Name()) // clean up

ctlr := makeController(conf, t.TempDir(), "")

cm := test.NewControllerManager(ctlr)
cm.StartAndWait(port)
defer cm.StopServer()

var extensionList distext.ExtensionList

resp, err := resty.R().Get(baseURL + constants.RoutePrefix + constants.ExtOciDiscoverPrefix)
So(err, ShouldBeNil)
So(resp, ShouldNotBeNil)
So(resp.StatusCode(), ShouldEqual, 200)
err = json.Unmarshal(resp.Body(), &extensionList)
So(err, ShouldBeNil)
So(len(extensionList.Extensions), ShouldEqual, 0)
})
}

func makeController(conf *config.Config, dir string, copyTestDataDest string) *api.Controller {
ctlr := api.NewController(conf)

if copyTestDataDest != "" {
test.CopyTestFiles(copyTestDataDest, dir)
}
ctlr.Config.Storage.RootDirectory = dir

return ctlr
}
31 changes: 31 additions & 0 deletions pkg/extensions/userprefs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# `userprefs`

`userprefs` component provides an endpoint for adding user preferences for repos. It is available only to authentificated users. Unauthentificated users will be denied access.

| Supported queries | Input | Output | Description |
| --- | --- | --- | --- |
| [Toggle repo star](#toggle-repo-star) | None | None | Sets the repo starred property to true if it is false, and to false if it is true |
| [Toggle repo bookmark](#toggle-repo-bookmark) | None | None | Sets the repo bookmarked property to true if it is false, and to false if it is true |

## General usage
The userprefs endpoint accepts as a query parameter what `action` to perform and then all other required parameters for the specified action.

## Toggle repo star
| Action | Parameter | Parameter Type | Parameter Description |
| --- | --- | --- | --- |
| toggleStar | repo | string | The repo name which should be starred |

A request to togle a star on a repo would look like this:
```
(PUT) http://localhost:8080/v2/_zot/ext/userprefs?action=toggleStar&repo=repoName
```

## Toggle repo bookmark
| Action | Parameter | Parameter Type | Parameter Description |
| --- | --- | --- | --- |
| toggleBookmark | repo | string | The repo name which should be bookmarked |

A request to togle a bookmark on a repo would look like this:
```
(PUT) http://localhost:8080/v2/_zot/ext/userprefs?action=toggleBookmark&repo=repoName
```

0 comments on commit 2b8479f

Please sign in to comment.