Skip to content

Commit e4e85a3

Browse files
Storage configuration support [storage] (#13314)
* Fix minio bug * Add tests for storage configuration * Change the Seek flag to keep compitable minio? * Fix test when first-byte-pos of all ranges is greater than the resource length Co-authored-by: techknowlogick <[email protected]>
1 parent e7750e0 commit e4e85a3

File tree

6 files changed

+62
-33
lines changed

6 files changed

+62
-33
lines changed

integrations/integration_test.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"encoding/json"
1212
"fmt"
1313
"io"
14-
"log"
1514
"net/http"
1615
"net/http/cookiejar"
1716
"net/http/httptest"
@@ -27,8 +26,10 @@ import (
2726
"code.gitea.io/gitea/models"
2827
"code.gitea.io/gitea/modules/base"
2928
"code.gitea.io/gitea/modules/graceful"
29+
"code.gitea.io/gitea/modules/log"
3030
"code.gitea.io/gitea/modules/queue"
3131
"code.gitea.io/gitea/modules/setting"
32+
"code.gitea.io/gitea/modules/storage"
3233
"code.gitea.io/gitea/modules/util"
3334
"code.gitea.io/gitea/routers"
3435
"code.gitea.io/gitea/routers/routes"
@@ -59,6 +60,8 @@ func NewNilResponseRecorder() *NilResponseRecorder {
5960
}
6061

6162
func TestMain(m *testing.M) {
63+
defer log.Close()
64+
6265
managerCtx, cancel := context.WithCancel(context.Background())
6366
graceful.InitManager(managerCtx)
6467
defer cancel()
@@ -142,34 +145,38 @@ func initIntegrationTest() {
142145
util.RemoveAll(models.LocalCopyPath())
143146
setting.CheckLFSVersion()
144147
setting.InitDBConfig()
148+
if err := storage.Init(); err != nil {
149+
fmt.Printf("Init storage failed: %v", err)
150+
os.Exit(1)
151+
}
145152

146153
switch {
147154
case setting.Database.UseMySQL:
148155
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
149156
setting.Database.User, setting.Database.Passwd, setting.Database.Host))
150157
defer db.Close()
151158
if err != nil {
152-
log.Fatalf("sql.Open: %v", err)
159+
log.Fatal("sql.Open: %v", err)
153160
}
154161
if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", setting.Database.Name)); err != nil {
155-
log.Fatalf("db.Exec: %v", err)
162+
log.Fatal("db.Exec: %v", err)
156163
}
157164
case setting.Database.UsePostgreSQL:
158165
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
159166
setting.Database.User, setting.Database.Passwd, setting.Database.Host, setting.Database.SSLMode))
160167
defer db.Close()
161168
if err != nil {
162-
log.Fatalf("sql.Open: %v", err)
169+
log.Fatal("sql.Open: %v", err)
163170
}
164171
dbrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM pg_database WHERE datname = '%s'", setting.Database.Name))
165172
if err != nil {
166-
log.Fatalf("db.Query: %v", err)
173+
log.Fatal("db.Query: %v", err)
167174
}
168175
defer dbrows.Close()
169176

170177
if !dbrows.Next() {
171178
if _, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", setting.Database.Name)); err != nil {
172-
log.Fatalf("db.Exec: CREATE DATABASE: %v", err)
179+
log.Fatal("db.Exec: CREATE DATABASE: %v", err)
173180
}
174181
}
175182
// Check if we need to setup a specific schema
@@ -183,18 +190,18 @@ func initIntegrationTest() {
183190
// This is a different db object; requires a different Close()
184191
defer db.Close()
185192
if err != nil {
186-
log.Fatalf("sql.Open: %v", err)
193+
log.Fatal("sql.Open: %v", err)
187194
}
188195
schrows, err := db.Query(fmt.Sprintf("SELECT 1 FROM information_schema.schemata WHERE schema_name = '%s'", setting.Database.Schema))
189196
if err != nil {
190-
log.Fatalf("db.Query: %v", err)
197+
log.Fatal("db.Query: %v", err)
191198
}
192199
defer schrows.Close()
193200

194201
if !schrows.Next() {
195202
// Create and setup a DB schema
196203
if _, err = db.Exec(fmt.Sprintf("CREATE SCHEMA %s", setting.Database.Schema)); err != nil {
197-
log.Fatalf("db.Exec: CREATE SCHEMA: %v", err)
204+
log.Fatal("db.Exec: CREATE SCHEMA: %v", err)
198205
}
199206
}
200207

@@ -203,10 +210,10 @@ func initIntegrationTest() {
203210
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
204211
host, port, "master", setting.Database.User, setting.Database.Passwd))
205212
if err != nil {
206-
log.Fatalf("sql.Open: %v", err)
213+
log.Fatal("sql.Open: %v", err)
207214
}
208215
if _, err := db.Exec(fmt.Sprintf("If(db_id(N'%s') IS NULL) BEGIN CREATE DATABASE %s; END;", setting.Database.Name, setting.Database.Name)); err != nil {
209-
log.Fatalf("db.Exec: %v", err)
216+
log.Fatal("db.Exec: %v", err)
210217
}
211218
defer db.Close()
212219
}

integrations/lfs_getobject_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ func storeAndGetLfs(t *testing.T, content *[]byte, extraHeader *http.Header, exp
7878
}
7979
}
8080
}
81+
8182
resp := session.MakeRequest(t, req, expectedStatus)
8283

