diff --git a/.rubocop.yml b/.rubocop.yml index 9d4e4ab..e1113b9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -22,12 +22,18 @@ Metrics/BlockLength: Metrics/ClassLength: Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false + Metrics/LineLength: Max: 200 Metrics/MethodLength: Enabled: false +Metrics/PerceivedComplexity: + Enabled: false + Style/ConditionalAssignment: Enabled: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a2d6f4..4d49114 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ IMPROVEMENTS: - Update dependencies, mainly `rack` to new major version 2 - Add Ruby 2.5 support - Add experimental [OpenTracing](http://opentracing.io/) support with [CNCF Jaeger](https://github.com/jaegertracing/jaeger) +- Support host offlining by deleting the associated DNS records ## 1.6.1 (October 31, 2017) diff --git a/lib/dyndnsd.rb b/lib/dyndnsd.rb index 2b73e75..6d6eb41 100755 --- a/lib/dyndnsd.rb +++ b/lib/dyndnsd.rb @@ -141,7 +141,11 @@ module Dyndnsd hostnames.each do |hostname| # myips order is always deterministic - if Helper.changed?(hostname, myips, @db['hosts']) + if myips.empty? && @db['hosts'].include?(hostname) + @db['hosts'].delete(hostname) + changes << :good + Metriks.meter('requests.good').mark + elsif Helper.changed?(hostname, myips, @db['hosts']) @db['hosts'][hostname] = myips changes << :good Metriks.meter('requests.good').mark @@ -180,10 +184,13 @@ module Dyndnsd forbidden_hostnames = hostnames - @users[user]['hosts'] return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if forbidden_hostnames.any? - myips = extract_myips(env, params) - - # require at least one IP to update - return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if myips.empty? + if params['offline'] == 'YES' + myips = [] + else + myips = extract_myips(env, params) + # require at least one IP to update + return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if myips.empty? + end Metriks.meter('requests.valid').mark Dyndnsd.logger.info "Request to update #{hostnames} to #{myips} for user #{user}" diff --git a/lib/dyndnsd/helper.rb b/lib/dyndnsd/helper.rb index 9eb738d..c9ba0a0 100644 --- a/lib/dyndnsd/helper.rb +++ b/lib/dyndnsd/helper.rb @@ -24,7 +24,7 @@ module Dyndnsd def self.changed?(hostname, myips, hosts) # myips order is always deterministic - (!hosts.include? hostname) || (hosts[hostname] != myips) + ((!hosts.include? hostname) || (hosts[hostname] != myips)) && !myips.empty? end def self.span(operation, &block) diff --git a/spec/daemon_spec.rb b/spec/daemon_spec.rb index f287099..fb3ff5d 100644 --- a/spec/daemon_spec.rb +++ b/spec/daemon_spec.rb @@ -167,6 +167,34 @@ describe Dyndnsd::Daemon do expect(last_response.body).to eq("nochg 2001:db8::1\ngood 2001:db8::1") end + it 'offlines a host' do + authorize 'test', 'secret' + + get '/nic/update?hostname=foo.example.org&myip=1.2.3.4' + expect(last_response).to be_ok + expect(last_response.body).to eq('good 1.2.3.4') + + get '/nic/update?hostname=foo.example.org&offline=YES' + expect(last_response).to be_ok + expect(last_response.body).to eq('good ') + + get '/nic/update?hostname=foo.example.org&offline=YES' + expect(last_response).to be_ok + expect(last_response.body).to eq('nochg ') + + get '/nic/update?hostname=foo.example.org&myip=1.2.3.4' + expect(last_response).to be_ok + expect(last_response.body).to eq('good 1.2.3.4') + + get '/nic/update?hostname=foo.example.org&myip=1.2.3.4&offline=YES' + expect(last_response).to be_ok + expect(last_response.body).to eq('good ') + + get '/nic/update?hostname=foo.example.org&myip=1.2.3.4&offline=YES' + expect(last_response).to be_ok + expect(last_response.body).to eq('nochg ') + end + it 'uses clients remote IP address if myip not specified' do authorize 'test', 'secret' get '/nic/update?hostname=foo.example.org'