节点在线、应用在线、配置在线使用令牌查询
大石头 authored at 2021-12-16 19:49:30
2.09 KiB
Stardust
package mockagent

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"sync"
)

// configFile is a minimal staragent.json reader/writer that preserves unknown
// fields while persisting Code/Secret across restarts.
type configFile struct {
	mu   sync.Mutex
	path string
	raw  map[string]any
}

func loadConfig(path string) (*configFile, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("read config: %w", err)
	}
	raw := map[string]any{}
	if len(data) > 0 {
		if err := json.Unmarshal(data, &raw); err != nil {
			return nil, fmt.Errorf("parse config %s: %w", path, err)
		}
	}

	return &configFile{path: path, raw: raw}, nil
}

func (c *configFile) string(key string) string {
	c.mu.Lock()
	defer c.mu.Unlock()
	if v, ok := c.raw[key]; ok {
		if s, ok := v.(string); ok {
			return s
		}
	}

	return ""
}

func (c *configFile) int(key string, def int) int {
	c.mu.Lock()
	defer c.mu.Unlock()
	if v, ok := c.raw[key]; ok {
		switch n := v.(type) {
		case float64:
			return int(n)
		case json.Number:
			if i, err := n.Int64(); err == nil {
				return int(i)
			}
		case string:
			if i, err := strconv.Atoi(n); err == nil {
				return i
			}
		}
	}

	return def
}

func (c *configFile) bool(key string, def bool) bool {
	c.mu.Lock()
	defer c.mu.Unlock()
	if v, ok := c.raw[key]; ok {
		if b, ok := v.(bool); ok {
			return b
		}
	}

	return def
}

func (c *configFile) persistSession(code, secret string) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	if code != "" {
		c.raw["Code"] = code
	}
	if secret != "" {
		c.raw["Secret"] = secret
	}

	return c.saveLocked()
}

func (c *configFile) persistServer(server string) error {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.raw["Server"] = server

	return c.saveLocked()
}

func (c *configFile) saveLocked() error {
	data, err := json.MarshalIndent(c.raw, "", "  ")
	if err != nil {
		return err
	}
	data = append(data, '\n')
	if dir := filepath.Dir(c.path); dir != "." && dir != "" {
		_ = os.MkdirAll(dir, 0o755)
	}
	tmp := c.path + ".tmp"
	if err := os.WriteFile(tmp, data, 0o600); err != nil {
		return err
	}

	return os.Rename(tmp, c.path)
}