From e4581728e5c6fd9287e2e60aa908b89cbf6feeaf Mon Sep 17 00:00:00 2001 From: Shulhan Date: Sat, 14 May 2022 00:22:27 +0700 Subject: cmd/resolver: implement command to create and delete zone file The command to create new zone file has the following signature: zone.d create While command to delete zone file has the following signature: zone.d delete --- _doc/resolver.adoc | 11 ++++++ _sys/usr/share/man/man1/resolver.1.gz | Bin 2906 -> 2973 bytes client.go | 62 ++++++++++++++++++++++++++++++++++ cmd/resolver/main.go | 16 +++++++++ cmd/resolver/resolver.go | 44 ++++++++++++++++++++++++ httpd.go | 41 +++++++++++----------- 6 files changed, 155 insertions(+), 19 deletions(-) diff --git a/_doc/resolver.adoc b/_doc/resolver.adoc index 3885315..b67a0e0 100644 --- a/_doc/resolver.adoc +++ b/_doc/resolver.adoc @@ -202,6 +202,17 @@ Delete record from hosts file "name" by domain name. -- +=== MANAGING ZONE.D + +zone.d create :: ++ +Create new zone file inside the zone.d directory. + +zone.d delete :: ++ +Delete zone file inside the zone.d directory. + + == EXIT STATUS Upon exit and success +resolver+ will return 0, or 1 otherwise. diff --git a/_sys/usr/share/man/man1/resolver.1.gz b/_sys/usr/share/man/man1/resolver.1.gz index 5a6d304..90dbf93 100644 Binary files a/_sys/usr/share/man/man1/resolver.1.gz and b/_sys/usr/share/man/man1/resolver.1.gz differ diff --git a/client.go b/client.go index 49f6a12..bfec2fa 100644 --- a/client.go +++ b/client.go @@ -411,3 +411,65 @@ func (cl *Client) HostsdRecordDelete(hostsName, domain string) (record *dns.Reso return record, nil } + +// ZonedCreate create new zone file. +func (cl *Client) ZonedCreate(name string) (zone *dns.Zone, err error) { + var ( + logp = "ZonedCreate" + res = libhttp.EndpointResponse{ + Data: &zone, + } + params = url.Values{} + + resb []byte + ) + + params.Set(paramNameName, name) + + _, resb, err = cl.PostForm(apiZoned, nil, params) + 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 zone, nil +} + +// ZonedDelete delete zone file by name. +func (cl *Client) ZonedDelete(name string) (zone *dns.Zone, err error) { + var ( + logp = "ZonedDelete" + res = libhttp.EndpointResponse{ + Data: &zone, + } + params = url.Values{} + + httpRes *http.Response + resb []byte + ) + + params.Set(paramNameName, name) + + httpRes, resb, err = cl.Delete(apiZoned, nil, params) + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } + if httpRes.StatusCode != http.StatusOK { + return nil, fmt.Errorf("%s: %s", logp, httpRes.Status) + } + + 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 zone, nil +} diff --git a/cmd/resolver/main.go b/cmd/resolver/main.go index 7126651..62af801 100644 --- a/cmd/resolver/main.go +++ b/cmd/resolver/main.go @@ -20,6 +20,7 @@ const ( cmdEnv = "env" cmdHostsd = "hosts.d" cmdQuery = "query" + cmdZoned = "zone.d" subCmdAdd = "add" subCmdCreate = "create" @@ -85,6 +86,10 @@ func main() { rsol.doCmdQuery(args) + case cmdZoned: + args = args[1:] + rsol.doCmdZoned(args) + default: log.Printf("resolver: unknown command: %s", rsol.cmd) os.Exit(2) @@ -230,6 +235,17 @@ hosts.d rr delete Delete record from hosts file "name" by domain name. +=== MANAGING ZONE.D + +zone.d create + + Create new zone file inside the zone.d directory. + +zone.d delete + + Delete zone file inside the zone.d directory. + + == Examples === QUERY diff --git a/cmd/resolver/resolver.go b/cmd/resolver/resolver.go index 792f8d9..75287db 100644 --- a/cmd/resolver/resolver.go +++ b/cmd/resolver/resolver.go @@ -468,6 +468,50 @@ func (rsol *resolver) doCmdQuery(args []string) { } } +func (rsol *resolver) doCmdZoned(args []string) { + if len(args) == 0 { + log.Fatalf("resolver: %s: missing argument", rsol.cmd) + } + + var ( + subCmd = strings.ToLower(args[0]) + + resc *rescached.Client + err error + ) + + switch subCmd { + case subCmdCreate: + args = args[1:] + if len(args) == 0 { + log.Fatalf("resolver: %s %s: missing parameter name", rsol.cmd, subCmd) + } + + resc = rsol.newRescachedClient() + _, err = resc.ZonedCreate(args[0]) + if err != nil { + log.Fatalf("resolver: %s", err) + } + fmt.Println("OK") + + case subCmdDelete: + args = args[1:] + if len(args) == 0 { + log.Fatalf("resolver: %s %s: missing parameter name", rsol.cmd, subCmd) + } + + resc = rsol.newRescachedClient() + _, err = resc.ZonedDelete(args[0]) + if err != nil { + log.Fatalf("resolver: %s", err) + } + fmt.Println("OK") + + default: + log.Fatalf("resolver: %s: unknown sub command: %s", rsol.cmd, subCmd) + } +} + // initSystemResolver read the system resolv.conf to create fallback DNS // resolver. func (rsol *resolver) initSystemResolver() (err error) { diff --git a/httpd.go b/httpd.go index f62e228..f84865b 100644 --- a/httpd.go +++ b/httpd.go @@ -39,8 +39,8 @@ const ( apiHostsd = "/api/hosts.d" apiHostsdRR = "/api/hosts.d/rr" - apiZone = "/api/zone.d" - apiZoneRRType = "/api/zone.d/:name/rr/:type" + apiZoned = "/api/zone.d" + apiZonedRRType = "/api/zone.d/:name/rr/:type" ) func (srv *Server) httpdInit() (err error) { @@ -220,41 +220,42 @@ func (srv *Server) httpdRegisterEndpoints() (err error) { } err = srv.httpd.RegisterEndpoint(&libhttp.Endpoint{ - Method: libhttp.RequestMethodPut, - Path: apiZone, - RequestType: libhttp.RequestTypeNone, + Method: libhttp.RequestMethodPost, + Path: apiZoned, + RequestType: libhttp.RequestTypeForm, ResponseType: libhttp.ResponseTypeJSON, - Call: srv.apiZoneCreate, + Call: srv.apiZonedCreate, }) if err != nil { return err } err = srv.httpd.RegisterEndpoint(&libhttp.Endpoint{ Method: libhttp.RequestMethodDelete, - Path: apiZone, + Path: apiZoned, RequestType: libhttp.RequestTypeNone, ResponseType: libhttp.ResponseTypeJSON, - Call: srv.apiZoneDelete, + Call: srv.apiZonedDelete, }) if err != nil { return err } + err = srv.httpd.RegisterEndpoint(&libhttp.Endpoint{ Method: libhttp.RequestMethodPost, - Path: apiZoneRRType, + Path: apiZonedRRType, RequestType: libhttp.RequestTypeJSON, ResponseType: libhttp.ResponseTypeJSON, - Call: srv.apiZoneRRCreate, + Call: srv.apiZonedRRCreate, }) if err != nil { return err } err = srv.httpd.RegisterEndpoint(&libhttp.Endpoint{ Method: libhttp.RequestMethodDelete, - Path: apiZoneRRType, + Path: apiZonedRRType, RequestType: libhttp.RequestTypeJSON, ResponseType: libhttp.ResponseTypeJSON, - Call: srv.apiZoneRRDelete, + Call: srv.apiZonedRRDelete, }) if err != nil { return err @@ -957,7 +958,7 @@ func (srv *Server) apiHostsdRecordDelete(epr *libhttp.EndpointRequest) (resbody return json.Marshal(&res) } -func (srv *Server) apiZoneCreate(epr *libhttp.EndpointRequest) (resbody []byte, err error) { +func (srv *Server) apiZonedCreate(epr *libhttp.EndpointRequest) (resb []byte, err error) { var ( res = libhttp.EndpointResponse{} zoneName = epr.HttpRequest.Form.Get(paramNameName) @@ -999,10 +1000,11 @@ func (srv *Server) apiZoneCreate(epr *libhttp.EndpointRequest) (resbody []byte, res.Code = http.StatusOK res.Data = zone - return json.Marshal(&res) + resb, err = json.Marshal(&res) + return resb, err } -func (srv *Server) apiZoneDelete(epr *libhttp.EndpointRequest) (resbody []byte, err error) { +func (srv *Server) apiZonedDelete(epr *libhttp.EndpointRequest) (resb []byte, err error) { var ( res = libhttp.EndpointResponse{} zoneName = epr.HttpRequest.Form.Get(paramNameName) @@ -1042,12 +1044,13 @@ func (srv *Server) apiZoneDelete(epr *libhttp.EndpointRequest) (resbody []byte, res.Code = http.StatusOK res.Message = zoneName + " has been deleted" + res.Data = zone return json.Marshal(&res) } -// apiZoneRRCreate create new RR for the zone file. -func (srv *Server) apiZoneRRCreate(epr *libhttp.EndpointRequest) (resbody []byte, err error) { +// apiZonedRRCreate create new RR for the zone file. +func (srv *Server) apiZonedRRCreate(epr *libhttp.EndpointRequest) (resb []byte, err error) { var ( res = libhttp.EndpointResponse{} zoneFileName = epr.HttpRequest.Form.Get(paramNameName) @@ -1146,8 +1149,8 @@ func (srv *Server) apiZoneRRCreate(epr *libhttp.EndpointRequest) (resbody []byte return json.Marshal(&res) } -// apiZoneRRDelete delete RR from the zone file. -func (srv *Server) apiZoneRRDelete(epr *libhttp.EndpointRequest) (resbody []byte, err error) { +// apiZonedRRDelete delete RR from the zone file. +func (srv *Server) apiZonedRRDelete(epr *libhttp.EndpointRequest) (resbody []byte, err error) { var ( res = libhttp.EndpointResponse{} zoneFileName = epr.HttpRequest.Form.Get(paramNameName) -- cgit v1.3