3
* Licensed to the Parasource Foundation under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The Parasource licenses this file to you under the Parasource License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
4
* You may obtain a copy of the License at http://www.parasource.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5
* See the License for the specific language governing permissions and limitations under the License.
12
"github.com/parasource/rhosus/rhosus/api"
13
"github.com/parasource/rhosus/rhosus/auth"
14
"github.com/parasource/rhosus/rhosus/registry"
15
"github.com/parasource/rhosus/rhosus/registry/cluster"
16
"github.com/parasource/rhosus/rhosus/registry/storage"
17
"github.com/parasource/rhosus/rhosus/util"
18
"github.com/parasource/rhosus/rhosus/util/uuid"
19
"github.com/rs/zerolog/log"
20
"github.com/spf13/cobra"
21
"github.com/spf13/pflag"
22
"github.com/spf13/viper"
33
uuidFileName = "registry.uuid"
36
var configDefaults = map[string]interface{}{
38
// http file server host and port
39
"api_addr": "127.0.0.1:8000",
40
"cluster_addr": "127.0.0.1:8100",
41
"etcd_addr": "127.0.0.1:2379",
42
"rhosus_path": "/var/lib/rhosus",
46
// seconds to wait til force shutdown
47
"shutdown_timeout": 30,
48
// how many times a file should be replicated
49
"replication_factor": 1,
50
// block size in bytes
54
type DefaultChecker struct {
58
func (c *DefaultChecker) checkIfUsingDefault(name string) bool {
61
flag = flag && os.Getenv(name) == ""
62
//flag = flag && c.flags.Lookup(name) == nil
67
var checker *DefaultChecker
70
rootCmd.Flags().String("api_addr", "127.0.0.1:8000", "api server address")
71
rootCmd.Flags().String("cluster_addr", "127.0.0.1:8100", "cluster server address")
72
rootCmd.Flags().String("etcd_addr", "127.0.0.1:2379", "etcd service discovery address")
73
rootCmd.Flags().String("rhosus_path", "/var/lib/rhosus", "rhosus data path")
74
rootCmd.Flags().Int("shutdown_timeout", 30, "node graceful shutdown timeout")
75
rootCmd.Flags().Int("replication_factor", 30, "replication factor")
76
rootCmd.Flags().Int("block_size", 4096, "block size in bytes")
78
viper.BindPFlag("api_addr", rootCmd.Flags().Lookup("cluster_addr"))
79
viper.BindPFlag("cluster_addr", rootCmd.Flags().Lookup("cluster_addr"))
80
viper.BindPFlag("etcd_addr", rootCmd.Flags().Lookup("etcd_addr"))
81
viper.BindPFlag("rhosus_path", rootCmd.Flags().Lookup("rhosus_path"))
82
viper.BindPFlag("shutdown_timeout", rootCmd.Flags().Lookup("shutdown_timeout"))
83
viper.BindPFlag("replication_factor", rootCmd.Flags().Lookup("replication_factor"))
84
viper.BindPFlag("block_size", rootCmd.Flags().Lookup("block size in bytes"))
86
checker = &DefaultChecker{
87
flags: rootCmd.Flags(),
91
var rootCmd = &cobra.Command{
93
Run: func(cmd *cobra.Command, args []string) {
97
for k, v := range configDefaults {
98
viper.SetDefault(k, v)
101
bindEnvs := []string{
102
"api_addr", "cluster_addr", "etcd_addr", "rhosus_path",
103
"shutdown_timeout", "replication_factor", "block_size",
105
for _, env := range bindEnvs {
106
err := viper.BindEnv(env)
108
log.Fatal().Err(err).Msg("error binding env variable")
112
if os.Getenv("GOMAXPROCS") == "" {
113
if viper.IsSet("gomaxprocs") && viper.GetInt("gomaxprocs") > 0 {
114
runtime.GOMAXPROCS(viper.GetInt("gomaxprocs"))
116
runtime.GOMAXPROCS(runtime.NumCPU())
120
v := viper.GetViper()
122
shutdownCh := make(chan struct{}, 1)
124
rhosusPath := v.GetString("rhosus_path")
126
// If rhosus home directory does not exist already,
127
// we create a new one
128
if ok := util.FileExists(rhosusPath); !ok {
129
err := os.Mkdir(rhosusPath, 0755)
131
log.Fatal().Err(err).Msg("error creating rhosus home directory")
134
if err := util.TestDirWritable(rhosusPath); err != nil {
135
log.Fatal().Err(err).Msg("rhosus home directory is not writable")
138
s, err := storage.NewStorage(storage.Config{
139
Path: path.Join(rhosusPath, "registry"),
144
log.Fatal().Err(err).Msg("error creating storage")
146
roleManager, err := auth.NewRoleManager(s)
148
log.Fatal().Err(err).Msg("error creating role manager")
150
tokenManager, err := auth.NewTokenStore(s)
152
log.Fatal().Err(err).Msg("error creating token manager")
155
authMethods := map[string]auth.Authenticator{
156
"credentials": auth.NewCredentialsAuth(roleManager, tokenManager),
159
conf, err := registryConfig(v, s)
161
r, err := registry.NewRegistry(conf)
163
log.Fatal().Err(err).Msg("error creating registry instance")
168
apiAddr := v.GetString("api_addr")
169
httpApi, err := api.NewApi(r, tokenManager, api.Config{
171
AuthMethods: authMethods,
175
go handleSignals(shutdownCh)
187
func registryConfig(v *viper.Viper, s *storage.Storage) (registry.Config, error) {
188
if os.Getenv("API_ADDR") == "" {
189
log.Warn().Msg("API_ADDR is not set explicitly, falling back to default")
191
if os.Getenv("CLUSTER_ADDR") == "" {
192
log.Warn().Msg("CLUSTER_ADDR is not set explicitly, falling back to default")
195
clusterAddr := v.GetString("cluster_addr")
196
rhosusPath := v.GetString("rhosus_path")
197
etcdAddr := v.GetString("etcd_addr")
199
// Generating id for Registry
200
registryId := getId(rhosusPath, true)
202
conf := registry.Config{
204
RhosusPath: rhosusPath,
207
Cluster: cluster.Config{
208
WalPath: path.Join(rhosusPath, "wal"),
209
ClusterAddr: clusterAddr,
217
func getId(rhosusPath string, persistent bool) string {
221
v4id, _ := uuid.NewV4()
225
uuidFilePath := path.Join(rhosusPath, uuidFileName)
227
// since we are just testing, we don't need that yet
228
if util.FileExists(uuidFilePath) {
229
file, err := os.OpenFile(uuidFilePath, os.O_RDONLY, 0666)
233
log.Fatal().Err(err).Str("path", uuidFilePath).Msg("error opening node uuid file")
235
data, err := io.ReadAll(file)
237
log.Fatal().Err(err).Str("path", uuidFilePath).Msg("error reading node uuid file")
242
v4uid, _ := uuid.NewV4()
245
file, err := os.OpenFile(uuidFilePath, os.O_CREATE|os.O_RDWR, 0755)
247
log.Fatal().Err(err).Msg("error opening node uuid file")
250
file.Write([]byte(id))
256
func handleSignals(shutdownCh chan<- struct{}) {
257
sigc := make(chan os.Signal, 1)
258
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, os.Interrupt, syscall.SIGTERM)
261
log.Info().Str("signal", sig.String()).Msg("system signal received")
265
case syscall.SIGINT, os.Interrupt, syscall.SIGTERM:
267
pidFile := viper.GetString("pid_file")
268
shutdownTimeout := time.Duration(viper.GetInt("shutdown_timeout")) * time.Second
272
go time.AfterFunc(shutdownTimeout, func() {
283
welcome := " ____ __ ______ _____ __ _______\n / __ \\/ / / / __ \\/ ___// / / / ___/\n / /_/ / /_/ / / / /\\__ \\/ / / /\\__ \\ \n / _, _/ __ / /_/ /___/ / /_/ /___/ / \n/_/ |_/_/ /_/\\____//____/\\____//____/ \n "
286
fmt.Println("\n|------ Rhosus registry")
287
fmt.Println("|------ Version " + util.Version() + "\n")