Skip to content

Commit

Permalink
Merge pull request #3587 from wkloucek/single-config-file-location
Browse files Browse the repository at this point in the history
load configuration only from one directory
  • Loading branch information
wkloucek authored Apr 26, 2022
2 parents 4b65e6d + a915f2e commit 0f12ffb
Show file tree
Hide file tree
Showing 11 changed files with 95 additions and 91 deletions.
1 change: 1 addition & 0 deletions .drone.star
Original file line number Diff line number Diff line change
Expand Up @@ -1774,6 +1774,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
"OCIS_URL": OCIS_URL,
"PROXY_TLS": "true",
"OCIS_BASE_DATA_PATH": "/mnt/data/ocis",
"OCIS_CONFIG_DIR": "/etc/ocis",
# change default secrets
"OCIS_JWT_SECRET": "Pive-Fumkiu4",
"STORAGE_TRANSFER_SECRET": "replace-me-with-a-transfer-secret",
Expand Down
1 change: 1 addition & 0 deletions .make/release.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ release-dirs:

# docker specific packaging flags
DOCKER_LDFLAGS += -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseDataPathType=path" -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseDataPathValue=/var/lib/ocis"
DOCKER_LDFLAGS += -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseConfigPathType=path" -X "$(OCIS_REPO)/ocis-pkg/config/defaults.BaseConfigPathValue=/etc/ocis"

release-linux-docker-amd64: release-dirs
GOOS=linux \
Expand Down
12 changes: 12 additions & 0 deletions changelog/unreleased/change-load-config-from-only-one-dir.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Change: Load configuration files just from one directory

We've changed the configuration file loading behavior and are now only loading
configuration files from ONE single directory. This directory can be set on
compile time or via an environment variable on startup (`OCIS_CONFIG_DIR`).

We are using following configuration default paths:

- Docker images: `/etc/ocis/`
- Binary releases: `$HOME/.ocis/config/`

