From ebbf76ab2dd2f4d7af93332e2e92c14119661865 Mon Sep 17 00:00:00 2001 From: Umputun Date: Thu, 14 Jun 2018 21:41:18 -0500 Subject: [PATCH 1/5] structured store opts --- app/main.go | 77 +++++++++++++++++++++++++++++------------------- app/main_test.go | 20 +++++++++---- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/app/main.go b/app/main.go index 45c206dd..8868eec1 100644 --- a/app/main.go +++ b/app/main.go @@ -32,25 +32,25 @@ type Opts struct { SecretKey string `long:"secret" env:"SECRET" required:"true" description:"secret key"` RemarkURL string `long:"url" env:"REMARK_URL" required:"true" description:"url to remark"` - BoltPath string `long:"bolt" env:"BOLTDB_PATH" default:"./var" description:"parent dir for bolt files"` - Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","` - Admins []string `long:"admin" env:"ADMIN" description:"admin(s) names" env-delim:","` - AdminEmail string `long:"admin-email" env:"ADMIN_EMAIL" default:"" description:"admin email"` - DevPasswd string `long:"dev-passwd" env:"DEV_PASSWD" default:"" description:"development mode password"` - BackupLocation string `long:"backup" env:"BACKUP_PATH" default:"./var/backup" description:"backups location"` - MaxBackupFiles int `long:"max-back" env:"MAX_BACKUP_FILES" default:"10" description:"max backups to keep"` - AvatarStore string `long:"avatars" env:"AVATAR_STORE" default:"./var/avatars" description:"avatars location"` - ImageProxy bool `long:"img-proxy" env:"IMG_PROXY" description:"enable image proxy"` - MaxCommentSize int `long:"max-comment" env:"MAX_COMMENT_SIZE" default:"2048" description:"max comment size"` - MaxCachedItems int `long:"max-cache-items" env:"MAX_CACHE_ITEMS" default:"1000" description:"max cached items"` - MaxCachedValue int `long:"max-cache-value" env:"MAX_CACHE_VALUE" default:"65536" description:"max size of cached value"` - MaxCacheSize int `long:"max-cache-size" env:"MAX_CACHE_SIZE" default:"50000000" description:"max size of total cache"` - LowScore int `long:"low-score" env:"LOW_SCORE" default:"-5" description:"low score threshold"` - CriticalScore int `long:"critical-score" env:"CRITICAL_SCORE" default:"-10" description:"critical score threshold"` - ReadOnlyAge int `long:"read-age" env:"READONLY_AGE" default:"0" description:"read-only age of comments"` - Port int `long:"port" env:"REMARK_PORT" default:"8080" description:"port"` - WebRoot string `long:"web-root" env:"REMARK_WEB_ROOT" default:"./web" description:"web root directory"` - Dbg bool `long:"dbg" env:"DEBUG" description:"debug mode"` + Store StoreGroup `group:"store" namespace:"store" env-namespace:"STORE"` + Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","` + Admins []string `long:"admin" env:"ADMIN" description:"admin(s) names" env-delim:","` + AdminEmail string `long:"admin-email" env:"ADMIN_EMAIL" default:"" description:"admin email"` + DevPasswd string `long:"dev-passwd" env:"DEV_PASSWD" default:"" description:"development mode password"` + BackupLocation string `long:"backup" env:"BACKUP_PATH" default:"./var/backup" description:"backups location"` + MaxBackupFiles int `long:"max-back" env:"MAX_BACKUP_FILES" default:"10" description:"max backups to keep"` + AvatarStore string `long:"avatars" env:"AVATAR_STORE" default:"./var/avatars" description:"avatars location"` + ImageProxy bool `long:"img-proxy" env:"IMG_PROXY" description:"enable image proxy"` + MaxCommentSize int `long:"max-comment" env:"MAX_COMMENT_SIZE" default:"2048" description:"max comment size"` + MaxCachedItems int `long:"max-cache-items" env:"MAX_CACHE_ITEMS" default:"1000" description:"max cached items"` + MaxCachedValue int `long:"max-cache-value" env:"MAX_CACHE_VALUE" default:"65536" description:"max size of cached value"` + MaxCacheSize int `long:"max-cache-size" env:"MAX_CACHE_SIZE" default:"50000000" description:"max size of total cache"` + LowScore int `long:"low-score" env:"LOW_SCORE" default:"-5" description:"low score threshold"` + CriticalScore int `long:"critical-score" env:"CRITICAL_SCORE" default:"-10" description:"critical score threshold"` + ReadOnlyAge int `long:"read-age" env:"READONLY_AGE" default:"0" description:"read-only age of comments"` + Port int `long:"port" env:"REMARK_PORT" default:"8080" description:"port"` + WebRoot string `long:"web-root" env:"REMARK_WEB_ROOT" default:"./web" description:"web root directory"` + Dbg bool `long:"dbg" env:"DEBUG" description:"debug mode"` Auth struct { Google AuthGroup `group:"google" namespace:"google" env-namespace:"GOOGLE" description:"Google OAuth"` @@ -66,6 +66,15 @@ type AuthGroup struct { CSEC string `long:"csec" env:"CSEC" description:"OAuth client secret"` } +// StoreGroup defines options group for store params +type StoreGroup struct { + Type string `long:"type" env:"TYPE" description:"type of storage" choice:"bolt" choice:"mongo" default:"bolt"` + Bolt struct { + Path string `long:"path" env:"PATH" default:"./var" description:"parent dir for bolt files"` + Timeout time.Duration `long:"timeout" env:"TIMEOUT" default:"30s" description:"bolt timeout"` + } `group:"bolt" namespace:"bolt" env-namespace:"BOLT"` +} + var revision = "unknown" // Application holds all active objects @@ -111,7 +120,7 @@ func main() { // doesn't start anything func New(opts Opts) (*Application, error) { - if err := makeDirs(opts.BoltPath, opts.BackupLocation, opts.AvatarStore); err != nil { + if err := makeDirs(opts.BackupLocation, opts.AvatarStore); err != nil { return nil, err } @@ -119,7 +128,7 @@ func New(opts Opts) (*Application, error) { return nil, errors.Errorf("invalid remark42 url %s", opts.RemarkURL) } - boltStore, err := makeBoltStore(opts.Sites, opts.BoltPath) + boltStore, err := makeStore(opts.Store, opts.Sites) if err != nil { return nil, err } @@ -224,17 +233,23 @@ func (a *Application) activateBackup(ctx context.Context) { } } -// makeBoltStore creates store for all sites -func makeBoltStore(siteNames []string, path string) (engine.Interface, error) { - sites := []engine.BoltSite{} - for _, site := range siteNames { - sites = append(sites, engine.BoltSite{SiteID: site, FileName: fmt.Sprintf("%s/%s.db", path, site)}) +// makeStore creates store for all sites +func makeStore(group StoreGroup, siteNames []string) (result engine.Interface, err error) { + switch group.Type { + case "bolt": + if err = makeDirs(group.Bolt.Path); err != nil { + return nil, err + } + sites := []engine.BoltSite{} + for _, site := range siteNames { + sites = append(sites, engine.BoltSite{SiteID: site, FileName: fmt.Sprintf("%s/%s.db", group.Bolt.Path, site)}) + } + result, err = engine.NewBoltDB(bolt.Options{Timeout: group.Bolt.Timeout}, sites...) + default: + return nil, errors.Errorf("unsupported store type %s", group.Type) } - result, err := engine.NewBoltDB(bolt.Options{Timeout: 30 * time.Second}, sites...) - if err != nil { - return nil, errors.Wrap(err, "can't initialize data store") - } - return result, nil + + return result, errors.Wrap(err, "can't initialize data store") } // mkdir -p for all dirs diff --git a/app/main_test.go b/app/main_test.go index 8e541701..ceba4218 100644 --- a/app/main_test.go +++ b/app/main_test.go @@ -49,7 +49,7 @@ func TestApplicationFailed(t *testing.T) { p := flags.NewParser(&opts, flags.Default) // RO bolt location - p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--bolt=/dev/null"}) + p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.bolt.path=/dev/null"}) _, err := New(opts) assert.EqualError(t, err, "can't initialize data store: failed to make boltdb for /dev/null/remark.db: "+ "open /dev/null/remark.db: not a directory") @@ -57,17 +57,24 @@ func TestApplicationFailed(t *testing.T) { // RO backup location opts = Opts{} - p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--bolt=/tmp", "--backup=/dev/null/not-writable"}) + p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.bolt.path=/tmp", + "--backup=/dev/null/not-writable"}) _, err = New(opts) assert.EqualError(t, err, "can't check directory status for /dev/null/not-writable: stat /dev/null/not-writable: not a directory") t.Log(err) // invalid url opts = Opts{} - p.ParseArgs([]string{"--secret=123456", "--url=demo.remark42.com", "--bolt=/tmp"}) + p.ParseArgs([]string{"--secret=123456", "--url=demo.remark42.com", "----store.bolt.path=/tmp"}) _, err = New(opts) assert.EqualError(t, err, "invalid remark42 url demo.remark42.com") t.Log(err) + + opts = Opts{} + p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.type=mongo"}) + _, err = New(opts) + assert.EqualError(t, err, "unsupported store type mongo") + t.Log(err) } func TestApplicationShutdown(t *testing.T) { @@ -79,7 +86,7 @@ func TestApplicationShutdown(t *testing.T) { } func TestApplicationMainSignal(t *testing.T) { - os.Args = []string{"test", "--secret=123456", "--bolt=/tmp/xyz", "--backup=/tmp", "--avatars=/tmp", + os.Args = []string{"test", "--secret=123456", "--store.bolt.path=/tmp/xyz", "--backup=/tmp", "--avatars=/tmp", "--port=18100", "--url=https://demo.remark42.com"} go func() { @@ -97,14 +104,15 @@ func prepApp(t *testing.T, port int, duration time.Duration) (*Application, cont p := flags.NewParser(&opts, flags.Default) p.ParseArgs([]string{"--secret=123456", "--dev-passwd=password", "--url=https://demo.remark42.com"}) opts.AvatarStore, opts.BackupLocation = "/tmp", "/tmp" - opts.BoltPath = fmt.Sprintf("/tmp/%d", port) + opts.Store.Bolt.Path = fmt.Sprintf("/tmp/%d", port) + opts.Store.Bolt.Timeout = 10 * time.Second opts.Auth.Github.CSEC, opts.Auth.Github.CID = "csec", "cid" opts.Auth.Google.CSEC, opts.Auth.Google.CID = "csec", "cid" opts.Auth.Facebook.CSEC, opts.Auth.Facebook.CID = "csec", "cid" opts.Auth.Yandex.CSEC, opts.Auth.Yandex.CID = "csec", "cid" opts.Port = port - os.Remove(opts.BoltPath + "/remark.db") + os.Remove(opts.Store.Bolt.Path + "/remark.db") // create app app, err := New(opts) From b347ad8e5e6e12aca4710eb60be73b50dab3e271 Mon Sep 17 00:00:00 2001 From: Umputun Date: Sun, 17 Jun 2018 12:22:41 -0500 Subject: [PATCH 2/5] add opts group for avatars --- app/main.go | 68 ++++++++++++++++++++++++++++++++---------------- app/main_test.go | 4 +-- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/app/main.go b/app/main.go index 8abd80ed..28c7bfd1 100644 --- a/app/main.go +++ b/app/main.go @@ -32,26 +32,26 @@ type Opts struct { SecretKey string `long:"secret" env:"SECRET" required:"true" description:"secret key"` RemarkURL string `long:"url" env:"REMARK_URL" required:"true" description:"url to remark"` - Store StoreGroup `group:"store" namespace:"store" env-namespace:"STORE"` - Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","` - Admins []string `long:"admin" env:"ADMIN" description:"admin(s) names" env-delim:","` - AdminEmail string `long:"admin-email" env:"ADMIN_EMAIL" default:"" description:"admin email"` - DevPasswd string `long:"dev-passwd" env:"DEV_PASSWD" default:"" description:"development mode password"` - BackupLocation string `long:"backup" env:"BACKUP_PATH" default:"./var/backup" description:"backups location"` - MaxBackupFiles int `long:"max-back" env:"MAX_BACKUP_FILES" default:"10" description:"max backups to keep"` - AvatarStore string `long:"avatars" env:"AVATAR_STORE" default:"./var/avatars" description:"avatars location"` - AvatarRszLmt int `long:"avatars-rsz-lmt" env:"AVATAR_RSZ_LMT" default:"0" description:"max image size for resizing avatars on save"` - ImageProxy bool `long:"img-proxy" env:"IMG_PROXY" description:"enable image proxy"` - MaxCommentSize int `long:"max-comment" env:"MAX_COMMENT_SIZE" default:"2048" description:"max comment size"` - MaxCachedItems int `long:"max-cache-items" env:"MAX_CACHE_ITEMS" default:"1000" description:"max cached items"` - MaxCachedValue int `long:"max-cache-value" env:"MAX_CACHE_VALUE" default:"65536" description:"max size of cached value"` - MaxCacheSize int `long:"max-cache-size" env:"MAX_CACHE_SIZE" default:"50000000" description:"max size of total cache"` - LowScore int `long:"low-score" env:"LOW_SCORE" default:"-5" description:"low score threshold"` - CriticalScore int `long:"critical-score" env:"CRITICAL_SCORE" default:"-10" description:"critical score threshold"` - ReadOnlyAge int `long:"read-age" env:"READONLY_AGE" default:"0" description:"read-only age of comments"` - Port int `long:"port" env:"REMARK_PORT" default:"8080" description:"port"` - WebRoot string `long:"web-root" env:"REMARK_WEB_ROOT" default:"./web" description:"web root directory"` - Dbg bool `long:"dbg" env:"DEBUG" description:"debug mode"` + Store StoreGroup `group:"store" namespace:"store" env-namespace:"STORE"` + Avatar AvatarGroup `group:"avatar" namespace:"avatar" env-namespace:"AVATAR"` + + Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","` + Admins []string `long:"admin" env:"ADMIN" description:"admin(s) names" env-delim:","` + AdminEmail string `long:"admin-email" env:"ADMIN_EMAIL" default:"" description:"admin email"` + DevPasswd string `long:"dev-passwd" env:"DEV_PASSWD" default:"" description:"development mode password"` + BackupLocation string `long:"backup" env:"BACKUP_PATH" default:"./var/backup" description:"backups location"` + MaxBackupFiles int `long:"max-back" env:"MAX_BACKUP_FILES" default:"10" description:"max backups to keep"` + ImageProxy bool `long:"img-proxy" env:"IMG_PROXY" description:"enable image proxy"` + MaxCommentSize int `long:"max-comment" env:"MAX_COMMENT_SIZE" default:"2048" description:"max comment size"` + MaxCachedItems int `long:"max-cache-items" env:"MAX_CACHE_ITEMS" default:"1000" description:"max cached items"` + MaxCachedValue int `long:"max-cache-value" env:"MAX_CACHE_VALUE" default:"65536" description:"max size of cached value"` + MaxCacheSize int `long:"max-cache-size" env:"MAX_CACHE_SIZE" default:"50000000" description:"max size of total cache"` + LowScore int `long:"low-score" env:"LOW_SCORE" default:"-5" description:"low score threshold"` + CriticalScore int `long:"critical-score" env:"CRITICAL_SCORE" default:"-10" description:"critical score threshold"` + ReadOnlyAge int `long:"read-age" env:"READONLY_AGE" default:"0" description:"read-only age of comments"` + Port int `long:"port" env:"REMARK_PORT" default:"8080" description:"port"` + WebRoot string `long:"web-root" env:"REMARK_WEB_ROOT" default:"./web" description:"web root directory"` + Dbg bool `long:"dbg" env:"DEBUG" description:"debug mode"` Auth struct { Google AuthGroup `group:"google" namespace:"google" env-namespace:"GOOGLE" description:"Google OAuth"` @@ -76,6 +76,15 @@ type StoreGroup struct { } `group:"bolt" namespace:"bolt" env-namespace:"BOLT"` } +// AvatarGroup defines options group for avatar params +type AvatarGroup struct { + Type string `long:"type" env:"TYPE" description:"type of avatar storage" choice:"fs" choice:"mongo" default:"fs"` + FS struct { + Path string `long:"path" env:"PATH" default:"./var/avatars" description:"avatars location"` + } `group:"fs" namespace:"fs" env-namespace:"FS"` + RszLmt int `long:"rsz-lmt" env:"RSZ_LMT" default:"0" description:"max image size for resizing avatars on save"` +} + var revision = "unknown" // Application holds all active objects @@ -121,7 +130,7 @@ func main() { // doesn't start anything func New(opts Opts) (*Application, error) { - if err := makeDirs(opts.BackupLocation, opts.AvatarStore); err != nil { + if err := makeDirs(opts.BackupLocation); err != nil { return nil, err } @@ -148,8 +157,12 @@ func New(opts Opts) (*Application, error) { jwtService := auth.NewJWT(opts.SecretKey, strings.HasPrefix(opts.RemarkURL, "https://"), 7*24*time.Hour) + avatarStore, err := makeAvatarStore(opts.Avatar) + if err != nil { + return nil, errors.Wrap(err, "failed to make avatar store") + } avatarProxy := &proxy.Avatar{ - Store: proxy.NewFSAvatarStore(opts.AvatarStore, opts.AvatarRszLmt), + Store: avatarStore, RoutePath: "/api/v1/avatar", RemarkURL: strings.TrimSuffix(opts.RemarkURL, "/"), } @@ -253,6 +266,17 @@ func makeStore(group StoreGroup, siteNames []string) (result engine.Interface, e return result, errors.Wrap(err, "can't initialize data store") } +func makeAvatarStore(group AvatarGroup) (result proxy.AvatarStore, err error) { + switch group.Type { + case "fs": + if err = makeDirs(group.FS.Path); err != nil { + return nil, err + } + return proxy.NewFSAvatarStore(group.FS.Path, group.RszLmt), nil + } + return nil, errors.Errorf("unsupported avatart store type %s", group.Type) +} + // mkdir -p for all dirs func makeDirs(dirs ...string) error { diff --git a/app/main_test.go b/app/main_test.go index ceba4218..0e089a14 100644 --- a/app/main_test.go +++ b/app/main_test.go @@ -86,7 +86,7 @@ func TestApplicationShutdown(t *testing.T) { } func TestApplicationMainSignal(t *testing.T) { - os.Args = []string{"test", "--secret=123456", "--store.bolt.path=/tmp/xyz", "--backup=/tmp", "--avatars=/tmp", + os.Args = []string{"test", "--secret=123456", "--store.bolt.path=/tmp/xyz", "--backup=/tmp", "--avatar.fs.path=/tmp", "--port=18100", "--url=https://demo.remark42.com"} go func() { @@ -103,7 +103,7 @@ func prepApp(t *testing.T, port int, duration time.Duration) (*Application, cont opts := Opts{} p := flags.NewParser(&opts, flags.Default) p.ParseArgs([]string{"--secret=123456", "--dev-passwd=password", "--url=https://demo.remark42.com"}) - opts.AvatarStore, opts.BackupLocation = "/tmp", "/tmp" + opts.Avatar.FS.Path, opts.Avatar.Type, opts.BackupLocation = "/tmp", "fs", "/tmp" opts.Store.Bolt.Path = fmt.Sprintf("/tmp/%d", port) opts.Store.Bolt.Timeout = 10 * time.Second opts.Auth.Github.CSEC, opts.Auth.Github.CID = "csec", "cid" From 9d7212e74a75cab6a4dbcbb8595dfa8f71f27ead Mon Sep 17 00:00:00 2001 From: Umputun Date: Sun, 17 Jun 2018 12:34:53 -0500 Subject: [PATCH 3/5] add opts group for cache --- app/main.go | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/app/main.go b/app/main.go index 28c7bfd1..cc4505c8 100644 --- a/app/main.go +++ b/app/main.go @@ -34,6 +34,7 @@ type Opts struct { Store StoreGroup `group:"store" namespace:"store" env-namespace:"STORE"` Avatar AvatarGroup `group:"avatar" namespace:"avatar" env-namespace:"AVATAR"` + Cache CacheGroup `group:"cache" namespace:"cache" env-namespace:"CACHE"` Sites []string `long:"site" env:"SITE" default:"remark" description:"site names" env-delim:","` Admins []string `long:"admin" env:"ADMIN" description:"admin(s) names" env-delim:","` @@ -43,9 +44,6 @@ type Opts struct { MaxBackupFiles int `long:"max-back" env:"MAX_BACKUP_FILES" default:"10" description:"max backups to keep"` ImageProxy bool `long:"img-proxy" env:"IMG_PROXY" description:"enable image proxy"` MaxCommentSize int `long:"max-comment" env:"MAX_COMMENT_SIZE" default:"2048" description:"max comment size"` - MaxCachedItems int `long:"max-cache-items" env:"MAX_CACHE_ITEMS" default:"1000" description:"max cached items"` - MaxCachedValue int `long:"max-cache-value" env:"MAX_CACHE_VALUE" default:"65536" description:"max size of cached value"` - MaxCacheSize int `long:"max-cache-size" env:"MAX_CACHE_SIZE" default:"50000000" description:"max size of total cache"` LowScore int `long:"low-score" env:"LOW_SCORE" default:"-5" description:"low score threshold"` CriticalScore int `long:"critical-score" env:"CRITICAL_SCORE" default:"-10" description:"critical score threshold"` ReadOnlyAge int `long:"read-age" env:"READONLY_AGE" default:"0" description:"read-only age of comments"` @@ -85,6 +83,16 @@ type AvatarGroup struct { RszLmt int `long:"rsz-lmt" env:"RSZ_LMT" default:"0" description:"max image size for resizing avatars on save"` } +// CacheGroup defines options group for cache params +type CacheGroup struct { + Type string `long:"type" env:"TYPE" description:"type of cache" choice:"mem" choice:"redis" default:"mem"` + Max struct { + Items int `long:"items" env:"ITEMS" default:"1000" description:"max cached items"` + Value int `long:"value" env:"VALUE" default:"65536" description:"max size of cached value"` + Size int64 `long:"size" env:"SIZE" default:"50000000" description:"max size of total cache"` + } `group:"max" namespace:"max" env-namespace:"MAX"` +} + var revision = "unknown" // Application holds all active objects @@ -138,7 +146,7 @@ func New(opts Opts) (*Application, error) { return nil, errors.Errorf("invalid remark42 url %s", opts.RemarkURL) } - boltStore, err := makeStore(opts.Store, opts.Sites) + boltStore, err := makeDataStore(opts.Store, opts.Sites) if err != nil { return nil, err } @@ -149,8 +157,8 @@ func New(opts Opts) (*Application, error) { MaxCommentSize: opts.MaxCommentSize, } - loadingCache, err := cache.NewMemoryCache(cache.MaxValSize(opts.MaxCachedValue), cache.MaxKeys(opts.MaxCachedItems), - cache.PostFlushFn(postFlushFn(opts.Sites, opts.Port))) + loadingCache, err := cache.NewMemoryCache(cache.MaxCacheSize(opts.Cache.Max.Size), cache.MaxValSize(opts.Cache.Max.Value), + cache.MaxKeys(opts.Cache.Max.Items), cache.PostFlushFn(postFlushFn(opts.Sites, opts.Port))) if err != nil { return nil, err } @@ -247,8 +255,8 @@ func (a *Application) activateBackup(ctx context.Context) { } } -// makeStore creates store for all sites -func makeStore(group StoreGroup, siteNames []string) (result engine.Interface, err error) { +// makeDataStore creates store for all sites +func makeDataStore(group StoreGroup, siteNames []string) (result engine.Interface, err error) { switch group.Type { case "bolt": if err = makeDirs(group.Bolt.Path); err != nil { From a287df02339f077992804a6cd05e3e9a10cc999c Mon Sep 17 00:00:00 2001 From: Umputun Date: Sun, 17 Jun 2018 12:40:34 -0500 Subject: [PATCH 4/5] change docs for grouped options --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 182b5941..c618025c 100644 --- a/README.md +++ b/README.md @@ -35,17 +35,18 @@ Remark42 is a self-hosted, lightweight, and simple (yet functional) comment engi | ------------------ | ------------------ | --------------------- | ---------------------------------------------- | | url | REMARK_URL | | url to remark42 server, _required_ | | secret | SECRET | | secret key, _required_ | -| bolt | BOLTDB_PATH | `./var` | path to data directory | +| store.bolt.path | STORE_BOLT_PATH | `./var` | path to data directory | +| store.bolt.timeout | STORE_BOLT_TIMEOUT | `30s` | boltdb access timeout | | site | SITE | `remark` | site name(s), _multi_ | | admin | ADMIN | | admin names (list of user ids), _multi_ | | admin-email | ADMIN_EMAIL | `admin@${REMARK_URL}` | admin email | | backup | BACKUP_PATH | `./var/backup` | backups location | | max-back | MAX_BACKUP_FILES | `10` | max backup files to keep | -| max-cache-items | MAX_CACHE_ITEMS | `1000` | max number of cached items, `0` - unlimited | -| max-cache-value | MAX_CACHE_VALUE | `65536` | max size of cached value, `0` - unlimited | -| max-cache-size | MAX_CACHE_SIZE | `50000000` | max size of all cached values, `0` - unlimited | -| avatars | AVATAR_STORE | `./var/avatars` | avatars location | -| avatars-rsz-lmt | AVATAR_RSZ_LMT | 0 | max image size for resizing avatars on save | +| cache.max.items | CACHE_MAX_ITEMS | `1000` | max number of cached items, `0` - unlimited | +| cache.max.value | CACHE_MAX_VALUE | `65536` | max size of cached value, `0` - unlimited | +| cache.max.size | CACHE_MAX_SIZE | `50000000` | max size of all cached values, `0` - unlimited | +| avatar.path | AVATAR_FS_PATH | `./var/avatars` | avatars location | +| avatar.rsz-lmt | AVATAR_RSZ_LMT | 0 | max image size for resizing avatars on save | | max-comment | MAX_COMMENT_SIZE | 2048 | comment's size limit | | auth.google.cid | AUTH_GOOGLE_CID | | Google OAuth client ID | | auth.google.csec | AUTH_GOOGLE_CSEC | | Google OAuth client secret | From 7bebc5ddfc826244150cdbb7c4043445440ff02f Mon Sep 17 00:00:00 2001 From: Umputun Date: Sun, 17 Jun 2018 12:57:08 -0500 Subject: [PATCH 5/5] missing checks for parse errors --- app/main_test.go | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/main_test.go b/app/main_test.go index 0e089a14..f8004be5 100644 --- a/app/main_test.go +++ b/app/main_test.go @@ -49,29 +49,33 @@ func TestApplicationFailed(t *testing.T) { p := flags.NewParser(&opts, flags.Default) // RO bolt location - p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.bolt.path=/dev/null"}) - _, err := New(opts) + _, err := p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.bolt.path=/dev/null"}) + assert.Nil(t, err) + _, err = New(opts) assert.EqualError(t, err, "can't initialize data store: failed to make boltdb for /dev/null/remark.db: "+ "open /dev/null/remark.db: not a directory") t.Log(err) // RO backup location opts = Opts{} - p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.bolt.path=/tmp", + _, err = p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.bolt.path=/tmp", "--backup=/dev/null/not-writable"}) + assert.Nil(t, err) _, err = New(opts) assert.EqualError(t, err, "can't check directory status for /dev/null/not-writable: stat /dev/null/not-writable: not a directory") t.Log(err) // invalid url opts = Opts{} - p.ParseArgs([]string{"--secret=123456", "--url=demo.remark42.com", "----store.bolt.path=/tmp"}) + _, err = p.ParseArgs([]string{"--secret=123456", "--url=demo.remark42.com", "----store.bolt.path=/tmp"}) + assert.Nil(t, err) _, err = New(opts) assert.EqualError(t, err, "invalid remark42 url demo.remark42.com") t.Log(err) opts = Opts{} - p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.type=mongo"}) + _, err = p.ParseArgs([]string{"--secret=123456", "--url=https://demo.remark42.com", "--store.type=mongo"}) + assert.Nil(t, err) _, err = New(opts) assert.EqualError(t, err, "unsupported store type mongo") t.Log(err) @@ -102,7 +106,8 @@ func prepApp(t *testing.T, port int, duration time.Duration) (*Application, cont // prepare options opts := Opts{} p := flags.NewParser(&opts, flags.Default) - p.ParseArgs([]string{"--secret=123456", "--dev-passwd=password", "--url=https://demo.remark42.com"}) + _, err := p.ParseArgs([]string{"--secret=123456", "--dev-passwd=password", "--url=https://demo.remark42.com"}) + require.Nil(t, err) opts.Avatar.FS.Path, opts.Avatar.Type, opts.BackupLocation = "/tmp", "fs", "/tmp" opts.Store.Bolt.Path = fmt.Sprintf("/tmp/%d", port) opts.Store.Bolt.Timeout = 10 * time.Second