diff options
| author | Shulhan <ms@kilabit.info> | 2025-08-20 23:25:17 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2025-08-20 23:25:17 +0700 |
| commit | 5b33f2080ccfe3742d60fa769de61f4ff1618bd9 (patch) | |
| tree | 6a7400da12b3efc9adacf437086f614083f1d538 | |
| parent | f9c0f7d0e73c89b7473b7c0123427b934fcbff65 (diff) | |
| download | lilin-5b33f2080ccfe3742d60fa769de61f4ff1618bd9.tar.xz | |
all: rename suffix Options with Config
Options means optional, while the field in struct may contains
mandatory or must not be empty.
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | client.go | 14 | ||||
| -rw-r--r-- | client_config.go (renamed from client_options.go) | 14 | ||||
| -rw-r--r-- | cmd/lilin/main.go | 6 | ||||
| -rw-r--r-- | lilin_test.go | 8 | ||||
| -rw-r--r-- | server.go | 18 | ||||
| -rw-r--r-- | server_config.go (renamed from server_options.go) | 32 | ||||
| -rw-r--r-- | service.go | 28 | ||||
| -rw-r--r-- | service_config.go (renamed from service_options.go) | 50 | ||||
| -rw-r--r-- | service_report.go | 20 | ||||
| -rw-r--r-- | service_report_test.go | 6 | ||||
| -rw-r--r-- | service_test.go | 6 | ||||
| -rw-r--r-- | worker.go | 20 | ||||
| -rw-r--r-- | worker_test.go | 18 |
14 files changed, 123 insertions, 118 deletions
@@ -3,3 +3,4 @@ /cover.html /cover.out +/testdata/var/log/lilin/service.d/*.log @@ -14,25 +14,25 @@ import ( // Client of Lilin server. type Client struct { - httpc *http.Client - Options ClientOptions + httpc *http.Client + Config ClientConfig } // NewClient create new client using the provided options. -func NewClient(opts ClientOptions) (client *Client, err error) { +func NewClient(cfg ClientConfig) (client *Client, err error) { var logp = `NewClient` client = &Client{ - Options: opts, + Config: cfg, } - err = client.Options.init() + err = client.Config.init() if err != nil { return nil, fmt.Errorf(`%s: %w`, logp, err) } client.httpc = &http.Client{ - Timeout: client.Options.Timeout, + Timeout: client.Config.Timeout, } return client, nil } @@ -41,7 +41,7 @@ func NewClient(opts ClientOptions) (client *Client, err error) { func (client *Client) ServicesSummary() (summary []Service, err error) { var logp = `ServicesSummary` - var reqURL = *client.Options.serverURL + var reqURL = *client.Config.serverURL reqURL.Path = pathAPIServicesSummary var httpReq = http.Request{ diff --git a/client_options.go b/client_config.go index 3203478..99a0f2e 100644 --- a/client_options.go +++ b/client_config.go @@ -9,8 +9,8 @@ import ( "time" ) -// ClientOptions options for client. -type ClientOptions struct { +// ClientConfig options for client. +type ClientConfig struct { serverURL *url.URL // ServerURL define the full URL of Lilin server. @@ -21,20 +21,20 @@ type ClientOptions struct { } // init validate and initialize the options.` -func (opts *ClientOptions) init() (err error) { +func (cfg *ClientConfig) init() (err error) { var logp = `init` - if opts.ServerURL == `` { + if cfg.ServerURL == `` { return fmt.Errorf(`%s: missing ServerURL`, logp) } - opts.serverURL, err = url.Parse(opts.ServerURL) + cfg.serverURL, err = url.Parse(cfg.ServerURL) if err != nil { return fmt.Errorf(`%s: %s`, logp, err) } - if opts.Timeout == 0 { - opts.Timeout = defTimeout + if cfg.Timeout == 0 { + cfg.Timeout = defTimeout } return nil } diff --git a/cmd/lilin/main.go b/cmd/lilin/main.go index dd97f72..70d68d0 100644 --- a/cmd/lilin/main.go +++ b/cmd/lilin/main.go @@ -15,17 +15,17 @@ import ( ) func main() { - var serverOpts = lilin.ServerOptions{ + var serverCfg = lilin.ServerConfig{ BaseDir: `testdata`, } - flag.BoolVar(&serverOpts.IsDevelopment, `dev`, false, + flag.BoolVar(&serverCfg.IsDevelopment, `dev`, false, `Enable development mode`) flag.Parse() var server *lilin.Server var err error - server, err = lilin.NewServer(serverOpts) + server, err = lilin.NewServer(serverCfg) if err != nil { log.Fatal(err) } diff --git a/lilin_test.go b/lilin_test.go index 3e1899d..e4db531 100644 --- a/lilin_test.go +++ b/lilin_test.go @@ -47,7 +47,7 @@ func TestMain(m *testing.M) { } func startServer() (server *lilin.Server) { - var serverOpts = lilin.ServerOptions{ + var serverOpts = lilin.ServerConfig{ BaseDir: `testdata`, } var err error @@ -64,7 +64,7 @@ func startServer() (server *lilin.Server) { } }() - err = net.WaitAlive(`tcp`, server.Options.Address, 5*time.Second) + err = net.WaitAlive(`tcp`, server.Config.Address, 5*time.Second) if err != nil { log.Fatal(err) } @@ -72,8 +72,8 @@ func startServer() (server *lilin.Server) { } func createClient(server *lilin.Server) (client *lilin.Client) { - var clientOpts = lilin.ClientOptions{ - ServerURL: `http://` + server.Options.Address, + var clientOpts = lilin.ClientConfig{ + ServerURL: `http://` + server.Config.Address, } var err error @@ -33,7 +33,7 @@ type Server struct { // from worker. updateq chan struct{} - Options ServerOptions + Config ServerConfig pageIndexTmpl *template.Template pageIndexBody bytes.Buffer @@ -44,20 +44,20 @@ type Server struct { } // NewServer create new server to serve the content of _www and HTTP APIs. -func NewServer(opts ServerOptions) (srv *Server, err error) { +func NewServer(cfg ServerConfig) (srv *Server, err error) { var logp = `NewServer` srv = &Server{ - Options: opts, + Config: cfg, updateq: make(chan struct{}, 1), } - err = srv.Options.init() + err = srv.Config.init() if err != nil { return nil, fmt.Errorf(`%s: %w`, logp, err) } - srv.worker, err = newWorker(srv.Options) + srv.worker, err = newWorker(srv.Config) if err != nil { return nil, fmt.Errorf(`%s: %w`, logp, err) } @@ -75,7 +75,7 @@ func NewServer(opts ServerOptions) (srv *Server, err error) { mux.Handle(`GET /`, srv) srv.httpd = &http.Server{ - Addr: srv.Options.Address, + Addr: srv.Config.Address, Handler: mux, ReadTimeout: 5 * time.Second, WriteTimeout: 5 * time.Second, @@ -84,7 +84,7 @@ func NewServer(opts ServerOptions) (srv *Server, err error) { } func (srv *Server) initFS() (err error) { - if srv.Options.IsDevelopment { + if srv.Config.IsDevelopment { var dirfs = os.DirFS(`_www`) srv.fs = dirfs.(fs.ReadFileFS) } else { @@ -139,7 +139,7 @@ func (srv *Server) ListenAndServe() (err error) { go srv.update() go srv.worker.start(srv.updateq) - log.Printf(`lilin: starting HTTP server at %s`, srv.Options.Address) + log.Printf(`lilin: starting HTTP server at %s`, srv.Config.Address) err = srv.httpd.ListenAndServe() if err != nil { @@ -212,7 +212,7 @@ func (srv *Server) update() { srv.worker.Reports.Lock() srv.pageIndexBody.Reset() - if srv.Options.IsDevelopment { + if srv.Config.IsDevelopment { err = srv.initTemplate() } else { err = srv.pageIndexTmpl.Execute( diff --git a/server_options.go b/server_config.go index 48c47b6..50d93ff 100644 --- a/server_options.go +++ b/server_config.go @@ -11,8 +11,8 @@ import ( "git.sr.ht/~shulhan/pakakeh.go/lib/ini" ) -// ServerOptions define the options for Lilin Server. -type ServerOptions struct { +// ServerConfig define the options for Lilin Server. +type ServerConfig struct { // BaseDir define the base directory for running the server, default // to "/". // Its affect where to read the configuration, storing states, and @@ -37,43 +37,43 @@ type ServerOptions struct { } // init initialize the server by reading the configuration from -// [ServerOptions.BaseDir]/etc/lilin/lilin.cfg. -func (opts *ServerOptions) init() (err error) { +// [ServerConfig.BaseDir]/etc/lilin/lilin.cfg. +func (cfg *ServerConfig) init() (err error) { var logp = `init` - if opts.BaseDir == `` { - opts.BaseDir = `/` + if cfg.BaseDir == `` { + cfg.BaseDir = `/` } - opts.configDir = filepath.Join(opts.BaseDir, `etc`, `lilin`) - opts.configServiceDir = filepath.Join(opts.configDir, `service.d`) - opts.logServiceDir = filepath.Join(opts.BaseDir, `var`, `log`, `lilin`, `service.d`) + cfg.configDir = filepath.Join(cfg.BaseDir, `etc`, `lilin`) + cfg.configServiceDir = filepath.Join(cfg.configDir, `service.d`) + cfg.logServiceDir = filepath.Join(cfg.BaseDir, `var`, `log`, `lilin`, `service.d`) - err = os.MkdirAll(opts.logServiceDir, 0700) + err = os.MkdirAll(cfg.logServiceDir, 0700) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } // Load main configuration. - var cfg = filepath.Join(opts.configDir, `lilin.cfg`) - _, err = os.Stat(cfg) + var fileCfg = filepath.Join(cfg.configDir, `lilin.cfg`) + _, err = os.Stat(fileCfg) if err != nil { return nil } var rawconf []byte - rawconf, err = os.ReadFile(cfg) + rawconf, err = os.ReadFile(fileCfg) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } - err = ini.Unmarshal(rawconf, opts) + err = ini.Unmarshal(rawconf, cfg) if err != nil { return fmt.Errorf(`%s: %w`, logp, err) } - if opts.Address == `` { - opts.Address = defAddress + if cfg.Address == `` { + cfg.Address = defAddress } return nil @@ -17,16 +17,16 @@ type Service struct { httpConn *http.Client dialer *net.Dialer ticker *time.Ticker - opts ServiceOptions + cfg ServiceConfig isReady bool } // NewService create and initialize the connection to service. -func NewService(opts ServiceOptions) (svc *Service, err error) { +func NewService(cfg ServiceConfig) (svc *Service, err error) { svc = &Service{ - opts: opts, + cfg: cfg, } - err = svc.opts.init() + err = svc.cfg.init() if err != nil { return nil, fmt.Errorf(`NewService: %w`, err) } @@ -37,7 +37,7 @@ func NewService(opts ServiceOptions) (svc *Service, err error) { func (svc *Service) Scan() (report ScanReport) { var err error - report.Name = svc.opts.Name + report.Name = svc.cfg.Name report.At = internal.Now() if !svc.isReady { err = svc.connect() @@ -47,11 +47,11 @@ func (svc *Service) Scan() (report ScanReport) { } } - switch svc.opts.scanURL.Scheme { + switch svc.cfg.scanURL.Scheme { case serviceKindHTTP, serviceKindHTTPS: var req = &http.Request{ - Method: svc.opts.HTTPMethod, - URL: svc.opts.scanURL, + Method: svc.cfg.HTTPMethod, + URL: svc.cfg.scanURL, } var httpResp *http.Response httpResp, err = svc.httpConn.Do(req) @@ -66,7 +66,7 @@ func (svc *Service) Scan() (report ScanReport) { case serviceKindTCP, serviceKindUDP: var conn net.Conn - conn, err = svc.dialer.Dial(svc.opts.scanURL.Scheme, svc.opts.scanURL.Host) + conn, err = svc.dialer.Dial(svc.cfg.scanURL.Scheme, svc.cfg.scanURL.Host) if err != nil { report.Error = err.Error() return report @@ -82,14 +82,14 @@ func (svc *Service) Scan() (report ScanReport) { // Start scanning periodically and send the report to reportq. func (svc *Service) Start(reportq chan<- ScanReport) { - svc.ticker = time.NewTicker(svc.opts.interval) + svc.ticker = time.NewTicker(svc.cfg.interval) reportq <- svc.Scan() for { _, ok := <-svc.ticker.C if !ok { - log.Printf("Service: %s not ok", svc.opts.Name) + log.Printf("Service: %s not ok", svc.cfg.Name) return } reportq <- svc.Scan() @@ -102,15 +102,15 @@ func (svc *Service) Stop() { } func (svc *Service) connect() (err error) { - switch svc.opts.scanURL.Scheme { + switch svc.cfg.scanURL.Scheme { case serviceKindHTTP, serviceKindHTTPS: svc.httpConn = &http.Client{ - Timeout: svc.opts.timeout, + Timeout: svc.cfg.timeout, } case serviceKindTCP, serviceKindUDP: svc.dialer = &net.Dialer{ - Timeout: svc.opts.timeout, + Timeout: svc.cfg.timeout, } } svc.isReady = true diff --git a/service_options.go b/service_config.go index fc0da11..9f9e0fc 100644 --- a/service_options.go +++ b/service_config.go @@ -21,9 +21,9 @@ const ( ) // defInterval define default interval in between scanning run. -const defInterval = 1 * time.Minute +const defInterval = 10 * time.Second -type ServiceOptions struct { +type ServiceConfig struct { scanURL *url.URL Name string @@ -49,63 +49,63 @@ type ServiceOptions struct { interval time.Duration } -func (opts *ServiceOptions) init() (err error) { - opts.scanURL, err = url.Parse(opts.Address) +func (cfg *ServiceConfig) init() (err error) { + cfg.scanURL, err = url.Parse(cfg.Address) if err != nil { - return fmt.Errorf(`invalid address %s`, opts.Address) + return fmt.Errorf(`invalid address %s`, cfg.Address) } - var scheme = strings.ToLower(opts.scanURL.Scheme) + var scheme = strings.ToLower(cfg.scanURL.Scheme) switch scheme { case `http`, `https`: - var httpMethod = strings.ToUpper(opts.HTTPMethod) + var httpMethod = strings.ToUpper(cfg.HTTPMethod) switch httpMethod { case ``: - opts.HTTPMethod = http.MethodGet + cfg.HTTPMethod = http.MethodGet case http.MethodDelete, http.MethodGet, http.MethodHead, http.MethodOptions, http.MethodPatch, http.MethodPost, http.MethodPut: - opts.HTTPMethod = httpMethod + cfg.HTTPMethod = httpMethod default: - return fmt.Errorf(`invalid HTTP method %s`, opts.HTTPMethod) + return fmt.Errorf(`invalid HTTP method %s`, cfg.HTTPMethod) } case serviceKindTCP: - _, err = net.ResolveTCPAddr(scheme, opts.scanURL.Host) + _, err = net.ResolveTCPAddr(scheme, cfg.scanURL.Host) if err != nil { - return fmt.Errorf(`invalid TCP address %s`, opts.Address) + return fmt.Errorf(`invalid TCP address %s`, cfg.Address) } case serviceKindUDP: - _, err = net.ResolveUDPAddr(scheme, opts.scanURL.Host) + _, err = net.ResolveUDPAddr(scheme, cfg.scanURL.Host) if err != nil { - return fmt.Errorf(`invalid UDP address %s`, opts.Address) + return fmt.Errorf(`invalid UDP address %s`, cfg.Address) } default: return fmt.Errorf(`unknown scheme in address %s`, scheme) } - if len(opts.Timeout) == 0 { - opts.timeout = defTimeout + if len(cfg.Timeout) == 0 { + cfg.timeout = defTimeout } else { - opts.timeout, err = time.ParseDuration(opts.Timeout) + cfg.timeout, err = time.ParseDuration(cfg.Timeout) if err != nil { - return fmt.Errorf(`invalid Timeout %s`, opts.Timeout) + return fmt.Errorf(`invalid Timeout %s`, cfg.Timeout) } } - if len(opts.Interval) == 0 { - opts.interval = defInterval + if len(cfg.Interval) == 0 { + cfg.interval = defInterval } else { - opts.interval, err = time.ParseDuration(opts.Interval) + cfg.interval, err = time.ParseDuration(cfg.Interval) if err != nil { - return fmt.Errorf(`invalid Interval %s`, opts.Interval) + return fmt.Errorf(`invalid Interval %s`, cfg.Interval) } - if opts.interval < defInterval { + if cfg.interval < defInterval { log.Printf(`%s: interval is less than %s, revert to default`, - opts.Name, defInterval) - opts.interval = defInterval + cfg.Name, defInterval) + cfg.interval = defInterval } } return nil diff --git a/service_report.go b/service_report.go index 7aee321..492e368 100644 --- a/service_report.go +++ b/service_report.go @@ -28,19 +28,19 @@ type ServiceReport struct { History []ScanReport } -func NewServiceReport(opts ServerOptions, name string) ( +func NewServiceReport(cfg ServerConfig, name string) ( svcReport *ServiceReport, err error, ) { var logp = `NewServiceReport` svcReport = &ServiceReport{ - logPath: filepath.Join(opts.logServiceDir, name+`.log`), + logPath: filepath.Join(cfg.logServiceDir, name+`.log`), Name: name, History: make([]ScanReport, 0, historyMax), } svcReport.logf, err = os.OpenFile(svcReport.logPath, - os.O_WRONLY|os.O_CREATE, 0600) + os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0600) if err != nil { return nil, fmt.Errorf(`%s: %w`, logp, err) } @@ -52,6 +52,7 @@ func NewServiceReport(opts ServerOptions, name string) ( // Close release any resources opened by report. func (svcReport *ServiceReport) Close() (err error) { + svcReport.writer.Flush() err = svcReport.logf.Close() if err != nil { return fmt.Errorf(`Close: %w`, err) @@ -60,16 +61,19 @@ func (svcReport *ServiceReport) Close() (err error) { } func (svcReport *ServiceReport) Store(scanReport ScanReport) { + var record = scanReport.toCSV() + log.Printf(`Store: %v`, record) + var err = svcReport.writer.Write(record) + if err != nil { + log.Printf(`Store: %s`, err) + } + svcReport.Last = scanReport svcReport.History = append(svcReport.History, scanReport) if len(svcReport.History) == historyMax { + svcReport.writer.Flush() var start = len(svcReport.History) - historyKeepSize copy(svcReport.History, svcReport.History[start:]) svcReport.History = svcReport.History[:historyKeepSize-1] } - var record = scanReport.toCSV() - var err = svcReport.writer.Write(record) - if err != nil { - log.Printf(`Store: %s`, err) - } } diff --git a/service_report_test.go b/service_report_test.go index 95fc27d..c61f543 100644 --- a/service_report_test.go +++ b/service_report_test.go @@ -12,16 +12,16 @@ import ( ) func TestServiceReport_Store(t *testing.T) { - var serverOpts = ServerOptions{ + var serverCfg = ServerConfig{ BaseDir: `testdata`, } - var err = serverOpts.init() + var err = serverCfg.init() if err != nil { t.Fatal(err) } var svcReport *ServiceReport - svcReport, err = NewServiceReport(serverOpts, `testStore`) + svcReport, err = NewServiceReport(serverCfg, `testStore`) if err != nil { t.Fatal(err) } diff --git a/service_test.go b/service_test.go index bd58b91..aeb1562 100644 --- a/service_test.go +++ b/service_test.go @@ -14,11 +14,11 @@ import ( func TestServiceStart_HTTP(t *testing.T) { type testCase struct { expReport lilin.ScanReport - opts lilin.ServiceOptions + cfg lilin.ServiceConfig } var listCase = []testCase{{ - opts: lilin.ServiceOptions{ + cfg: lilin.ServiceConfig{ Name: `http_service`, Address: `http://` + dummyHTTPAddress + `/health`, }, @@ -31,7 +31,7 @@ func TestServiceStart_HTTP(t *testing.T) { var reportq = make(chan lilin.ScanReport, 1) for _, tcase := range listCase { - svc, err := lilin.NewService(tcase.opts) + svc, err := lilin.NewService(tcase.cfg) if err != nil { t.Fatal(err) } @@ -22,12 +22,12 @@ type worker struct { Reports Reports } -func newWorker(opts ServerOptions) (wrk *worker, err error) { +func newWorker(cfg ServerConfig) (wrk *worker, err error) { wrk = &worker{ Services: make(map[string]*Service), } - err = wrk.loadServiceDir(opts) + err = wrk.loadServiceDir(cfg) if err != nil { return nil, err } @@ -36,7 +36,7 @@ func newWorker(opts ServerOptions) (wrk *worker, err error) { Services: make(map[string]*ServiceReport, len(wrk.Services)), } for name := range wrk.Services { - wrk.Reports.Services[name], err = NewServiceReport(opts, name) + wrk.Reports.Services[name], err = NewServiceReport(cfg, name) if err != nil { return nil, err } @@ -45,13 +45,13 @@ func newWorker(opts ServerOptions) (wrk *worker, err error) { } type serviceConfigs struct { - Options map[string]ServiceOptions `ini:"service"` + Config map[string]ServiceConfig `ini:"service"` } // loadServiceDir Load all the service configurations. -func (wrk *worker) loadServiceDir(opts ServerOptions) (err error) { +func (wrk *worker) loadServiceDir(cfg ServerConfig) (err error) { var listde []os.DirEntry - listde, err = os.ReadDir(opts.configServiceDir) + listde, err = os.ReadDir(cfg.configServiceDir) if err != nil { return err } @@ -71,7 +71,7 @@ func (wrk *worker) loadServiceDir(opts ServerOptions) (err error) { continue } - var serviceCfg = filepath.Join(opts.configServiceDir, name) + var serviceCfg = filepath.Join(cfg.configServiceDir, name) var rawcfg []byte rawcfg, err = os.ReadFile(serviceCfg) @@ -85,9 +85,9 @@ func (wrk *worker) loadServiceDir(opts ServerOptions) (err error) { } } var svc *Service - for name, svcOpts := range svcConfigs.Options { - svcOpts.Name = name - svc, err = NewService(svcOpts) + for name, svcConfig := range svcConfigs.Config { + svcConfig.Name = name + svc, err = NewService(svcConfig) if err != nil { return err } diff --git a/worker_test.go b/worker_test.go index a149b5a..8863542 100644 --- a/worker_test.go +++ b/worker_test.go @@ -15,26 +15,26 @@ func TestNewWorker(t *testing.T) { type testCase struct { expServices map[string]*Service expError string - serverOpts ServerOptions + serverCfg ServerConfig } var listCase = []testCase{{ - serverOpts: ServerOptions{ + serverCfg: ServerConfig{ BaseDir: `testdata/worker/withoutServiceDir/`, }, expError: `open testdata/worker/withoutServiceDir/etc/lilin/service.d: no such file or directory`, }, { - serverOpts: ServerOptions{ + serverCfg: ServerConfig{ BaseDir: `testdata/worker/readError/`, }, expError: `open testdata/worker/readError/etc/lilin/service.d/broken.cfg: no such file or directory`, }, { - serverOpts: ServerOptions{ + serverCfg: ServerConfig{ BaseDir: `testdata/`, }, expServices: map[string]*Service{ `example http`: &Service{ - opts: ServiceOptions{ + cfg: ServiceConfig{ scanURL: &url.URL{ Scheme: `http`, Host: `127.0.0.1:6121`, @@ -49,7 +49,7 @@ func TestNewWorker(t *testing.T) { }, }, `example tcp`: &Service{ - opts: ServiceOptions{ + cfg: ServiceConfig{ scanURL: &url.URL{ Scheme: `tcp`, Host: `127.0.0.1:6122`, @@ -62,7 +62,7 @@ func TestNewWorker(t *testing.T) { }, }, `example udp`: &Service{ - opts: ServiceOptions{ + cfg: ServiceConfig{ scanURL: &url.URL{ Scheme: `udp`, Host: `127.0.0.1:6123`, @@ -78,12 +78,12 @@ func TestNewWorker(t *testing.T) { }} for _, tcase := range listCase { - err := tcase.serverOpts.init() + err := tcase.serverCfg.init() if err != nil { t.Fatal(err) } - wrk, err := newWorker(tcase.serverOpts) + wrk, err := newWorker(tcase.serverCfg) if err != nil { test.Assert(t, ``, tcase.expError, err.Error()) continue |
