From dfc441b32458d204dae6498867f08e7da483c815 Mon Sep 17 00:00:00 2001 From: Shulhan Date: Sat, 16 Apr 2022 01:06:38 +0700 Subject: cmd/resolver: implement command to fetch and print server environment The "env" command fetch the current server environment and print as ini format to stdout. --- _doc/resolver.1.gz | Bin 2143 -> 2226 bytes _doc/resolver.adoc | 22 ++++++++++++++-- client.go | 25 +++++++++++++++++- cmd/resolver/main.go | 23 ++++++++++++++++- cmd/resolver/resolver.go | 25 ++++++++++++++++++ environment.go | 65 +++++++++++++++++++++++++++++++++++++++-------- 6 files changed, 146 insertions(+), 14 deletions(-) diff --git a/_doc/resolver.1.gz b/_doc/resolver.1.gz index 599ce1d..db15a61 100644 Binary files a/_doc/resolver.1.gz and b/_doc/resolver.1.gz differ diff --git a/_doc/resolver.adoc b/_doc/resolver.adoc index 9c475d9..46fbc15 100644 --- a/_doc/resolver.adoc +++ b/_doc/resolver.adoc @@ -3,7 +3,7 @@ = RESOLVER(1) :doctype: manpage :man source: resolver -:man version: 2018.08.26 +:man version: 2022.04.15 :man manual: resolver @@ -115,6 +115,12 @@ Remove the domain name from rescached caches. If the parameter is "all", it will remove all caches. -- +env:: ++ +-- +Fetch the current server environment and print it as JSON format to stdout. +-- + == EXIT STATUS @@ -152,7 +158,19 @@ Inspect the rescached's caches on server at http://127.0.0.1:5380, Search caches that contains "bit" on the domain name, - $ resolver -server=http://127.0.0.1:5380 caches search bit + $ resolver caches search bit + +Remove caches that contains domain name "kilabit.info", + + $ resolver caches remove kilabit.info + +Remove all caches in the server, + + $ resolver caches remove all + +Fetch and print current server environment, + + $ resolver env == AUTHOR diff --git a/client.go b/client.go index 289f031..bafb16b 100644 --- a/client.go +++ b/client.go @@ -114,10 +114,33 @@ func (cl *Client) CachesSearch(q string) (listMsg []*dns.Message, err error) { if err != nil { return nil, fmt.Errorf("%s: %w", logp, err) } - if res.Code != http.StatusOK { return nil, fmt.Errorf("%s: %d %s", logp, res.Code, res.Message) } return listMsg, nil } + +// Env get the server environment. +func (cl *Client) Env() (env *Environment, err error) { + var ( + logp = "Env" + res = libhttp.EndpointResponse{ + Data: &env, + } + resb []byte + ) + + _, resb, err = cl.Get(apiEnvironment, nil, nil) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } + err = json.Unmarshal(resb, &res) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } + if res.Code != http.StatusOK { + return nil, fmt.Errorf("%s: %d %s", logp, res.Code, res.Message) + } + return env, nil +} diff --git a/cmd/resolver/main.go b/cmd/resolver/main.go index 90a1686..90fcc68 100644 --- a/cmd/resolver/main.go +++ b/cmd/resolver/main.go @@ -16,6 +16,7 @@ import ( // List of valid commands. const ( cmdCaches = "caches" + cmdEnv = "env" cmdQuery = "query" subCmdSearch = "search" @@ -83,6 +84,9 @@ func main() { os.Exit(2) } + case cmdEnv: + rsol.doCmdEnv() + case cmdQuery: args = args[1:] if len(args) == 0 { @@ -165,6 +169,11 @@ caches remove Remove the domain name from rescached caches. If the parameter is "all", it will remove all caches. +env + + Fetch the current server environment and print it as JSON format to + stdout. + == Examples @@ -197,5 +206,17 @@ Inspect the rescached's caches on server at http://127.0.0.1:5380, Search caches that contains "bit" on the domain name, - $ resolver -server=http://127.0.0.1:5380 caches search bit`) + $ resolver caches search bit + +Remove caches that contains domain name "kilabit.info", + + $ resolver caches remove kilabit.info + +Remove all caches in the server, + + $ resolver caches remove all + +Fetch and print current server environment, + + $ resolver env`) } diff --git a/cmd/resolver/resolver.go b/cmd/resolver/resolver.go index 1985981..b7129cc 100644 --- a/cmd/resolver/resolver.go +++ b/cmd/resolver/resolver.go @@ -4,6 +4,7 @@ package main import ( + "encoding/json" "fmt" "log" "math/rand" @@ -103,6 +104,30 @@ func (rsol *resolver) doCmdCachesSearch(q string) { printMessages(listMsg) } +func (rsol *resolver) doCmdEnv() { + var ( + resc = rsol.newRescachedClient() + + env *rescached.Environment + envJson []byte + err error + ) + + env, err = resc.Env() + if err != nil { + log.Printf("resolver: %s: %s", rsol.cmd, err) + return + } + + envJson, err = json.MarshalIndent(env, "", " ") + if err != nil { + log.Printf("resolver: %s: %s", rsol.cmd, err) + return + } + + fmt.Printf("%s\n", envJson) +} + func (rsol *resolver) doCmdQuery(args []string) { var ( maxAttempts = defAttempts diff --git a/environment.go b/environment.go index 43ce214..b8f2729 100644 --- a/environment.go +++ b/environment.go @@ -5,6 +5,7 @@ package rescached import ( "fmt" + "io" "strconv" "strings" @@ -214,13 +215,21 @@ func (env *Environment) loadResolvConf() (ok bool, err error) { return true, nil } -// -// write the options values back to file. -// -func (env *Environment) write(file string) (err error) { - in, err := ini.Open(file) - if err != nil { - return fmt.Errorf("write: %w", err) +func (env *Environment) save(file string) (in *ini.Ini, err error) { + var ( + logp = "save" + + hb *hostsBlock + ns string + ) + + if len(file) == 0 { + in = &ini.Ini{} + } else { + in, err = ini.Open(file) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } } in.Set(sectionNameRescached, "", keyFileResolvConf, env.FileResolvConf) @@ -229,14 +238,14 @@ func (env *Environment) write(file string) (err error) { in.UnsetAll(sectionNameRescached, "", keyHostsBlock) - for _, hb := range env.HostsBlocks { + for _, hb = range env.HostsBlocks { if hb.IsEnabled { in.Add(sectionNameRescached, "", keyHostsBlock, hb.URL) } } in.UnsetAll(sectionNameDNS, subNameServer, keyParent) - for _, ns := range env.NameServers { + for _, ns = range env.NameServers { in.Add(sectionNameDNS, subNameServer, keyParent, ns) } @@ -262,5 +271,41 @@ func (env *Environment) write(file string) (err error) { in.Set(sectionNameDNS, subNameServer, keyCachePruneThreshold, fmt.Sprintf("%s", env.ServerOptions.PruneThreshold)) - return in.Save(file) + return in, nil +} + +// Write the configuration as ini format to Writer w. +func (env *Environment) Write(w io.Writer) (err error) { + if w == nil { + return nil + } + + var ( + logp = "Environment.Write" + in *ini.Ini + ) + + in, err = env.save(env.fileConfig) + if err != nil { + return fmt.Errorf("%s: %w", logp, err) + } + + return in.Write(w) +} + +// +// write the options values back to file. +// +func (env *Environment) write(file string) (err error) { + var ( + in *ini.Ini + ) + in, err = env.save(file) + if err != nil { + return err + } + if len(file) > 0 { + return in.Save(file) + } + return nil } -- cgit v1.3