From 32af34bc485a395ec8d0a0a5a59e0fc4a64d8742 Mon Sep 17 00:00:00 2001 From: Terje Kvernes Date: Thu, 29 Feb 2024 13:03:17 +0100 Subject: [PATCH] Make `host remove` a bit safer to use. (#211) ## The problem... It was much too easy to do `host remove foo -f` and have it bite in the worst possible way. ## The solution? In this PR, `-force` is no longer a catch-all for making `host remove`, well, remove the host. If the host has cnames, ptrs, mx, srvs or ipadresses across multiple vlans, the user needs to declare a desire to override each of these explicitly via the new option `-override`. ## Supported input Accepted overrides are `cname`, `ipadress`, `mx`, `srv`, `ptr`, `naptr`. Invalid overrides offered as parameters to `-override` are errors and the command will report on the unexpected input and stop before executing anything. The choice to have these as textual inputs is intended with the explicit goal of making their use require more than tab-completing an option. ## Example usage `host remove foo -force -override cname,ipaddress,mx`. This would allow deletion / removal of a host with cnames, ipadresses across different vlans, and mx set. However, any ptr or srv RRs will still cause the deletion to cancel. ## Example warning from `host remove` ``` WARNING: : bar.example.org requires force and cnames as overrides for deletion: 1 cnames, override with 'cname' - fubar.example.org multiple ipaddresses on the same VLAN. Must use 'force'." ``` ## Notes: 1. `-force` alone works on multiple ipadresses from the same VLAN. 2. `-override` requires the presence of `-force`. The documentation states this both from expanded inline help and `host remove -h`. --------- Co-authored-by: pederhan --- ci/testsuite | 47 +- ci/testsuite-result.json | 3472 ++++++++++++++++++++- mreg_cli/commands/host_submodules/core.py | 91 +- mreg_cli/utilities/host.py | 5 +- mreg_cli/utilities/network.py | 20 + 5 files changed, 3513 insertions(+), 122 deletions(-) diff --git a/ci/testsuite b/ci/testsuite index edbb8e61..5643c58c 100644 --- a/ci/testsuite +++ b/ci/testsuite @@ -199,7 +199,6 @@ dhcp assoc foo aa:bb:cc:dd:ee:ff # should fail, the host has two IPs of differen host aaaa_remove foo 2001:db9::5 host aaaa_add foo 2001:db8::5 -f dhcp assoc foo aa:bb:cc:dd:ee:ff # should work, the host now has two IPs of different types on the same VLAN. - host remove foo -f network remove 10.0.0.0/24 -f network remove 2001:db8::/64 -f @@ -234,6 +233,7 @@ host a_show baz host aaaa_add bar 2001:db8::/64 # must force host aaaa_add bar 2001:db8::11 -f host aaaa_add bar 2001:db8::12 -macaddress 11:22:33:44:55:67 -f +host remove bar # should fail, because it has multiple addresses, must force host aaaa_show bar host aaaa_change -old 2001:db8::11 -new 2001:db8::13 bar host aaaa_change -old 2001:db8::12 -new 2001:db8::14 bar # has mac addr, should keep it assigned to the new ip @@ -242,6 +242,7 @@ host aaaa_move -ip 2001:db8::14 -fromhost bar -tohost baz host a_show baz # CNAME host cname_add bar fubar +host remove bar # should fail, because it has a cname record, must force and override with 'cname' host cname_show bar host cname_remove bar fubar # HINFO @@ -255,6 +256,7 @@ host loc_remove baz # MX host mx_add baz 10 mail.example.org host mx_show baz +host remove baz # Should fail, because it has an MX record, must force and override with 'mx' host mx_remove baz 10 mail.example.org # NAPTR host naptr_add -name baz -preference 16384 -order 3 -flag u -service "SIP" -regex "[abc]+" -replacement "wonk" @@ -293,6 +295,49 @@ host remove *.example.org host remove bar -f host remove baz -f host remove clover + +# Test handling of overrides +# MX +host add foo -ip 10.0.0.10 -contact "foo@example.org" +host mx_add foo 10 mail.example.org +host remove foo # Should fail, because it has an MX record, must force and override with 'mx' +host remove foo -force -override mx + +# PTR +host add foo -ip 10.0.0.10 -contact "foo@example.org" +host ptr_add 10.0.0.11 foo.example.org +host remove foo # Should fail, because it has a PTR record, must force and override with 'ptr' +host remove foo -force -override ptr + +# NAPTR +host add foo -ip 10.0.0.10 -contact "foo@example.org" +host naptr_add -name foo -preference 16384 -order 3 -flag u -service "SIP" -regex "[abc]+" -replacement "wonk" +host remove foo +host remove foo -force -override naptr + +# SRV +host add foo -ip 10.0.0.10 -contact "foo@example.org" +host srv_add -name "_sip._tcp.example.org" -priority 10 -weight 5 -port 3456 -host foo.example.org +host remove foo # Should fail, because it has an SRV record, must force and override with 'srv' +host remove foo -force -override srv + +# CNAME +host add foo -ip 10.0.0.10 -contact "foo@example.org" +host cname_add foo fubar +host remove foo # Should fail, because it has a CNAME record, must force and override with 'cname' +host remove foo -force -override cname + +# All of the above +host add foo -ip 10.0.0.10 -contact "foo@example.org" +host mx_add foo 10 mail.example.org +host ptr_add 10.0.0.11 foo.example.org +host naptr_add -name foo -preference 16384 -order 3 -flag u -service "SIP" -regex "[abc]+" -replacement "wonk" +host srv_add -name "_sip._tcp.example.org" -priority 10 -weight 5 -port 3456 -host foo.example.org +host cname_add foo fubar +host remove foo # Should fail, because it has multiple records, must force and override with everything. +host remove foo -force -override mx,ptr,naptr,srv,cname + + network remove 10.0.0.0/24 -f network remove 2001:db8::/64 -f diff --git a/ci/testsuite-result.json b/ci/testsuite-result.json index feb5eddd..1a6d7f98 100644 --- a/ci/testsuite-result.json +++ b/ci/testsuite-result.json @@ -10423,10 +10423,10 @@ "warning": [], "error": [], "output": [ - "2024-01-23 11:30:00 [system-signals]: Txt create: txt = 'v=spf1 -all'", - "2024-01-23 11:30:00 [test]: Host create: name = 'somehost.example.org', contact = 'support@example.org'", - "2024-01-23 11:30:00 [test]: Ipaddress create: ipaddress = '10.0.1.4'", - "2024-01-23 11:30:00 [test]: Host update: contact: support@example.org -> new-support@example.org" + "2024-02-28 12:23:39 [system-signals]: Txt create: txt = 'v=spf1 -all'", + "2024-02-28 12:23:39 [test]: Host create: name = 'somehost.example.org', contact = 'support@example.org'", + "2024-02-28 12:23:39 [test]: Ipaddress create: ipaddress = '10.0.1.4'", + "2024-02-28 12:23:39 [test]: Host update: contact: support@example.org -> new-support@example.org" ], "api_requests": [ { @@ -10440,7 +10440,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:00.296065+01:00", + "timestamp": "2024-02-28T12:23:39.579919+01:00", "user": "system-signals", "resource": "host", "name": "somehost.example.org", @@ -10452,7 +10452,7 @@ } }, { - "timestamp": "2024-01-23T11:30:00.300907+01:00", + "timestamp": "2024-02-28T12:23:39.584355+01:00", "user": "test", "resource": "host", "name": "somehost.example.org", @@ -10462,7 +10462,7 @@ "data": "{\"name\": \"somehost.example.org\", \"contact\": \"support@example.org\"}" }, { - "timestamp": "2024-01-23T11:30:00.306110+01:00", + "timestamp": "2024-02-28T12:23:39.589814+01:00", "user": "test", "resource": "host", "name": "somehost.example.org", @@ -10472,14 +10472,14 @@ "data": "{\"ipaddress\": \"10.0.1.4\"}" }, { - "timestamp": "2024-01-23T11:30:00.516985+01:00", + "timestamp": "2024-02-28T12:23:39.815065+01:00", "user": "test", "resource": "host", "name": "somehost.example.org", "model_id": 4, "model": "Host", "action": "update", - "data": "{\"current_data\": {\"id\": 4, \"ipaddresses\": [{\"id\": 3, \"macaddress\": \"\", \"created_at\": \"2024-01-23T11:30:00.305587+01:00\", \"updated_at\": \"2024-01-23T11:30:00.305596+01:00\", \"ipaddress\": \"10.0.1.4\", \"host\": 4}], \"cnames\": [], \"mxs\": [], \"txts\": [{\"id\": 4, \"created_at\": \"2024-01-23T11:30:00.295418+01:00\", \"updated_at\": \"2024-01-23T11:30:00.295424+01:00\", \"txt\": \"v=spf1 -all\", \"host\": 4}], \"ptr_overrides\": [], \"hinfo\": null, \"loc\": null, \"bacnetid\": null, \"created_at\": \"2024-01-23T11:30:00.293959+01:00\", \"updated_at\": \"2024-01-23T11:30:00.293967+01:00\", \"name\": \"somehost.example.org\", \"contact\": \"support@example.org\", \"ttl\": null, \"comment\": \"\", \"zone\": 1}, \"update\": {\"contact\": \"new-support@example.org\"}}" + "data": "{\"current_data\": {\"id\": 4, \"ipaddresses\": [{\"id\": 3, \"macaddress\": \"\", \"created_at\": \"2024-02-28T12:23:39.589266+01:00\", \"updated_at\": \"2024-02-28T12:23:39.589274+01:00\", \"ipaddress\": \"10.0.1.4\", \"host\": 4}], \"cnames\": [], \"mxs\": [], \"txts\": [{\"id\": 4, \"created_at\": \"2024-02-28T12:23:39.579426+01:00\", \"updated_at\": \"2024-02-28T12:23:39.579436+01:00\", \"txt\": \"v=spf1 -all\", \"host\": 4}], \"ptr_overrides\": [], \"hinfo\": null, \"loc\": null, \"bacnetid\": null, \"created_at\": \"2024-02-28T12:23:39.577802+01:00\", \"updated_at\": \"2024-02-28T12:23:39.577810+01:00\", \"name\": \"somehost.example.org\", \"contact\": \"support@example.org\", \"ttl\": null, \"comment\": \"\", \"zone\": 1}, \"update\": {\"contact\": \"new-support@example.org\"}}" } ] } @@ -10495,7 +10495,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:00.296065+01:00", + "timestamp": "2024-02-28T12:23:39.579919+01:00", "user": "system-signals", "resource": "host", "name": "somehost.example.org", @@ -10507,7 +10507,7 @@ } }, { - "timestamp": "2024-01-23T11:30:00.300907+01:00", + "timestamp": "2024-02-28T12:23:39.584355+01:00", "user": "test", "resource": "host", "name": "somehost.example.org", @@ -10517,7 +10517,7 @@ "data": "{\"name\": \"somehost.example.org\", \"contact\": \"support@example.org\"}" }, { - "timestamp": "2024-01-23T11:30:00.306110+01:00", + "timestamp": "2024-02-28T12:23:39.589814+01:00", "user": "test", "resource": "host", "name": "somehost.example.org", @@ -10527,14 +10527,14 @@ "data": "{\"ipaddress\": \"10.0.1.4\"}" }, { - "timestamp": "2024-01-23T11:30:00.516985+01:00", + "timestamp": "2024-02-28T12:23:39.815065+01:00", "user": "test", "resource": "host", "name": "somehost.example.org", "model_id": 4, "model": "Host", "action": "update", - "data": "{\"current_data\": {\"id\": 4, \"ipaddresses\": [{\"id\": 3, \"macaddress\": \"\", \"created_at\": \"2024-01-23T11:30:00.305587+01:00\", \"updated_at\": \"2024-01-23T11:30:00.305596+01:00\", \"ipaddress\": \"10.0.1.4\", \"host\": 4}], \"cnames\": [], \"mxs\": [], \"txts\": [{\"id\": 4, \"created_at\": \"2024-01-23T11:30:00.295418+01:00\", \"updated_at\": \"2024-01-23T11:30:00.295424+01:00\", \"txt\": \"v=spf1 -all\", \"host\": 4}], \"ptr_overrides\": [], \"hinfo\": null, \"loc\": null, \"bacnetid\": null, \"created_at\": \"2024-01-23T11:30:00.293959+01:00\", \"updated_at\": \"2024-01-23T11:30:00.293967+01:00\", \"name\": \"somehost.example.org\", \"contact\": \"support@example.org\", \"ttl\": null, \"comment\": \"\", \"zone\": 1}, \"update\": {\"contact\": \"new-support@example.org\"}}" + "data": "{\"current_data\": {\"id\": 4, \"ipaddresses\": [{\"id\": 3, \"macaddress\": \"\", \"created_at\": \"2024-02-28T12:23:39.589266+01:00\", \"updated_at\": \"2024-02-28T12:23:39.589274+01:00\", \"ipaddress\": \"10.0.1.4\", \"host\": 4}], \"cnames\": [], \"mxs\": [], \"txts\": [{\"id\": 4, \"created_at\": \"2024-02-28T12:23:39.579426+01:00\", \"updated_at\": \"2024-02-28T12:23:39.579436+01:00\", \"txt\": \"v=spf1 -all\", \"host\": 4}], \"ptr_overrides\": [], \"hinfo\": null, \"loc\": null, \"bacnetid\": null, \"created_at\": \"2024-02-28T12:23:39.577802+01:00\", \"updated_at\": \"2024-02-28T12:23:39.577810+01:00\", \"name\": \"somehost.example.org\", \"contact\": \"support@example.org\", \"ttl\": null, \"comment\": \"\", \"zone\": 1}, \"update\": {\"contact\": \"new-support@example.org\"}}" } ] } @@ -12284,11 +12284,11 @@ "warning": [], "error": [], "output": [ - "2024-01-23 11:30:01 [test]: HostGroup create: name = 'mygroup', description = 'This describes the group'", - "2024-01-23 11:30:01 [test]: Host add: testhost1.example.org", - "2024-01-23 11:30:01 [test]: Host add: testhost2.example.org", - "2024-01-23 11:30:01 [test]: Group add: myself", - "2024-01-23 11:30:01 [test]: Host remove: testhost2.example.org" + "2024-02-28 12:23:41 [test]: HostGroup create: name = 'mygroup', description = 'This describes the group'", + "2024-02-28 12:23:41 [test]: Host add: testhost1.example.org", + "2024-02-28 12:23:41 [test]: Host add: testhost2.example.org", + "2024-02-28 12:23:41 [test]: Group add: myself", + "2024-02-28 12:23:41 [test]: Host remove: testhost2.example.org" ], "api_requests": [ { @@ -12302,7 +12302,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:01.624291+01:00", + "timestamp": "2024-02-28T12:23:41.057394+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12312,7 +12312,7 @@ "data": "{\"name\": \"mygroup\", \"description\": \"This describes the group\"}" }, { - "timestamp": "2024-01-23T11:30:01.804995+01:00", + "timestamp": "2024-02-28T12:23:41.248132+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12325,7 +12325,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.854552+01:00", + "timestamp": "2024-02-28T12:23:41.298688+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12338,7 +12338,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.891110+01:00", + "timestamp": "2024-02-28T12:23:41.333278+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12351,7 +12351,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.941636+01:00", + "timestamp": "2024-02-28T12:23:41.382245+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12377,7 +12377,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:01.624291+01:00", + "timestamp": "2024-02-28T12:23:41.057394+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12387,7 +12387,7 @@ "data": "{\"name\": \"mygroup\", \"description\": \"This describes the group\"}" }, { - "timestamp": "2024-01-23T11:30:01.804995+01:00", + "timestamp": "2024-02-28T12:23:41.248132+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12400,7 +12400,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.854552+01:00", + "timestamp": "2024-02-28T12:23:41.298688+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12413,7 +12413,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.891110+01:00", + "timestamp": "2024-02-28T12:23:41.333278+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12426,7 +12426,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.941636+01:00", + "timestamp": "2024-02-28T12:23:41.382245+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12784,15 +12784,15 @@ "warning": [], "error": [], "output": [ - "2024-01-23 11:30:01 [test]: HostGroup create: name = 'mygroup', description = 'This describes the group'", - "2024-01-23 11:30:01 [test]: Host add: testhost1.example.org", - "2024-01-23 11:30:01 [test]: Host add: testhost2.example.org", - "2024-01-23 11:30:01 [test]: Group add: myself", - "2024-01-23 11:30:01 [test]: Host remove: testhost2.example.org", - "2024-01-23 11:30:02 [test]: HostGroup add: yourgroup", - "2024-01-23 11:30:02 [test]: HostGroup remove: yourgroup", - "2024-01-23 11:30:02 [test]: Group add: anotherowner", - "2024-01-23 11:30:02 [test]: Group remove: myself" + "2024-02-28 12:23:41 [test]: HostGroup create: name = 'mygroup', description = 'This describes the group'", + "2024-02-28 12:23:41 [test]: Host add: testhost1.example.org", + "2024-02-28 12:23:41 [test]: Host add: testhost2.example.org", + "2024-02-28 12:23:41 [test]: Group add: myself", + "2024-02-28 12:23:41 [test]: Host remove: testhost2.example.org", + "2024-02-28 12:23:41 [test]: HostGroup add: yourgroup", + "2024-02-28 12:23:41 [test]: HostGroup remove: yourgroup", + "2024-02-28 12:23:41 [test]: Group add: anotherowner", + "2024-02-28 12:23:41 [test]: Group remove: myself" ], "api_requests": [ { @@ -12806,7 +12806,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:01.624291+01:00", + "timestamp": "2024-02-28T12:23:41.057394+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12816,7 +12816,7 @@ "data": "{\"name\": \"mygroup\", \"description\": \"This describes the group\"}" }, { - "timestamp": "2024-01-23T11:30:01.804995+01:00", + "timestamp": "2024-02-28T12:23:41.248132+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12829,7 +12829,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.854552+01:00", + "timestamp": "2024-02-28T12:23:41.298688+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12842,7 +12842,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.891110+01:00", + "timestamp": "2024-02-28T12:23:41.333278+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12855,7 +12855,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.941636+01:00", + "timestamp": "2024-02-28T12:23:41.382245+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12868,7 +12868,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.110333+01:00", + "timestamp": "2024-02-28T12:23:41.521894+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12881,7 +12881,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.160208+01:00", + "timestamp": "2024-02-28T12:23:41.573469+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12894,7 +12894,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.194806+01:00", + "timestamp": "2024-02-28T12:23:41.605128+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12907,7 +12907,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.226563+01:00", + "timestamp": "2024-02-28T12:23:41.638332+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12933,7 +12933,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:01.624291+01:00", + "timestamp": "2024-02-28T12:23:41.057394+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12943,7 +12943,7 @@ "data": "{\"name\": \"mygroup\", \"description\": \"This describes the group\"}" }, { - "timestamp": "2024-01-23T11:30:01.804995+01:00", + "timestamp": "2024-02-28T12:23:41.248132+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12956,7 +12956,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.854552+01:00", + "timestamp": "2024-02-28T12:23:41.298688+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12969,7 +12969,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.891110+01:00", + "timestamp": "2024-02-28T12:23:41.333278+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12982,7 +12982,7 @@ } }, { - "timestamp": "2024-01-23T11:30:01.941636+01:00", + "timestamp": "2024-02-28T12:23:41.382245+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -12995,7 +12995,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.110333+01:00", + "timestamp": "2024-02-28T12:23:41.521894+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -13008,7 +13008,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.160208+01:00", + "timestamp": "2024-02-28T12:23:41.573469+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -13021,7 +13021,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.194806+01:00", + "timestamp": "2024-02-28T12:23:41.605128+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -13034,7 +13034,7 @@ } }, { - "timestamp": "2024-01-23T11:30:02.226563+01:00", + "timestamp": "2024-02-28T12:23:41.638332+01:00", "user": "test", "resource": "group", "name": "mygroup", @@ -14288,7 +14288,7 @@ "error": [], "output": [ "Name: fruit", - "Created: 2024-01-23", + "Created: 2024-02-28", "Description: 5 a day", "Atom members:", " apple", @@ -14392,8 +14392,8 @@ "warning": [], "error": [], "output": [ - "2024-01-23 11:30:02 [test]: HostPolicyAtom create: description = 'Here's the description', name = 'apple'", - "2024-01-23 11:30:03 [test]: HostPolicyAtom add to: hostpolicy_role fruit" + "2024-02-28 12:23:42 [test]: HostPolicyAtom create: description = 'Here's the description', name = 'apple'", + "2024-02-28 12:23:42 [test]: HostPolicyAtom add to: hostpolicy_role fruit" ], "api_requests": [ { @@ -14407,7 +14407,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:02.976539+01:00", + "timestamp": "2024-02-28T12:23:42.361063+01:00", "user": "test", "resource": "hostpolicy_atom", "name": "apple", @@ -14430,7 +14430,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:02.976539+01:00", + "timestamp": "2024-02-28T12:23:42.361063+01:00", "user": "test", "resource": "hostpolicy_atom", "name": "apple", @@ -14453,7 +14453,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:03.192643+01:00", + "timestamp": "2024-02-28T12:23:42.572360+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -14592,9 +14592,9 @@ "warning": [], "error": [], "output": [ - "2024-01-23 11:30:02 [test]: HostPolicyAtom create: description = 'Here's the description', name = 'apple'", - "2024-01-23 11:30:03 [test]: HostPolicyAtom add to: hostpolicy_role fruit", - "2024-01-23 11:30:03 [test]: HostPolicyAtom remove from: hostpolicy_role fruit" + "2024-02-28 12:23:42 [test]: HostPolicyAtom create: description = 'Here's the description', name = 'apple'", + "2024-02-28 12:23:42 [test]: HostPolicyAtom add to: hostpolicy_role fruit", + "2024-02-28 12:23:42 [test]: HostPolicyAtom remove from: hostpolicy_role fruit" ], "api_requests": [ { @@ -14608,7 +14608,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:02.976539+01:00", + "timestamp": "2024-02-28T12:23:42.361063+01:00", "user": "test", "resource": "hostpolicy_atom", "name": "apple", @@ -14631,7 +14631,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:02.976539+01:00", + "timestamp": "2024-02-28T12:23:42.361063+01:00", "user": "test", "resource": "hostpolicy_atom", "name": "apple", @@ -14654,7 +14654,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:03.192643+01:00", + "timestamp": "2024-02-28T12:23:42.572360+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -14667,7 +14667,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.402442+01:00", + "timestamp": "2024-02-28T12:23:42.813592+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15516,13 +15516,13 @@ "warning": [], "error": [], "output": [ - "2024-01-23 11:30:03 [test]: HostPolicyRole create: description = '5 a day', name = 'fruit', labels = '[]'", - "2024-01-23 11:30:03 [test]: HostPolicyAtom add: apple", - "2024-01-23 11:30:03 [test]: HostPolicyAtom add: orange", - "2024-01-23 11:30:03 [test]: HostPolicyAtom remove: apple", - "2024-01-23 11:30:03 [test]: Host add: foo.example.org", - "2024-01-23 11:30:03 [test]: Host remove: foo.example.org", - "2024-01-23 11:30:03 [test]: HostPolicyAtom remove: tangerine" + "2024-02-28 12:23:42 [test]: HostPolicyRole create: description = '5 a day', name = 'fruit', labels = '[]'", + "2024-02-28 12:23:42 [test]: HostPolicyAtom add: apple", + "2024-02-28 12:23:42 [test]: HostPolicyAtom add: orange", + "2024-02-28 12:23:42 [test]: HostPolicyAtom remove: apple", + "2024-02-28 12:23:43 [test]: Host add: foo.example.org", + "2024-02-28 12:23:43 [test]: Host remove: foo.example.org", + "2024-02-28 12:23:43 [test]: HostPolicyAtom remove: tangerine" ], "api_requests": [ { @@ -15536,7 +15536,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:03.077421+01:00", + "timestamp": "2024-02-28T12:23:42.465128+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15546,7 +15546,7 @@ "data": "{\"description\": \"5 a day\", \"name\": \"fruit\", \"labels\": []}" }, { - "timestamp": "2024-01-23T11:30:03.192643+01:00", + "timestamp": "2024-02-28T12:23:42.572360+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15559,7 +15559,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.242962+01:00", + "timestamp": "2024-02-28T12:23:42.618867+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15572,7 +15572,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.402442+01:00", + "timestamp": "2024-02-28T12:23:42.813592+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15585,7 +15585,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.685499+01:00", + "timestamp": "2024-02-28T12:23:43.177707+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15598,7 +15598,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.783484+01:00", + "timestamp": "2024-02-28T12:23:43.375246+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15611,7 +15611,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.834689+01:00", + "timestamp": "2024-02-28T12:23:43.429510+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15637,7 +15637,7 @@ "previous": null, "results": [ { - "timestamp": "2024-01-23T11:30:03.077421+01:00", + "timestamp": "2024-02-28T12:23:42.465128+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15647,7 +15647,7 @@ "data": "{\"description\": \"5 a day\", \"name\": \"fruit\", \"labels\": []}" }, { - "timestamp": "2024-01-23T11:30:03.192643+01:00", + "timestamp": "2024-02-28T12:23:42.572360+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15660,7 +15660,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.242962+01:00", + "timestamp": "2024-02-28T12:23:42.618867+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15673,7 +15673,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.402442+01:00", + "timestamp": "2024-02-28T12:23:42.813592+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15686,7 +15686,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.685499+01:00", + "timestamp": "2024-02-28T12:23:43.177707+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15699,7 +15699,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.783484+01:00", + "timestamp": "2024-02-28T12:23:43.375246+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -15712,7 +15712,7 @@ } }, { - "timestamp": "2024-01-23T11:30:03.834689+01:00", + "timestamp": "2024-02-28T12:23:43.429510+01:00", "user": "test", "resource": "hostpolicy_role", "name": "fruit", @@ -17627,6 +17627,40 @@ "zone": 1 } }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.5", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "foo", + "vlan": 1234, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/2001%3Adb8%3A%3A5", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "2001:db8::/64", + "description": "foo_ipv6", + "vlan": 1234, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, { "method": "GET", "url": "/api/v1/naptrs/?host=13", @@ -19820,6 +19854,160 @@ ], "time": null }, + { + "command": "host remove bar", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove bar # should fail, because it has multiple addresses, must force", + "ok": [], + "warning": [ + "WARNING: : bar.example.org requires force and override for deletion:\n multiple ipaddresses on the same VLAN. Must use 'force'." + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/bar.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.14", + "host": 14 + }, + { + "macaddress": "11:22:33:44:55:66", + "ipaddress": "10.0.0.15", + "host": 14 + }, + { + "macaddress": "", + "ipaddress": "2001:db8::11", + "host": 14 + }, + { + "macaddress": "11:22:33:44:55:67", + "ipaddress": "2001:db8::12", + "host": 14 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 14 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "bar.example.org", + "contact": "me@example.org", + "ttl": null, + "comment": "This is the comment", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.14", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.15", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/2001%3Adb8%3A%3A11", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "2001:db8::/64", + "description": "dolor sit amet", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/2001%3Adb8%3A%3A12", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "2001:db8::/64", + "description": "dolor sit amet", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=14", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=bar.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + } + ], + "time": null + }, { "command": "host aaaa_show bar", "command_filter": null, @@ -20461,18 +20649,16 @@ "time": null }, { - "command": "host cname_show bar", + "command": "host remove bar", "command_filter": null, "command_filter_negate": false, - "command_issued": "host cname_show bar", - "ok": [ - "OK: : showed cname aliases for bar.example.org" + "command_issued": "host remove bar # should fail, because it has a cname record, must force and override with 'cname'", + "ok": [], + "warning": [ + "WARNING: : bar.example.org requires force and override for deletion:\n 1 cnames, override with 'cname'\n - fubar.example.org\n multiple ipaddresses on the same VLAN. Must use 'force'." ], - "warning": [], "error": [], - "output": [ - "Cname: fubar.example.org -> bar.example.org" - ], + "output": [], "api_requests": [ { "method": "GET", @@ -20517,12 +20703,131 @@ "comment": "This is the comment", "zone": 1 } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.14", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.15", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=14", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=bar.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } } ], "time": null }, { - "command": "host cname_remove bar fubar", + "command": "host cname_show bar", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host cname_show bar", + "ok": [ + "OK: : showed cname aliases for bar.example.org" + ], + "warning": [], + "error": [], + "output": [ + "Cname: fubar.example.org -> bar.example.org" + ], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/bar.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.14", + "host": 14 + }, + { + "macaddress": "11:22:33:44:55:66", + "ipaddress": "10.0.0.15", + "host": 14 + } + ], + "cnames": [ + { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 14 + } + ], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 14 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "bar.example.org", + "contact": "me@example.org", + "ttl": null, + "comment": "This is the comment", + "zone": 1 + } + } + ], + "time": null + }, + { + "command": "host cname_remove bar fubar", "command_filter": null, "command_filter_negate": false, "command_issued": "host cname_remove bar fubar", @@ -21102,6 +21407,122 @@ ], "time": null }, + { + "command": "host remove baz", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove baz # Should fail, because it has an MX record, must force and override with 'mx'", + "ok": [], + "warning": [ + "WARNING: : baz.example.org requires force and override for deletion:\n multiple ipaddresses on the same VLAN. Must use 'force'.\n 1 MX records, override with 'mx'\n - mail.example.org (priority: 10)" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/baz.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "11:22:33:aa:bb:cc", + "ipaddress": "10.0.0.10", + "host": 15 + }, + { + "macaddress": "11:22:33:44:55:67", + "ipaddress": "2001:db8::14", + "host": 15 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 15 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 15 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "baz.example.org", + "contact": "", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/2001%3Adb8%3A%3A14", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "2001:db8::/64", + "description": "dolor sit amet", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=15", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=baz.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + } + ], + "time": null + }, { "command": "host mx_remove baz 10 mail.example.org", "command_filter": null, @@ -23216,6 +23637,40 @@ "zone": 1 } }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.14", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.15", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, { "method": "GET", "url": "/api/v1/naptrs/?host=14", @@ -23298,6 +23753,40 @@ "zone": 1 } }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/2001%3Adb8%3A%3A14", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "2001:db8::/64", + "description": "dolor sit amet", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, { "method": "GET", "url": "/api/v1/naptrs/?host=15", @@ -23402,6 +23891,2789 @@ ], "time": null }, + { + "command": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "ok": [ + "OK: : created host foo.example.org with IP 10.0.0.10" + ], + "warning": [ + "WARNING: : host not found: foo.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?ipaddresses__ipaddress=10.0.0.10", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/hosts/", + "data": { + "name": "foo.example.org", + "contact": "foo@example.org", + "comment": null, + "ipaddress": "10.0.0.10" + }, + "status": 201 + } + ], + "time": null + }, + { + "command": "host mx_add foo 10 mail.example.org", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host mx_add foo 10 mail.example.org", + "ok": [ + "OK: : Added MX record to foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 18 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 18 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "POST", + "url": "/api/v1/mxs/", + "data": { + "host": 18, + "priority": 10, + "mx": "mail.example.org" + }, + "status": 201, + "response": { + "priority": 10, + "mx": "mail.example.org", + "host": 18 + } + } + ], + "time": null + }, + { + "command": "host remove foo", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo # Should fail, because it has an MX record, must force and override with 'mx'", + "ok": [], + "warning": [ + "WARNING: : foo.example.org requires force and override for deletion:\n 1 MX records, override with 'mx'\n - mail.example.org (priority: 10)" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 18 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 18 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 18 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=18", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + } + ], + "time": null + }, + { + "command": "host remove foo -force -override mx", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo -force -override mx", + "ok": [ + "OK: : removed foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 18 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 18 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 18 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=18", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "DELETE", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 204 + } + ], + "time": null + }, + { + "command": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "ok": [ + "OK: : created host foo.example.org with IP 10.0.0.10" + ], + "warning": [ + "WARNING: : host not found: foo.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?ipaddresses__ipaddress=10.0.0.10", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/hosts/", + "data": { + "name": "foo.example.org", + "contact": "foo@example.org", + "comment": null, + "ipaddress": "10.0.0.10" + }, + "status": 201 + } + ], + "time": null + }, + { + "command": "host ptr_add 10.0.0.11 foo.example.org", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host ptr_add 10.0.0.11 foo.example.org", + "ok": [ + "OK: : Added PTR record 10.0.0.11 to foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.11", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 19 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 19 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/ptroverrides/?ipaddress=10.0.0.11", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.11", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/ptroverrides/", + "data": { + "host": 19, + "ipaddress": "10.0.0.11" + }, + "status": 201, + "response": { + "ipaddress": "10.0.0.11", + "host": 19 + } + } + ], + "time": null + }, + { + "command": "host remove foo", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo # Should fail, because it has a PTR record, must force and override with 'ptr'", + "ok": [], + "warning": [ + "WARNING: : foo.example.org requires force and override for deletion:\n 1 PTR records, override with 'ptr'\n - 10.0.0.11" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 19 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 19 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 19 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=19", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + } + ], + "time": null + }, + { + "command": "host remove foo -force -override ptr", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo -force -override ptr", + "ok": [ + "OK: : deleted PTR record 10.0.0.11 when removing foo.example.org", + "OK: : removed foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 19 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 19 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 19 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=19", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "DELETE", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 204 + } + ], + "time": null + }, + { + "command": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "ok": [ + "OK: : created host foo.example.org with IP 10.0.0.10" + ], + "warning": [ + "WARNING: : host not found: foo.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?ipaddresses__ipaddress=10.0.0.10", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/hosts/", + "data": { + "name": "foo.example.org", + "contact": "foo@example.org", + "comment": null, + "ipaddress": "10.0.0.10" + }, + "status": 201 + } + ], + "time": null + }, + { + "command": "host naptr_add -name foo -preference 16384 -order 3 -flag u -service \"SIP\" -regex \"[abc]+\" -replacement \"wonk\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host naptr_add -name foo -preference 16384 -order 3 -flag u -service \"SIP\" -regex \"[abc]+\" -replacement \"wonk\"", + "ok": [ + "OK: : created NAPTR record for foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 20 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 20 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "POST", + "url": "/api/v1/naptrs/", + "data": { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "SIP", + "regex": "[abc]+", + "replacement": "wonk", + "host": 20 + }, + "status": 201, + "response": { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "SIP", + "regex": "[abc]+", + "replacement": "wonk", + "host": 20 + } + } + ], + "time": null + }, + { + "command": "host remove foo", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo", + "ok": [], + "warning": [ + "WARNING: : foo.example.org requires force and override for deletion:\n 1 NAPTR records, override with 'naptr'\n - wonk" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 20 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 20 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=20", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "sip", + "regex": "[abc]+", + "replacement": "wonk", + "host": 20 + } + ] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + } + ], + "time": null + }, + { + "command": "host remove foo -force -override naptr", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo -force -override naptr", + "ok": [ + "OK: : deleted NAPTR record wonk when removing foo.example.org", + "OK: : removed foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 20 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 20 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=20", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "sip", + "regex": "[abc]+", + "replacement": "wonk", + "host": 20 + } + ] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "DELETE", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 204 + } + ], + "time": null + }, + { + "command": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "ok": [ + "OK: : created host foo.example.org with IP 10.0.0.10" + ], + "warning": [ + "WARNING: : host not found: foo.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?ipaddresses__ipaddress=10.0.0.10", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/hosts/", + "data": { + "name": "foo.example.org", + "contact": "foo@example.org", + "comment": null, + "ipaddress": "10.0.0.10" + }, + "status": 201 + } + ], + "time": null + }, + { + "command": "host srv_add -name \"_sip._tcp.example.org\" -priority 10 -weight 5 -port 3456 -host foo.example.org", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host srv_add -name \"_sip._tcp.example.org\" -priority 10 -weight 5 -port 3456 -host foo.example.org", + "ok": [ + "OK: : Added SRV record _sip._tcp.example.org with target foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/_sip._tcp.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 21 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 21 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "POST", + "url": "/api/v1/srvs/", + "data": { + "name": "_sip._tcp.example.org", + "priority": "10", + "weight": "5", + "port": "3456", + "host": 21, + "ttl": null + }, + "status": 201, + "response": { + "name": "_sip._tcp.example.org", + "priority": 10, + "weight": 5, + "port": 3456, + "ttl": null, + "zone": 1, + "host": 21 + } + } + ], + "time": null + }, + { + "command": "host remove foo", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo # Should fail, because it has an SRV record, must force and override with 'srv'", + "ok": [], + "warning": [ + "WARNING: : foo.example.org requires force and override for deletion:\n 1 SRV records, override with 'srv'\n - _sip._tcp.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 21 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 21 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=21", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "name": "_sip._tcp.example.org", + "priority": 10, + "weight": 5, + "port": 3456, + "ttl": null, + "zone": 1, + "host": 21 + } + ] + } + } + ], + "time": null + }, + { + "command": "host remove foo -force -override srv", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo -force -override srv", + "ok": [ + "OK: : deleted SRV record _sip._tcp.example.org when removing foo.example.org", + "OK: : removed foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 21 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 21 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=21", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "name": "_sip._tcp.example.org", + "priority": 10, + "weight": 5, + "port": 3456, + "ttl": null, + "zone": 1, + "host": 21 + } + ] + } + }, + { + "method": "DELETE", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 204 + } + ], + "time": null + }, + { + "command": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "ok": [ + "OK: : created host foo.example.org with IP 10.0.0.10" + ], + "warning": [ + "WARNING: : host not found: foo.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?ipaddresses__ipaddress=10.0.0.10", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/hosts/", + "data": { + "name": "foo.example.org", + "contact": "foo@example.org", + "comment": null, + "ipaddress": "10.0.0.10" + }, + "status": 201 + } + ], + "time": null + }, + { + "command": "host cname_add foo fubar", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host cname_add foo fubar", + "ok": [ + "OK: : Added cname alias fubar.example.org for foo.example.org" + ], + "warning": [ + "WARNING: : host not found: 'fubar.example.org'" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 22 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 22 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/fubar.example.org", + "data": {}, + "status": 404, + "response": { + "detail": "Not found." + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?cnames__name=fubar.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=fubar.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/fubar.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "POST", + "url": "/api/v1/cnames/", + "data": { + "host": 22, + "name": "fubar.example.org" + }, + "status": 201, + "response": { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 22 + } + } + ], + "time": null + }, + { + "command": "host remove foo", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo # Should fail, because it has a CNAME record, must force and override with 'cname'", + "ok": [], + "warning": [ + "WARNING: : foo.example.org requires force and override for deletion:\n 1 cnames, override with 'cname'\n - fubar.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 22 + } + ], + "cnames": [ + { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 22 + } + ], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 22 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=22", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + } + ], + "time": null + }, + { + "command": "host remove foo -force -override cname", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo -force -override cname", + "ok": [ + "OK: : removed foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 22 + } + ], + "cnames": [ + { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 22 + } + ], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 22 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=22", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "DELETE", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 204 + } + ], + "time": null + }, + { + "command": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host add foo -ip 10.0.0.10 -contact \"foo@example.org\"", + "ok": [ + "OK: : created host foo.example.org with IP 10.0.0.10" + ], + "warning": [ + "WARNING: : host not found: foo.example.org" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?ipaddresses__ipaddress=10.0.0.10", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.10", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/hosts/", + "data": { + "name": "foo.example.org", + "contact": "foo@example.org", + "comment": null, + "ipaddress": "10.0.0.10" + }, + "status": 201 + } + ], + "time": null + }, + { + "command": "host mx_add foo 10 mail.example.org", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host mx_add foo 10 mail.example.org", + "ok": [ + "OK: : Added MX record to foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [], + "mxs": [], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "POST", + "url": "/api/v1/mxs/", + "data": { + "host": 23, + "priority": 10, + "mx": "mail.example.org" + }, + "status": 201, + "response": { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + } + ], + "time": null + }, + { + "command": "host ptr_add 10.0.0.11 foo.example.org", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host ptr_add 10.0.0.11 foo.example.org", + "ok": [ + "OK: : Added PTR record 10.0.0.11 to foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.11", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/ptroverrides/?ipaddress=10.0.0.11", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/networks/ip/10.0.0.11", + "data": {}, + "status": 200, + "response": { + "excluded_ranges": [], + "network": "10.0.0.0/24", + "description": "lorem ipsum", + "vlan": null, + "dns_delegated": false, + "category": "", + "location": "", + "frozen": false, + "reserved": 3 + } + }, + { + "method": "GET", + "url": "/api/v1/networks/10.0.0.0/24/reserved_list", + "data": {}, + "status": 200, + "response": [ + "10.0.0.0", + "10.0.0.1", + "10.0.0.2", + "10.0.0.3", + "10.0.0.255" + ] + }, + { + "method": "POST", + "url": "/api/v1/ptroverrides/", + "data": { + "host": 23, + "ipaddress": "10.0.0.11" + }, + "status": 201, + "response": { + "ipaddress": "10.0.0.11", + "host": 23 + } + } + ], + "time": null + }, + { + "command": "host naptr_add -name foo -preference 16384 -order 3 -flag u -service \"SIP\" -regex \"[abc]+\" -replacement \"wonk\"", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host naptr_add -name foo -preference 16384 -order 3 -flag u -service \"SIP\" -regex \"[abc]+\" -replacement \"wonk\"", + "ok": [ + "OK: : created NAPTR record for foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 23 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "POST", + "url": "/api/v1/naptrs/", + "data": { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "SIP", + "regex": "[abc]+", + "replacement": "wonk", + "host": 23 + }, + "status": 201, + "response": { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "SIP", + "regex": "[abc]+", + "replacement": "wonk", + "host": 23 + } + } + ], + "time": null + }, + { + "command": "host srv_add -name \"_sip._tcp.example.org\" -priority 10 -weight 5 -port 3456 -host foo.example.org", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host srv_add -name \"_sip._tcp.example.org\" -priority 10 -weight 5 -port 3456 -host foo.example.org", + "ok": [ + "OK: : Added SRV record _sip._tcp.example.org with target foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/_sip._tcp.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 23 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/foo.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "POST", + "url": "/api/v1/srvs/", + "data": { + "name": "_sip._tcp.example.org", + "priority": "10", + "weight": "5", + "port": "3456", + "host": 23, + "ttl": null + }, + "status": 201, + "response": { + "name": "_sip._tcp.example.org", + "priority": 10, + "weight": 5, + "port": 3456, + "ttl": null, + "zone": 1, + "host": 23 + } + } + ], + "time": null + }, + { + "command": "host cname_add foo fubar", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host cname_add foo fubar", + "ok": [ + "OK: : Added cname alias fubar.example.org for foo.example.org" + ], + "warning": [ + "WARNING: : host not found: 'fubar.example.org'" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 23 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/fubar.example.org", + "data": {}, + "status": 404, + "response": { + "detail": "Not found." + } + }, + { + "method": "GET", + "url": "/api/v1/hosts/?cnames__name=fubar.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/cnames/?name=fubar.example.org", + "data": {}, + "status": 200, + "response": { + "count": 0, + "next": null, + "previous": null, + "results": [] + } + }, + { + "method": "GET", + "url": "/api/v1/zones/forward/hostname/fubar.example.org", + "data": {}, + "status": 200, + "response": { + "zone": { + "nameservers": [ + { + "name": "ns2.example.org", + "ttl": null + } + ], + "updated": true, + "primary_ns": "ns2.example.org", + "email": "hostperson@example.org", + "refresh": 360, + "retry": 1800, + "expire": 2400, + "soa_ttl": 1800, + "default_ttl": 300, + "name": "example.org" + } + } + }, + { + "method": "POST", + "url": "/api/v1/cnames/", + "data": { + "host": 23, + "name": "fubar.example.org" + }, + "status": 201, + "response": { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 23 + } + } + ], + "time": null + }, + { + "command": "host remove foo", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo # Should fail, because it has multiple records, must force and override with everything.", + "ok": [], + "warning": [ + "WARNING: : foo.example.org requires force and override for deletion:\n 1 cnames, override with 'cname'\n - fubar.example.org\n 1 MX records, override with 'mx'\n - mail.example.org (priority: 10)\n 1 NAPTR records, override with 'naptr'\n - wonk\n 1 SRV records, override with 'srv'\n - _sip._tcp.example.org\n 1 PTR records, override with 'ptr'\n - 10.0.0.11" + ], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [ + { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 23 + } + ], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 23 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=23", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "sip", + "regex": "[abc]+", + "replacement": "wonk", + "host": 23 + } + ] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "name": "_sip._tcp.example.org", + "priority": 10, + "weight": 5, + "port": 3456, + "ttl": null, + "zone": 1, + "host": 23 + } + ] + } + } + ], + "time": null + }, + { + "command": "host remove foo -force -override mx,ptr,naptr,srv,cname", + "command_filter": null, + "command_filter_negate": false, + "command_issued": "host remove foo -force -override mx,ptr,naptr,srv,cname", + "ok": [ + "OK: : deleted NAPTR record wonk when removing foo.example.org", + "OK: : deleted SRV record _sip._tcp.example.org when removing foo.example.org", + "OK: : deleted PTR record 10.0.0.11 when removing foo.example.org", + "OK: : removed foo.example.org" + ], + "warning": [], + "error": [], + "output": [], + "api_requests": [ + { + "method": "GET", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 200, + "response": { + "ipaddresses": [ + { + "macaddress": "", + "ipaddress": "10.0.0.10", + "host": 23 + } + ], + "cnames": [ + { + "name": "fubar.example.org", + "ttl": null, + "zone": 1, + "host": 23 + } + ], + "mxs": [ + { + "priority": 10, + "mx": "mail.example.org", + "host": 23 + } + ], + "txts": [ + { + "txt": "v=spf1 -all", + "host": 23 + } + ], + "ptr_overrides": [ + { + "ipaddress": "10.0.0.11", + "host": 23 + } + ], + "hinfo": null, + "loc": null, + "bacnetid": null, + "name": "foo.example.org", + "contact": "foo@example.org", + "ttl": null, + "comment": "", + "zone": 1 + } + }, + { + "method": "GET", + "url": "/api/v1/naptrs/?host=23", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "preference": 16384, + "order": 3, + "flag": "u", + "service": "sip", + "regex": "[abc]+", + "replacement": "wonk", + "host": 23 + } + ] + } + }, + { + "method": "GET", + "url": "/api/v1/srvs/?host__name=foo.example.org", + "data": {}, + "status": 200, + "response": { + "count": 1, + "next": null, + "previous": null, + "results": [ + { + "name": "_sip._tcp.example.org", + "priority": 10, + "weight": 5, + "port": 3456, + "ttl": null, + "zone": 1, + "host": 23 + } + ] + } + }, + { + "method": "DELETE", + "url": "/api/v1/hosts/foo.example.org", + "data": {}, + "status": 204 + } + ], + "time": null + }, { "command": "network remove 10.0.0.0/24 -f", "command_filter": null, @@ -23797,7 +27069,7 @@ "error": [], "output": [ "Name: myrole", - "Created: 2024-01-23", + "Created: 2024-02-28", "Description: This is the description", "Atom members:", " None", diff --git a/mreg_cli/commands/host_submodules/core.py b/mreg_cli/commands/host_submodules/core.py index 14d4d9ee..184b241a 100644 --- a/mreg_cli/commands/host_submodules/core.py +++ b/mreg_cli/commands/host_submodules/core.py @@ -12,7 +12,7 @@ """ import argparse -from typing import Dict, Union +from typing import Dict, List, Optional, Union from mreg_cli.commands.host import registry as command_registry from mreg_cli.exceptions import HostNotFoundWarning @@ -30,6 +30,7 @@ host_info_by_name, host_info_by_name_or_ip, ) +from mreg_cli.utilities.network import get_network_by_ip, ips_are_in_same_vlan from mreg_cli.utilities.output import output_host_info, output_ip_info from mreg_cli.utilities.shared import convert_wildcard_to_regex, format_mac from mreg_cli.utilities.validators import is_valid_email, is_valid_ip, is_valid_mac @@ -140,34 +141,81 @@ def add(args: argparse.Namespace) -> None: metavar="NAME/IP", ), Flag("-force", action="store_true", description="Enable force."), + Flag( + "-override", + short_desc="Comma separated override list, requires -force.", + description=( + "Comma separated overrides for forced removal. Requires -force." + "Accepted overrides: 'cname', 'ipadress', 'mx', 'srv', 'ptr', 'naptr'." + "Example usage: '-override cname,ipaddress,mx'" + ), + metavar="OVERRIDE", + ), ], ) def remove(args: argparse.Namespace) -> None: """Remove host. - :param args: argparse.Namespace (name, force) + :param args: argparse.Namespace (name, force, override) """ # Get host info or raise exception info = host_info_by_name_or_ip(args.name) + overrides: List[str] = args.override.split(",") if args.override else [] + + accepted_overrides = ["cname", "ipaddress", "mx", "srv", "ptr", "naptr"] + for override in overrides: + if override not in accepted_overrides: + cli_warning(f"Invalid override: {override}. Accepted overrides: {accepted_overrides}") - warn_msg = "" + def forced(override_required: Optional[str] = None) -> bool: + # If we require an override, check if it's in the list of provided overrides. + if override_required: + return override_required in overrides + + # We didn't require an override, so we only need to check for force. + if args.force: + return True + + # And the fallback is "no". + return False + + warnings: List[str] = [] # Require force if host has any cnames. - cnames = info["cnames"] - if len(cnames): - if not args.force: - warn_msg += "{} cnames. ".format(len(cnames)) + if info["cnames"] and not args.force: + warnings.append(f" {len(info['cnames'])} cnames, override with 'cname'") + for cname in info["cnames"]: + warnings.append(f" - {cname['name']}") + + # Require force if host has multiple A/AAAA records and they are not in the same VLAN. + if len(info["ipaddresses"]) > 1: + same_vlan = ips_are_in_same_vlan([ip["ipaddress"] for ip in info["ipaddresses"]]) + + if same_vlan and not forced(): + warnings.append(" multiple ipaddresses on the same VLAN. Must use 'force'.") + elif not same_vlan and not forced("ipaddresses"): + warnings.append( + " {} ipaddresses on distinct VLANs, override with 'ipadress'".format( + len(info["ipaddresses"]) + ) + ) + for ip in info["ipaddresses"]: + vlan = get_network_by_ip(ip["ipaddress"]).get("vlan") + warnings.append(f" - {ip['ipaddress']} (vlan: {vlan})") - # Require force if host has multiple A/AAAA records - if len(info["ipaddresses"]) > 1 and not args.force: - warn_msg += "{} ipaddresses. ".format(len(info["ipaddresses"])) + if info["mxs"] and not forced("mx"): + warnings.append(f" {len(info['mxs'])} MX records, override with 'mx'") + for mx in info["mxs"]: + warnings.append(f" - {mx['mx']} (priority: {mx['priority']})") # Require force if host has any NAPTR records. Delete the NAPTR records if # force path = "/api/v1/naptrs/" naptrs = get_list(path, params={"host": info["id"]}) if len(naptrs) > 0: - if not args.force: - warn_msg += "{} NAPTR records. ".format(len(naptrs)) + if not forced("naptr"): + warnings.append(" {} NAPTR records, override with 'naptr'".format(len(naptrs))) + for naptr in naptrs: + warnings.append(f" - {naptr['replacement']}") else: for naptr in naptrs: cli_info( @@ -181,8 +229,10 @@ def remove(args: argparse.Namespace) -> None: path = "/api/v1/srvs/" srvs = get_list(path, params={"host__name": info["name"]}) if len(srvs) > 0: - if not args.force: - warn_msg += "{} SRV records. ".format(len(srvs)) + if not forced("srv"): + warnings.append(f" {len(srvs)} SRV records, override with 'srv'") + for srv in srvs: + warnings.append(f" - {srv['name']}") else: for srv in srvs: cli_info( @@ -194,8 +244,10 @@ def remove(args: argparse.Namespace) -> None: # Require force if host has any PTR records. Delete the PTR records if force if len(info["ptr_overrides"]) > 0: - if not args.force: - warn_msg += "{} PTR records. ".format(len(info["ptr_overrides"])) + if not forced("ptr"): + warnings.append(f" {len(info['ptr_overrides'])} PTR records, override with 'ptr'") + for ptr in info["ptr_overrides"]: + warnings.append(f" - {ptr['ipaddress']}") else: for ptr in info["ptr_overrides"]: cli_info( @@ -211,8 +263,11 @@ def remove(args: argparse.Namespace) -> None: info["ipaddress"] = info["ipaddresses"][0]["ipaddress"] # Warn user and raise exception if any force requirements was found - if warn_msg: - cli_warning("{} has: {}Must force".format(info["name"], warn_msg)) + if warnings: + warn_msg = "\n".join(warnings) + cli_warning( + "{} requires force and override for deletion:\n{}".format(info["name"], warn_msg) + ) # Delete host path = f"/api/v1/hosts/{info['name']}" diff --git a/mreg_cli/utilities/host.py b/mreg_cli/utilities/host.py index 58900b26..84323c2e 100644 --- a/mreg_cli/utilities/host.py +++ b/mreg_cli/utilities/host.py @@ -16,6 +16,7 @@ get_network_by_ip, get_network_first_unused_ip, get_network_reserved_ips, + ips_are_in_same_vlan, ) from mreg_cli.utilities.shared import format_mac from mreg_cli.utilities.validators import ( @@ -100,9 +101,7 @@ def get_unique_ip_by_name_or_ip(arg: str) -> Dict[str, Any]: + " Please specify a specific address to use instead." ) - net1 = get_network_by_ip(ip1) - net2 = get_network_by_ip(ip2) - if net1["vlan"] and net2["vlan"] and net1["vlan"] == net2["vlan"]: + if ips_are_in_same_vlan([ip1, ip2]): # In the case of the host having IPv4 and IPv6 on the same VLAN, we return the IPv4 # address. This works "okay" for now as its the only DUID type they can share. if is_valid_ipv4(ip1): diff --git a/mreg_cli/utilities/network.py b/mreg_cli/utilities/network.py index 58def557..8ae47b9d 100644 --- a/mreg_cli/utilities/network.py +++ b/mreg_cli/utilities/network.py @@ -39,6 +39,26 @@ def ipsort(ips: Iterable[Any]) -> List[Any]: return sorted(ips, key=lambda i: ipaddress.ip_address(i)) +def ips_are_in_same_vlan(ips: List[str]) -> bool: + """Return True if all ips are in the same vlan.""" + # IPs must be in a network, and that network must have a vlan for this to work. + last_vlan = "" + for ip in ips: + network = get_network_by_ip(ip) + if not network: + return False + + if "vlan" not in network: + return False + + if last_vlan and network["vlan"] != last_vlan: + return False + + last_vlan = network["vlan"] + + return True + + def get_network_by_ip(ip: str) -> Dict[str, Any]: """Return a network associated with given IP.""" if is_valid_ip(ip):