mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
#23905
- Update with upstream nanomdm changes up to
825f2979a2
- Removed PostgeSQL folder from our nanomdm
- Added nanomdm MySQL test job to our CI
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/Committing-Changes.md#changes-files)
for more information.
- [x] Added/updated tests
- [x] Manual QA for all new/changed functionality
137 lines
3.4 KiB
Go
137 lines
3.4 KiB
Go
// Package cli contains shared command-line helpers and utilities.
|
|
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/storage"
|
|
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/storage/allmulti"
|
|
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/storage/file"
|
|
"github.com/fleetdm/fleet/v4/server/mdm/nanomdm/storage/mysql"
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
_ "github.com/lib/pq"
|
|
"github.com/micromdm/nanolib/log"
|
|
)
|
|
|
|
type StringAccumulator []string
|
|
|
|
func (s *StringAccumulator) String() string {
|
|
return strings.Join(*s, ",")
|
|
}
|
|
|
|
func (s *StringAccumulator) Set(value string) error {
|
|
*s = append(*s, value)
|
|
return nil
|
|
}
|
|
|
|
type Storage struct {
|
|
Storage StringAccumulator
|
|
DSN StringAccumulator
|
|
Options StringAccumulator
|
|
}
|
|
|
|
func NewStorage() *Storage {
|
|
return &Storage{}
|
|
}
|
|
|
|
func (s *Storage) Parse(logger log.Logger) (storage.AllStorage, error) {
|
|
if len(s.Storage) != len(s.DSN) {
|
|
return nil, errors.New("must have same number of storage and DSN flags")
|
|
}
|
|
if len(s.Options) > 0 && len(s.Storage) != len(s.Options) {
|
|
return nil, errors.New("must have same number of storage and storage options flags")
|
|
}
|
|
// default storage and DSN pair
|
|
if len(s.Storage) < 1 {
|
|
s.Storage = append(s.Storage, "file")
|
|
s.DSN = append(s.DSN, "db")
|
|
}
|
|
var mdmStorage []storage.AllStorage
|
|
for idx, storage := range s.Storage {
|
|
dsn := s.DSN[idx]
|
|
options := ""
|
|
if len(s.Options) > 0 {
|
|
options = s.Options[idx]
|
|
}
|
|
logger.Info(
|
|
"msg", "storage setup",
|
|
"storage", storage,
|
|
)
|
|
switch storage {
|
|
case "file":
|
|
fileStorage, err := fileStorageConfig(dsn, options)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mdmStorage = append(mdmStorage, fileStorage)
|
|
case "mysql":
|
|
mysqlStorage, err := mysqlStorageConfig(dsn, options, logger)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
mdmStorage = append(mdmStorage, mysqlStorage)
|
|
default:
|
|
return nil, fmt.Errorf("unknown storage: %s", storage)
|
|
}
|
|
}
|
|
if len(mdmStorage) < 1 {
|
|
return nil, errors.New("no storage setup")
|
|
}
|
|
if len(mdmStorage) == 1 {
|
|
return mdmStorage[0], nil
|
|
}
|
|
logger.Info("msg", "storage setup", "storage", "multi-storage", "count", len(mdmStorage))
|
|
return allmulti.New(
|
|
logger.With("component", "multi-storage"),
|
|
mdmStorage...,
|
|
), nil
|
|
}
|
|
|
|
var NoStorageOptions = errors.New("storage backend does not support options, please specify no (or empty) options")
|
|
|
|
func fileStorageConfig(dsn, options string) (*file.FileStorage, error) {
|
|
if options != "" {
|
|
return nil, NoStorageOptions
|
|
}
|
|
return file.New(dsn)
|
|
}
|
|
|
|
func mysqlStorageConfig(dsn, options string, logger log.Logger) (*mysql.MySQLStorage, error) {
|
|
logger = logger.With("storage", "mysql")
|
|
opts := []mysql.Option{
|
|
mysql.WithDSN(dsn),
|
|
mysql.WithLogger(logger),
|
|
}
|
|
if options != "" {
|
|
for k, v := range splitOptions(options) {
|
|
switch k {
|
|
case "delete":
|
|
if v == "1" {
|
|
opts = append(opts, mysql.WithDeleteCommands())
|
|
logger.Debug("msg", "deleting commands")
|
|
} else if v != "0" {
|
|
return nil, fmt.Errorf("invalid value for delete option: %q", v)
|
|
}
|
|
default:
|
|
return nil, fmt.Errorf("invalid option: %q", k)
|
|
}
|
|
}
|
|
}
|
|
return mysql.New(opts...)
|
|
}
|
|
|
|
func splitOptions(s string) map[string]string {
|
|
out := make(map[string]string)
|
|
opts := strings.Split(s, ",")
|
|
for _, opt := range opts {
|
|
optKAndV := strings.SplitN(opt, "=", 2)
|
|
if len(optKAndV) < 2 {
|
|
optKAndV = append(optKAndV, "")
|
|
}
|
|
out[optKAndV[0]] = optKAndV[1]
|
|
}
|
|
return out
|
|
}
|