Browse Source

daemon: add host offlining by deleting the associated DNS records

cn 8 months ago
parent
commit
147071da9e
5 changed files with 48 additions and 6 deletions
  1. 6
    0
      .rubocop.yml
  2. 1
    0
      CHANGELOG.md
  3. 12
    5
      lib/dyndnsd.rb
  4. 1
    1
      lib/dyndnsd/helper.rb
  5. 28
    0
      spec/daemon_spec.rb

+ 6
- 0
.rubocop.yml View File

@@ -22,12 +22,18 @@ Metrics/BlockLength:
22 22
 Metrics/ClassLength:
23 23
   Enabled: false
24 24
 
25
+Metrics/CyclomaticComplexity:
26
+  Enabled: false
27
+
25 28
 Metrics/LineLength:
26 29
   Max: 200
27 30
 
28 31
 Metrics/MethodLength:
29 32
   Enabled: false
30 33
 
34
+Metrics/PerceivedComplexity:
35
+  Enabled: false
36
+
31 37
 Style/ConditionalAssignment:
32 38
   Enabled: false
33 39
 

+ 1
- 0
CHANGELOG.md View File

@@ -10,6 +10,7 @@ IMPROVEMENTS:
10 10
 - Update dependencies, mainly `rack` to new major version 2
11 11
 - Add Ruby 2.5 support
12 12
 - Add experimental [OpenTracing](http://opentracing.io/) support with [CNCF Jaeger](https://github.com/jaegertracing/jaeger)
13
+- Support host offlining by deleting the associated DNS records
13 14
 
14 15
 ## 1.6.1 (October 31, 2017)
15 16
 

+ 12
- 5
lib/dyndnsd.rb View File

@@ -141,7 +141,11 @@ module Dyndnsd
141 141
 
142 142
         hostnames.each do |hostname|
143 143
           # myips order is always deterministic
144
-          if Helper.changed?(hostname, myips, @db['hosts'])
144
+          if myips.empty? && @db['hosts'].include?(hostname)
145
+            @db['hosts'].delete(hostname)
146
+            changes << :good
147
+            Metriks.meter('requests.good').mark
148
+          elsif Helper.changed?(hostname, myips, @db['hosts'])
145 149
             @db['hosts'][hostname] = myips
146 150
             changes << :good
147 151
             Metriks.meter('requests.good').mark
@@ -180,10 +184,13 @@ module Dyndnsd
180 184
       forbidden_hostnames = hostnames - @users[user]['hosts']
181 185
       return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if forbidden_hostnames.any?
182 186
 
183
-      myips = extract_myips(env, params)
184
-
185
-      # require at least one IP to update
186
-      return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if myips.empty?
187
+      if params['offline'] == 'YES'
188
+        myips = []
189
+      else
190
+        myips = extract_myips(env, params)
191
+        # require at least one IP to update
192
+        return [422, {'X-DynDNS-Response' => 'host_forbidden'}, []] if myips.empty?
193
+      end
187 194
 
188 195
       Metriks.meter('requests.valid').mark
189 196
       Dyndnsd.logger.info "Request to update #{hostnames} to #{myips} for user #{user}"

+ 1
- 1
lib/dyndnsd/helper.rb View File

@@ -24,7 +24,7 @@ module Dyndnsd
24 24
 
25 25
     def self.changed?(hostname, myips, hosts)
26 26
       # myips order is always deterministic
27
-      (!hosts.include? hostname) || (hosts[hostname] != myips)
27
+      ((!hosts.include? hostname) || (hosts[hostname] != myips)) && !myips.empty?
28 28
     end
29 29
 
30 30
     def self.span(operation, &block)

+ 28
- 0
spec/daemon_spec.rb View File

@@ -167,6 +167,34 @@ describe Dyndnsd::Daemon do
167 167
     expect(last_response.body).to eq("nochg 2001:db8::1\ngood 2001:db8::1")
168 168
   end
169 169
 
170
+  it 'offlines a host' do
171
+    authorize 'test', 'secret'
172
+
173
+    get '/nic/update?hostname=foo.example.org&myip=1.2.3.4'
174
+    expect(last_response).to be_ok
175
+    expect(last_response.body).to eq('good 1.2.3.4')
176
+
177
+    get '/nic/update?hostname=foo.example.org&offline=YES'
178
+    expect(last_response).to be_ok
179
+    expect(last_response.body).to eq('good ')
180
+
181
+    get '/nic/update?hostname=foo.example.org&offline=YES'
182
+    expect(last_response).to be_ok
183
+    expect(last_response.body).to eq('nochg ')
184
+
185
+    get '/nic/update?hostname=foo.example.org&myip=1.2.3.4'
186
+    expect(last_response).to be_ok
187
+    expect(last_response.body).to eq('good 1.2.3.4')
188
+
189
+    get '/nic/update?hostname=foo.example.org&myip=1.2.3.4&offline=YES'
190
+    expect(last_response).to be_ok
191
+    expect(last_response.body).to eq('good ')
192
+
193
+    get '/nic/update?hostname=foo.example.org&myip=1.2.3.4&offline=YES'
194
+    expect(last_response).to be_ok
195
+    expect(last_response.body).to eq('nochg ')
196
+  end
197
+
170 198
   it 'uses clients remote IP address if myip not specified' do
171 199
     authorize 'test', 'secret'
172 200
     get '/nic/update?hostname=foo.example.org'