-
Notifications
You must be signed in to change notification settings - Fork 220
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement File based configuration (#351)
* Implement file-based configuration * Implement file-based configuration * Replace DefaultServerCapabilities with NewDefaultServerCapabilities() to avoid data race (#360) Co-authored-by: JB <[email protected]> * Only pass a copy of system.Info to hooks (#365) * Only pass a copy of system.Info to hooks * Rename Itoa to Int64toa --------- Co-authored-by: JB <[email protected]> * Allow configurable max stored qos > 0 messages (#359) * Allow configurable max stored qos > 0 messages * Only rollback Inflight if QoS > 0 * Only rollback Inflight if QoS > 0 * Minor refactor * Update server version * Implement file-based configuration * Implement file-based configuration * update configs with maximum_inflight value * update docker configuration * fix tests --------- Co-authored-by: mochi-co <[email protected]> Co-authored-by: thedevop <[email protected]>
- Loading branch information
1 parent
26720c2
commit 26418c6
Showing
44 changed files
with
1,160 additions
and
219 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// SPDX-License-Identifier: MIT | ||
// SPDX-FileCopyrightText: 2023 mochi-mqtt | ||
// SPDX-FileContributor: dgduncan, mochi-co | ||
|
||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"github.com/mochi-mqtt/server/v2/config" | ||
"log" | ||
"log/slog" | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
|
||
mqtt "github.com/mochi-mqtt/server/v2" | ||
) | ||
|
||
func main() { | ||
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, nil))) // set basic logger to ensure logs before configuration are in a consistent format | ||
|
||
configFile := flag.String("config", "config.yaml", "path to mochi config yaml or json file") | ||
flag.Parse() | ||
|
||
entries, err := os.ReadDir("./") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
for _, e := range entries { | ||
fmt.Println(e.Name()) | ||
} | ||
|
||
sigs := make(chan os.Signal, 1) | ||
done := make(chan bool, 1) | ||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) | ||
go func() { | ||
<-sigs | ||
done <- true | ||
}() | ||
|
||
configBytes, err := os.ReadFile(*configFile) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
options, err := config.FromBytes(configBytes) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
server := mqtt.New(options) | ||
|
||
go func() { | ||
err := server.Serve() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
}() | ||
|
||
<-done | ||
server.Log.Warn("caught signal, stopping...") | ||
_ = server.Close() | ||
server.Log.Info("mochi mqtt shutdown complete") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
listeners: | ||
- type: "tcp" | ||
id: "tcp12" | ||
address: ":1883" | ||
- type: "ws" | ||
id: "ws1" | ||
address: ":1882" | ||
- type: "sysinfo" | ||
id: "stats" | ||
address: ":1880" | ||
hooks: | ||
auth: | ||
allow_all: true | ||
options: | ||
inline_client: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// SPDX-License-Identifier: MIT | ||
// SPDX-FileCopyrightText: 2023 mochi-mqtt, mochi-co | ||
// SPDX-FileContributor: mochi-co | ||
|
||
package config | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/mochi-mqtt/server/v2/hooks/auth" | ||
"github.com/mochi-mqtt/server/v2/hooks/debug" | ||
"github.com/mochi-mqtt/server/v2/hooks/storage/badger" | ||
"github.com/mochi-mqtt/server/v2/hooks/storage/bolt" | ||
"github.com/mochi-mqtt/server/v2/hooks/storage/redis" | ||
"github.com/mochi-mqtt/server/v2/listeners" | ||
"gopkg.in/yaml.v3" | ||
|
||
mqtt "github.com/mochi-mqtt/server/v2" | ||
) | ||
|
||
// config defines the structure of configuration data to be parsed from a config source. | ||
type config struct { | ||
Options mqtt.Options | ||
Listeners []listeners.Config `yaml:"listeners" json:"listeners"` | ||
HookConfigs HookConfigs `yaml:"hooks" json:"hooks"` | ||
} | ||
|
||
// HookConfigs contains configurations to enable individual hooks. | ||
type HookConfigs struct { | ||
Auth *HookAuthConfig `yaml:"auth" json:"auth"` | ||
Storage *HookStorageConfig `yaml:"storage" json:"storage"` | ||
Debug *debug.Options `yaml:"debug" json:"debug"` | ||
} | ||
|
||
// HookAuthConfig contains configurations for the auth hook. | ||
type HookAuthConfig struct { | ||
Ledger auth.Ledger `yaml:"ledger" json:"ledger"` | ||
AllowAll bool `yaml:"allow_all" json:"allow_all"` | ||
} | ||
|
||
// HookStorageConfig contains configurations for the different storage hooks. | ||
type HookStorageConfig struct { | ||
Badger *badger.Options `yaml:"badger" json:"badger"` | ||
Bolt *bolt.Options `yaml:"bolt" json:"bolt"` | ||
Redis *redis.Options `yaml:"redis" json:"redis"` | ||
} | ||
|
||
// ToHooks converts Hook file configurations into Hooks to be added to the server. | ||
func (hc HookConfigs) ToHooks() []mqtt.HookLoadConfig { | ||
var hlc []mqtt.HookLoadConfig | ||
|
||
if hc.Auth != nil { | ||
hlc = append(hlc, hc.toHooksAuth()...) | ||
} | ||
|
||
if hc.Storage != nil { | ||
hlc = append(hlc, hc.toHooksStorage()...) | ||
} | ||
|
||
if hc.Debug != nil { | ||
hlc = append(hlc, mqtt.HookLoadConfig{ | ||
Hook: new(debug.Hook), | ||
Config: hc.Debug, | ||
}) | ||
} | ||
|
||
return hlc | ||
} | ||
|
||
// toHooksAuth converts auth hook configurations into auth hooks. | ||
func (hc HookConfigs) toHooksAuth() []mqtt.HookLoadConfig { | ||
var hlc []mqtt.HookLoadConfig | ||
if hc.Auth.AllowAll { | ||
hlc = append(hlc, mqtt.HookLoadConfig{ | ||
Hook: new(auth.AllowHook), | ||
}) | ||
} else { | ||
hlc = append(hlc, mqtt.HookLoadConfig{ | ||
Hook: new(auth.Hook), | ||
Config: &auth.Options{ | ||
Ledger: &auth.Ledger{ // avoid copying sync.Locker | ||
Users: hc.Auth.Ledger.Users, | ||
Auth: hc.Auth.Ledger.Auth, | ||
ACL: hc.Auth.Ledger.ACL, | ||
}, | ||
}, | ||
}) | ||
} | ||
return hlc | ||
} | ||
|
||
// toHooksAuth converts storage hook configurations into storage hooks. | ||
func (hc HookConfigs) toHooksStorage() []mqtt.HookLoadConfig { | ||
var hlc []mqtt.HookLoadConfig | ||
if hc.Storage.Badger != nil { | ||
hlc = append(hlc, mqtt.HookLoadConfig{ | ||
Hook: new(badger.Hook), | ||
Config: hc.Storage.Badger, | ||
}) | ||
} | ||
|
||
if hc.Storage.Bolt != nil { | ||
hlc = append(hlc, mqtt.HookLoadConfig{ | ||
Hook: new(bolt.Hook), | ||
Config: hc.Storage.Bolt, | ||
}) | ||
} | ||
|
||
if hc.Storage.Redis != nil { | ||
hlc = append(hlc, mqtt.HookLoadConfig{ | ||
Hook: new(redis.Hook), | ||
Config: hc.Storage.Redis, | ||
}) | ||
} | ||
return hlc | ||
} | ||
|
||
// FromBytes unmarshals a byte slice of JSON or YAML config data into a valid server options value. | ||
// Any hooks configurations are converted into Hooks using the toHooks methods in this package. | ||
func FromBytes(b []byte) (*mqtt.Options, error) { | ||
c := new(config) | ||
o := mqtt.Options{} | ||
|
||
if len(b) == 0 { | ||
return nil, nil | ||
} | ||
|
||
if b[0] == '{' { | ||
err := json.Unmarshal(b, c) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
err := yaml.Unmarshal(b, c) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
o = c.Options | ||
o.Hooks = c.HookConfigs.ToHooks() | ||
o.Listeners = c.Listeners | ||
|
||
return &o, nil | ||
} |
Oops, something went wrong.