8384
return resp
@@ -210,7 +211,7 @@ func TestGetLFSRange(t *testing.T) {
210211
{"bytes=0-10", "123456789\n", http.StatusPartialContent},
211212
// end-range bigger than length-1 is ignored
212213
{"bytes=0-11", "123456789\n", http.StatusPartialContent},
213-
{"bytes=11-", "", http.StatusPartialContent},
214+
{"bytes=11-", "Requested Range Not Satisfiable", http.StatusRequestedRangeNotSatisfiable},
214215
// incorrect header value cause whole header to be ignored
215216
{"bytes=-", "123456789\n", http.StatusOK},
216217
{"foobar", "123456789\n", http.StatusOK},

integrations/mysql.ini.tmpl

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -45,27 +45,28 @@ START_SSH_SERVER = true
4545
OFFLINE_MODE = false
4646

4747
LFS_START_SERVER = true
48-
LFS_CONTENT_PATH = integrations/gitea-integration-mysql/datalfs-mysql
4948
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
50-
LFS_STORE_TYPE = minio
51-
LFS_SERVE_DIRECT = false
52-
LFS_MINIO_ENDPOINT = minio:9000
53-
LFS_MINIO_ACCESS_KEY_ID = 123456
54-
LFS_MINIO_SECRET_ACCESS_KEY = 12345678
55-
LFS_MINIO_BUCKET = gitea
56-
LFS_MINIO_LOCATION = us-east-1
57-
LFS_MINIO_BASE_PATH = lfs/
58-
LFS_MINIO_USE_SSL = false
49+
50+
[lfs]
51+
MINIO_BASE_PATH = lfs/
5952

6053
[attachment]
54+
MINIO_BASE_PATH = attachments/
55+
56+
[avatars]
57+
MINIO_BASE_PATH = avatars/
58+
59+
[repo-avatars]
60+
MINIO_BASE_PATH = repo-avatars/
61+
62+
[storage]
6163
STORAGE_TYPE = minio
6264
SERVE_DIRECT = false
6365
MINIO_ENDPOINT = minio:9000
6466
MINIO_ACCESS_KEY_ID = 123456
6567
MINIO_SECRET_ACCESS_KEY = 12345678
6668
MINIO_BUCKET = gitea
6769
MINIO_LOCATION = us-east-1
68-
MINIO_BASE_PATH = attachments/
6970
MINIO_USE_SSL = false
7071

7172
[mailer]
@@ -88,9 +89,6 @@ ENABLE_NOTIFY_MAIL = true
8889
DISABLE_GRAVATAR = false
8990
ENABLE_FEDERATED_AVATAR = false
9091

91-
AVATAR_UPLOAD_PATH = integrations/gitea-integration-mysql/data/avatars
92-
REPOSITORY_AVATAR_UPLOAD_PATH = integrations/gitea-integration-mysql/data/repo-avatars
93-
9492
[session]
9593
PROVIDER = file
9694
PROVIDER_CONFIG = integrations/gitea-integration-mysql/data/sessions

modules/lfs/content_store.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"crypto/sha256"
99
"encoding/hex"
1010
"errors"
11+
"fmt"
1112
"io"
1213
"os"
1314

@@ -21,6 +22,21 @@ var (
2122
errSizeMismatch = errors.New("Content size does not match")
2223
)
2324

25+
// ErrRangeNotSatisfiable represents an error which request range is not satisfiable.
26+
type ErrRangeNotSatisfiable struct {
27+
FromByte int64
28+
}
29+
30+
func (err ErrRangeNotSatisfiable) Error() string {
31+
return fmt.Sprintf("Requested range %d is not satisfiable", err.FromByte)
32+
}
33+
34+
// IsErrRangeNotSatisfiable returns true if the error is an ErrRangeNotSatisfiable
35+
func IsErrRangeNotSatisfiable(err error) bool {
36+
_, ok := err.(ErrRangeNotSatisfiable)
37+
return ok
38+
}
39+
2440
// ContentStore provides a simple file system based storage.
2541
type ContentStore struct {
2642
storage.ObjectStorage
@@ -35,7 +51,12 @@ func (s *ContentStore) Get(meta *models.LFSMetaObject, fromByte int64) (io.ReadC
3551
return nil, err
3652
}
3753
if fromByte > 0 {
38-
_, err = f.Seek(fromByte, os.SEEK_CUR)
54+
if fromByte >= meta.Size {
55+
return nil, ErrRangeNotSatisfiable{
56+
FromByte: fromByte,
57+
}
58+
}
59+
_, err = f.Seek(fromByte, io.SeekStart)
3960
if err != nil {
4061
log.Error("Whilst trying to read LFS OID[%s]: Unable to seek to %d Error: %v", meta.Oid, fromByte, err)
4162
}

modules/lfs/server.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,12 @@ func getContentHandler(ctx *context.Context) {
191191
contentStore := &ContentStore{ObjectStorage: storage.LFS}
192192
content, err := contentStore.Get(meta, fromByte)
193193
if err != nil {
194-
// Errors are logged in contentStore.Get
195-
writeStatus(ctx, 404)
194+
if IsErrRangeNotSatisfiable(err) {
195+
writeStatus(ctx, http.StatusRequestedRangeNotSatisfiable)
196+
} else {
197+
// Errors are logged in contentStore.Get
198+
writeStatus(ctx, 404)
199+
}
196200
return
197201
}
198202
defer content.Close()

modules/setting/storage.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,12 @@ func (s *Storage) MapTo(v interface{}) error {
3232
}
3333

3434
func getStorage(name, typ string, overrides ...*ini.Section) Storage {
35-
sectionName := "storage"
36-
if len(name) > 0 {
37-
sectionName = sectionName + "." + typ
38-
}
35+
const sectionName = "storage"
3936
sec := Cfg.Section(sectionName)
4037

4138
if len(overrides) == 0 {
4239
overrides = []*ini.Section{
40+
Cfg.Section(sectionName + "." + typ),
4341
Cfg.Section(sectionName + "." + name),
4442
}
4543
}

0 commit comments

Comments
 (0)