-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconfig.go
152 lines (134 loc) · 4.18 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package cloudsync
import (
"errors"
"os"
"path/filepath"
"strings"
"github.com/oklog/ulid/v2"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v3"
)
// CloudConfig remote infrastructure and services configuration.
type CloudConfig struct {
Region string `yaml:"region"`
Bucket string `yaml:"bucket"`
AccessKey string `yaml:"access_key"`
SecretKey string `yaml:"secret_key"`
}
// ScannerConfig Scanner configuration.
type ScannerConfig struct {
// PartitionID a Scanner instance will use this field to create logical partitions in the specified bucket.
//
// This could be used in many ways such as:
//
// - Create a multi-tenant environment.
//
// - Store data from several machines (maybe from within a network) into a single bucket without operational
// overhead.
//
// Note: This field is auto-generated using Unique Lexicographic IDs (ULID) if not found.
PartitionID string `yaml:"partition_id"`
// ReadHidden read from files using the '.' character prefix.
ReadHidden bool `yaml:"read_hidden"`
// DeepTraversing read every node until leafs are reached from a root directory tree. If set to false,
// Scanner will read only the root tree files.
DeepTraversing bool `yaml:"deep_traversing"`
// IgnoredKeys deny list of custom reserved file or folder keys. Scanner will skip items specified here.
IgnoredKeys []string `yaml:"ignored_keys"`
// LogErrors disable or enable logging of errors. Useful for development or overall process visibility purposes.
LogErrors bool `yaml:"log_errors"`
}
// Config Main application configuration.
type Config struct {
FilePath string `yaml:"-"`
RootDirectory string `yaml:"-"`
Cloud CloudConfig `yaml:"cloud"`
Scanner ScannerConfig `yaml:"scanner"`
ignoredKeysHashSet map[string]struct{}
}
// NewConfig allocates a Config instance used by internal components to perform its processes.
func NewConfig(path, file, rootDirectory string) (Config, error) {
filePath := filepath.Join(path, file)
f, err := os.Open(filePath)
if err != nil {
return Config{}, err
}
defer f.Close()
var cfg Config
decoder := yaml.NewDecoder(f)
if err = decoder.Decode(&cfg); err != nil {
return Config{}, err
}
log.Debug().Str("path", filePath).Msg("Loaded config")
if cfg.Scanner.PartitionID == "" {
cfg.Scanner.PartitionID = ulid.Make().String() // set a tenant id by default
}
cfg.RootDirectory = rootDirectory
cfg.FilePath = filePath
return cfg, nil
}
func newIgnoredKeysSet(keys []string) map[string]struct{} {
if len(keys) == 0 {
return nil
}
m := make(map[string]struct{}, len(keys))
for _, k := range keys {
if strings.HasPrefix(k, "*.") {
k = strings.TrimPrefix(k, "*.")
}
m[k] = struct{}{}
}
return m
}
// KeyIsIgnored verifies if a specified key was selected to be ignored.
func (c *Config) KeyIsIgnored(key string) bool {
if c.ignoredKeysHashSet == nil {
c.ignoredKeysHashSet = newIgnoredKeysSet(c.Scanner.IgnoredKeys)
}
splStr := strings.Split(key, ".")
if len(splStr) > 1 {
extension := splStr[len(splStr)-1]
if _, ok := c.ignoredKeysHashSet[extension]; ok {
return true
}
}
_, ok := c.ignoredKeysHashSet[key]
return ok
}
// SaveConfig stores the specified Config into host's physical disk.
func SaveConfig(cfg Config) error {
log.Debug().Msg("cloudsync: Saving configuration file")
f, err := os.OpenFile(cfg.FilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
encoder := yaml.NewEncoder(f)
defer encoder.Close()
return encoder.Encode(cfg)
}
// SaveConfigIfNotExists creates a path and/or Config file if not found.
//
// If no file was found, it will allocate a ULID as ScannerConfig.PartitionID.
func SaveConfigIfNotExists(path, file string) bool {
if path == "" || file == "" {
return false
}
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
_ = os.Mkdir(path, os.ModePerm)
}
// lookup for config file to verify its existence, stop process if found
dirTmp, _ := os.ReadDir(path)
for _, entry := range dirTmp {
if file == entry.Name() {
return true // idempotency
}
}
_ = SaveConfig(Config{
FilePath: filepath.Join(path, file),
Scanner: ScannerConfig{
PartitionID: ulid.Make().String(),
},
})
return true
}