https://github.com/owncloud/ocis/pull/3587
4 changes: 3 additions & 1 deletion docs/helpers/configenvextractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ func GenerateIntermediateCode(templatePath string, intermediateCodePath string,

func RunIntermediateCode(intermediateCodePath string) {
fmt.Println("Running intermediate go code for " + intermediateCodePath)
os.Setenv("OCIS_BASE_DATA_PATH", "~/.ocis")
defaultPath := "~/.ocis"
os.Setenv("OCIS_BASE_DATA_PATH", defaultPath)
os.Setenv("OCIS_CONFIG_DIR", path.Join(defaultPath, "config"))
out, err := exec.Command("go", "run", intermediateCodePath).Output()
if err != nil {
log.Fatal(err)
Expand Down
13 changes: 7 additions & 6 deletions docs/ocis/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,16 @@ Let's explore the various flows with examples and workflows.

Let's explore with examples this approach.

#### Expected loading locations:
#### Expected loading locations

- `$HOME/.ocis/config/`
- `/etc/ocis/`
- `.config/`
- docker images: `/etc/ocis/`
- binary releases: `$HOME/.ocis/config/`

followed by the extension name. When configuring the proxy, a valid full path that will get loaded is `$HOME/.ocis/config/proxy.yaml`.
followed by the `<extension name>.yaml`, eg `proxy.yaml` for the extension configuration. You also can put an `ocis.yaml` config file to the expected loading location to use a single config file.

#### Only config files
You can set another directory as config path in the environment variable `OCIS_CONFIG_DIR`. It will then pick the same file names, but from the folder you configured.

#### Only config files

The following config files are present in the default loading locations:

Expand Down
17 changes: 9 additions & 8 deletions docs/ocis/deployment/systemd.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@ geekdocFilePath: systemd.md
{{< toc >}}

## Install the oCIS binary

Download the oCIS binary of your preferred version and for your CPU architecture and operating system from [download.owncloud.com](https://download.owncloud.com/ocis/ocis).

Rename the downloaded binary to `ocis` and move it to `/usr/bin/`. As a next step, you need to mark it as executable with `chmod +x /usr/bin/ocis`.

When you now run `ocis help` on your command line, you should see the available options for the oCIS command.


## Systemd service definition

Create the Systemd service definition for oCIS in the file `/etc/systemd/system/ocis.service` with following content:
```

```systemd
[Unit]
Description=OCIS server
Expand Down Expand Up @@ -49,16 +50,16 @@ OCIS_INSECURE=false
OCIS_LOG_LEVEL=error
GLAUTH_LDAPS_CERT=/etc/ocis/ldap/ldaps.crt
GLAUTH_LDAPS_KEY=/etc/ocis/ldap/ldaps.key
IDP_TRANSPORT_TLS_CERT=/etc/ocis/idp/server.crt
IDP_TRANSPORT_TLS_KEY=/etc/ocis/idp/server.key
PROXY_TRANSPORT_TLS_CERT=/etc/ocis/proxy/server.crt
PROXY_TRANSPORT_TLS_KEY=/etc/ocis/proxy/server.key
OCIS_CONFIG_DIR=/etc/ocis
OCIS_BASE_DATA_PATH=/var/lib/ocis
```

Since we set `OCIS_CONFIG_DIR` to `/etc/ocis` you can also place configuration files in this directory.

Please change your `OCIS_URL` in order to reflect your actual deployment. If you are using self-signed certificates you need to set `OCIS_INSECURE=true` in `/etc/ocis/ocis.env`.

oCIS will store all data in `/var/lib/ocis`, because we configured it so by setting `OCIS_BASE_DATA_PATH`. Therefore you need to create that directory and make it accessible to the user, you use to start oCIS.


## Starting the oCIS service

Expand Down
41 changes: 37 additions & 4 deletions ocis-pkg/config/defaults/paths.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const ()

var (
// switch between modes
BaseDataPathType = "homedir"
// don't read from this, only write
BaseDataPathType = "homedir" // or "path"
// default data path
BaseDataPathValue = "/var/lib/ocis"
)

func BaseDataPath() string {

// It is not nice to have hidden / secrete configuration options
// But how can we update the base path for every occurence with a flageset option?
// This is currenlty not possible and needs a new configuration concept
// But how can we update the base path for every occurrence with a flagset option?
// This is currently not possible and needs a new configuration concept
p := os.Getenv("OCIS_BASE_DATA_PATH")
if p != "" {
return p
Expand All @@ -40,3 +40,36 @@ func BaseDataPath() string {
return ""
}
}

var (
// switch between modes
BaseConfigPathType = "homedir" // or "path"
// default config path
BaseConfigPathValue = "/etc/ocis"
)

func BaseConfigPath() string {

// It is not nice to have hidden / secrete configuration options
// But how can we update the base path for every occurrence with a flagset option?
// This is currently not possible and needs a new configuration concept
p := os.Getenv("OCIS_CONFIG_DIR")
if p != "" {
return p
}

switch BaseConfigPathType {
case "homedir":
dir, err := os.UserHomeDir()
if err != nil {
// fallback to BaseConfigPathValue for users without home
return BaseConfigPathValue
}
return path.Join(dir, ".ocis", "config")
case "path":
return BaseConfigPathValue
default:
log.Fatalf("BaseConfigPathType %s not found", BaseConfigPathType)
return ""
}
}
76 changes: 10 additions & 66 deletions ocis-pkg/config/helpers.go
Original file line number Diff line number Diff line change
@@ -1,87 +1,31 @@
package config

import (
"io/fs"
"os"
"path/filepath"
"strings"
"path"

gofig "github.com/gookit/config/v2"
gooyaml "github.com/gookit/config/v2/yaml"
"github.com/owncloud/ocis/ocis-pkg/config/defaults"
)

var (
defaultLocations = []string{
filepath.Join(os.Getenv("HOME"), "/.ocis/config/"),
"/etc/ocis/",
".config/",
}

// supportedExtensions is determined by gookit/config.
supportedExtensions = []string{
"yaml",
"yml",
}
// decoderConfigTagname sets the tag name to be used from the config structs
// currently we only support "yaml" because we only support config loading
// from yaml files and the yaml parser has no simple way to set a custom tag name to use
decoderConfigTagName = "yaml"
)

// DefaultConfigSources returns a slice with matched expected config files. It sugars coat several aspects of config file
// management by assuming there are 3 default locations a config file could be.
// It uses globbing to match a config file by name, and retrieve any supported extension supported by our drivers.
// It sanitizes the output depending on the list of drivers provided.
func DefaultConfigSources(filename string, drivers []string) []string {
var sources []string

locations := []string{}
if v := os.Getenv("OCIS_CONFIG_DIR"); v != "" {
locations = append(locations, v)
// only use the configured config dir
locations = append(locations, os.Getenv("OCIS_CONFIG_DIR"))
} else {
// merge config from all default locations
locations = append(locations, defaultLocations...)
}

for i := range locations {
dirFS := os.DirFS(locations[i])
pattern := filename + ".*"
matched, _ := fs.Glob(dirFS, pattern)
if len(matched) > 0 {
// prepend path to results
for j := 0; j < len(matched); j++ {
matched[j] = filepath.Join(locations[i], matched[j])
}
}
sources = append(sources, matched...)
}

return sanitizeExtensions(sources, drivers, func(a, b string) bool {
return strings.HasSuffix(filepath.Base(a), b)
})
}

// sanitizeExtensions removes elements from "set" which extensions are not in "ext".
func sanitizeExtensions(set []string, ext []string, f func(a, b string) bool) []string {
var r []string
for i := 0; i < len(set); i++ {
for j := 0; j < len(ext); j++ {
if f(filepath.Base(set[i]), ext[j]) {
r = append(r, set[i])
}
}
}
return r
}

// BindSourcesToStructs assigns any config value from a config file / env variable to struct `dst`. Its only purpose
// is to solely modify `dst`, not dealing with the config structs; and do so in a thread safe manner.
func BindSourcesToStructs(extension string, dst interface{}) (*gofig.Config, error) {
sources := DefaultConfigSources(extension, supportedExtensions)
cnf := gofig.NewWithOptions(extension)
cnf.WithOptions(func(options *gofig.Options) {
options.DecoderConfig.TagName = "yaml"
options.DecoderConfig.TagName = decoderConfigTagName
})
cnf.AddDriver(gooyaml.Driver)
_ = cnf.LoadFiles(sources...)

cfgFile := path.Join(defaults.BaseConfigPath(), extension+".yaml")
_ = cnf.LoadFiles([]string{cfgFile}...)

err := cnf.BindStruct("", &dst)
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions ocis/docker/Dockerfile.linux.amd64
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ RUN addgroup -g 1000 -S ocis-group && \

RUN mkdir -p /var/lib/ocis && \
chown -R ocis-user:ocis-group /var/lib/ocis && \
chmod -R 777 /var/lib/ocis
chmod -R 777 /var/lib/ocis && \
mkdir -p /etc/ocis && \
chown -R ocis-user:ocis-group /etc/ocis && \
chmod -R 777 /etc/ocis

VOLUME [ "/var/lib/ocis" ]
VOLUME [ "/var/lib/ocis", "/etc/ocis" ]
WORKDIR /var/lib/ocis

USER 1000
Expand Down
7 changes: 5 additions & 2 deletions ocis/docker/Dockerfile.linux.arm
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ RUN addgroup -g 1000 -S ocis-group && \

RUN mkdir -p /var/lib/ocis && \
chown -R ocis-user:ocis-group /var/lib/ocis && \
chmod -R 777 /var/lib/ocis
chmod -R 777 /var/lib/ocis && \
mkdir -p /etc/ocis && \
chown -R ocis-user:ocis-group /etc/ocis && \
chmod -R 777 /etc/ocis

VOLUME [ "/var/lib/ocis" ]
VOLUME [ "/var/lib/ocis", "/etc/ocis" ]
WORKDIR /var/lib/ocis

USER 1000
Expand Down
7 changes: 5 additions & 2 deletions ocis/docker/Dockerfile.linux.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ RUN addgroup -g 1000 -S ocis-group && \

RUN mkdir -p /var/lib/ocis && \
chown -R ocis-user:ocis-group /var/lib/ocis && \
chmod -R 777 /var/lib/ocis
chmod -R 777 /var/lib/ocis && \
mkdir -p /etc/ocis && \
chown -R ocis-user:ocis-group /etc/ocis && \
chmod -R 777 /etc/ocis

VOLUME [ "/var/lib/ocis" ]
VOLUME [ "/var/lib/ocis", "/etc/ocis" ]
WORKDIR /var/lib/ocis

USER 1000
Expand Down

0 comments on commit 0f12ffb

Please sign in to comment.