mirror of
https://github.com/project-zot/zot.git
synced 2026-06-16 04:17:55 +08:00
storage: add s3 backend support (without GC and dedupe)
Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
committed by
Ramkumar Chinchani
parent
8e4d828867
commit
9c568c0ee2
@@ -21,6 +21,7 @@ type StorageConfig struct {
|
||||
RootDirectory string
|
||||
GC bool
|
||||
Dedupe bool
|
||||
StorageDriver map[string]interface{} `mapstructure:",omitempty"`
|
||||
}
|
||||
|
||||
type TLSConfig struct {
|
||||
@@ -81,6 +82,7 @@ type GlobalStorageConfig struct {
|
||||
RootDirectory string
|
||||
Dedupe bool
|
||||
GC bool
|
||||
StorageDriver map[string]interface{} `mapstructure:",omitempty"`
|
||||
SubPaths map[string]StorageConfig
|
||||
}
|
||||
|
||||
|
||||
+43
-4
@@ -15,8 +15,11 @@ import (
|
||||
"github.com/anuvu/zot/pkg/extensions/monitoring"
|
||||
"github.com/anuvu/zot/pkg/log"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
"github.com/anuvu/zot/pkg/storage/s3"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/docker/distribution/registry/storage/driver/factory"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -62,6 +65,7 @@ func DefaultHeaders() mux.MiddlewareFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// nolint: gocyclo
|
||||
func (c *Controller) Run() error {
|
||||
// validate configuration
|
||||
if err := c.Config.Validate(c.Log); err != nil {
|
||||
@@ -107,8 +111,26 @@ func (c *Controller) Run() error {
|
||||
}
|
||||
}
|
||||
|
||||
defaultStore := storage.NewImageStore(c.Config.Storage.RootDirectory,
|
||||
c.Config.Storage.GC, c.Config.Storage.Dedupe, c.Log, c.Metrics)
|
||||
var defaultStore storage.ImageStore
|
||||
if len(c.Config.Storage.StorageDriver) == 0 {
|
||||
defaultStore = storage.NewImageStore(c.Config.Storage.RootDirectory,
|
||||
c.Config.Storage.GC, c.Config.Storage.Dedupe, c.Log, c.Metrics)
|
||||
} else {
|
||||
storeName := fmt.Sprintf("%v", c.Config.Storage.StorageDriver["name"])
|
||||
if storeName != storage.S3StorageDriverName {
|
||||
c.Log.Fatal().Err(errors.ErrBadConfig).Msgf("unsupported storage driver: %s",
|
||||
c.Config.Storage.StorageDriver["name"])
|
||||
}
|
||||
// Init a Storager from connection string.
|
||||
store, err := factory.Create(storeName, c.Config.Storage.StorageDriver)
|
||||
if err != nil {
|
||||
c.Log.Error().Err(err).Str("rootDir", c.Config.Storage.RootDirectory).Msg("unable to create s3 service")
|
||||
return err
|
||||
}
|
||||
|
||||
defaultStore = s3.NewImageStore(c.Config.Storage.RootDirectory,
|
||||
c.Config.Storage.GC, c.Config.Storage.Dedupe, c.Log, c.Metrics, store)
|
||||
}
|
||||
|
||||
c.StoreController.DefaultStore = defaultStore
|
||||
|
||||
@@ -141,8 +163,25 @@ func (c *Controller) Run() error {
|
||||
}
|
||||
}
|
||||
|
||||
subImageStore[route] = storage.NewImageStore(storageConfig.RootDirectory,
|
||||
storageConfig.GC, storageConfig.Dedupe, c.Log, c.Metrics)
|
||||
if len(storageConfig.StorageDriver) == 0 {
|
||||
subImageStore[route] = storage.NewImageStore(storageConfig.RootDirectory,
|
||||
storageConfig.GC, storageConfig.Dedupe, c.Log, c.Metrics)
|
||||
} else {
|
||||
storeName := fmt.Sprintf("%v", storageConfig.StorageDriver["name"])
|
||||
if storeName != storage.S3StorageDriverName {
|
||||
c.Log.Fatal().Err(errors.ErrBadConfig).Msgf("unsupported storage driver: %s", storageConfig.StorageDriver["name"])
|
||||
}
|
||||
|
||||
// Init a Storager from connection string.
|
||||
store, err := factory.Create(storeName, storageConfig.StorageDriver)
|
||||
if err != nil {
|
||||
c.Log.Error().Err(err).Str("rootDir", storageConfig.RootDirectory).Msg("Unable to create s3 service")
|
||||
return err
|
||||
}
|
||||
|
||||
subImageStore[route] = s3.NewImageStore(storageConfig.RootDirectory,
|
||||
storageConfig.GC, storageConfig.Dedupe, c.Log, c.Metrics, store)
|
||||
}
|
||||
|
||||
// Enable extensions if extension config is provided
|
||||
if c.Config != nil && c.Config.Extensions != nil {
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/anuvu/zot/errors"
|
||||
"github.com/anuvu/zot/pkg/api"
|
||||
"github.com/anuvu/zot/pkg/api/config"
|
||||
"github.com/anuvu/zot/pkg/storage"
|
||||
"github.com/chartmuseum/auth"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
@@ -123,6 +124,12 @@ func getCredString(username, password string) string {
|
||||
return usernameAndHash
|
||||
}
|
||||
|
||||
func skipIt(t *testing.T) {
|
||||
if os.Getenv("S3MOCK_ENDPOINT") == "" {
|
||||
t.Skip("Skipping testing without AWS S3 mock server")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
Convey("Make a new controller", t, func() {
|
||||
conf := config.New()
|
||||
@@ -131,6 +138,126 @@ func TestNew(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestObjectStorageController(t *testing.T) {
|
||||
skipIt(t)
|
||||
Convey("Negative make a new object storage controller", t, func() {
|
||||
port := getFreePort()
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
storageDriverParams := map[string]interface{}{
|
||||
"rootDir": "zot",
|
||||
"name": storage.S3StorageDriverName,
|
||||
}
|
||||
conf.Storage.StorageDriver = storageDriverParams
|
||||
c := api.NewController(conf)
|
||||
So(c, ShouldNotBeNil)
|
||||
|
||||
c.Config.Storage.RootDirectory = "zot"
|
||||
|
||||
err := c.Run()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Make a new object storage controller", t, func() {
|
||||
port := getFreePort()
|
||||
baseURL := getBaseURL(port, false)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
bucket := "zot-storage-test"
|
||||
endpoint := os.Getenv("S3MOCK_ENDPOINT")
|
||||
|
||||
storageDriverParams := map[string]interface{}{
|
||||
"rootDir": "zot",
|
||||
"name": storage.S3StorageDriverName,
|
||||
"region": "us-east-2",
|
||||
"bucket": bucket,
|
||||
"regionendpoint": endpoint,
|
||||
"secure": false,
|
||||
"skipverify": false,
|
||||
}
|
||||
conf.Storage.StorageDriver = storageDriverParams
|
||||
c := api.NewController(conf)
|
||||
So(c, ShouldNotBeNil)
|
||||
|
||||
c.Config.Storage.RootDirectory = "/"
|
||||
|
||||
go func(controller *api.Controller) {
|
||||
// this blocks
|
||||
if err := controller.Run(); err != nil {
|
||||
return
|
||||
}
|
||||
}(c)
|
||||
|
||||
// wait till ready
|
||||
for {
|
||||
_, err := resty.R().Get(baseURL)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
defer func(controller *api.Controller) {
|
||||
ctx := context.Background()
|
||||
_ = controller.Server.Shutdown(ctx)
|
||||
}(c)
|
||||
})
|
||||
}
|
||||
|
||||
func TestObjectStorageControllerSubPaths(t *testing.T) {
|
||||
skipIt(t)
|
||||
Convey("Make a new object storage controller", t, func() {
|
||||
port := getFreePort()
|
||||
baseURL := getBaseURL(port, false)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
bucket := "zot-storage-test"
|
||||
endpoint := os.Getenv("S3MOCK_ENDPOINT")
|
||||
|
||||
storageDriverParams := map[string]interface{}{
|
||||
"rootDir": "zot",
|
||||
"name": storage.S3StorageDriverName,
|
||||
"region": "us-east-2",
|
||||
"bucket": bucket,
|
||||
"regionendpoint": endpoint,
|
||||
"secure": false,
|
||||
"skipverify": false,
|
||||
}
|
||||
conf.Storage.StorageDriver = storageDriverParams
|
||||
c := api.NewController(conf)
|
||||
So(c, ShouldNotBeNil)
|
||||
|
||||
c.Config.Storage.RootDirectory = "zot"
|
||||
subPathMap := make(map[string]config.StorageConfig)
|
||||
subPathMap["/a"] = config.StorageConfig{
|
||||
RootDirectory: "/a",
|
||||
StorageDriver: storageDriverParams,
|
||||
}
|
||||
c.Config.Storage.SubPaths = subPathMap
|
||||
|
||||
go func(controller *api.Controller) {
|
||||
// this blocks
|
||||
if err := controller.Run(); err != nil {
|
||||
return
|
||||
}
|
||||
}(c)
|
||||
|
||||
for {
|
||||
_, err := resty.R().Get(baseURL)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
defer func(controller *api.Controller) {
|
||||
ctx := context.Background()
|
||||
_ = controller.Server.Shutdown(ctx)
|
||||
}(c)
|
||||
})
|
||||
}
|
||||
|
||||
func TestHtpasswdSingleCred(t *testing.T) {
|
||||
Convey("Single cred", t, func() {
|
||||
port := getFreePort()
|
||||
|
||||
Reference in New Issue
Block a user