storage: add s3 backend support (without GC and dedupe)

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
This commit is contained in:
Petu Eusebiu
2021-07-17 06:53:05 +03:00
committed by Ramkumar Chinchani
parent 8e4d828867
commit 9c568c0ee2
15 changed files with 3534 additions and 1049 deletions
+2
View File
@@ -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
View File
@@ -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 {
+127
View File
@@ -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()