1
0
mirror of https://github.com/cmur2/dyndnsd.git synced 2025-08-08 08:33:56 +02:00

Compare commits

..

1 Commits

Author SHA1 Message Date
cn
3f150ad065 docs: add link to newer version 2020-07-28 17:33:27 +02:00
33 changed files with 76 additions and 577 deletions

View File

@@ -1,9 +0,0 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -1,26 +0,0 @@
---
name: cd
on:
push:
tags:
- 'v*.*.*'
jobs:
release-dockerimage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Extract dyndnsd version from tag name
run: |
echo "DYNDNSD_VERSION=${GITHUB_REF#refs/*/v}" >> $GITHUB_ENV
# https://github.com/marketplace/actions/build-and-push-docker-images
- name: Build and push Docker image for dyndnsd ${{ env.DYNDNSD_VERSION }}
uses: docker/build-push-action@v1
with:
username: cmur2
password: ${{ secrets.DOCKER_TOKEN }}
repository: cmur2/dyndnsd
path: docker
build_args: DYNDNSD_VERSION=${{ env.DYNDNSD_VERSION }}
tag_with_ref: true

View File

@@ -1,29 +0,0 @@
---
name: ci
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
schedule:
- cron: '35 4 * * 4' # weekly on thursday morning
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version:
- '3.0'
steps:
- uses: actions/checkout@v2
- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Lint and Test
run: |
bundle exec rake ci

View File

@@ -1,19 +0,0 @@
---
name: dockerhub
on:
schedule:
- cron: '7 4 * * 4' # weekly on thursday morning
workflow_dispatch:
jobs:
pull-released-dockerimages:
runs-on: ubuntu-latest
steps:
- name: Avoid stale tags by pulling
run: |
ALL_IMAGES="$(curl -s https://hub.docker.com/v2/repositories/cmur2/dyndnsd/tags?page_size=1000 | jq -r '.results[].name | "cmur2/dyndnsd:" + .' | grep -e 'cmur2/dyndnsd:v')"
for image in $ALL_IMAGES; do
echo "Pulling $image to avoid staleness..."
docker pull "$image"
done

View File

@@ -1,46 +0,0 @@
---
name: vulnscan
on:
schedule:
- cron: '7 4 * * 4' # weekly on thursday morning
workflow_dispatch:
jobs:
scan-released-dockerimages:
runs-on: ubuntu-latest
env:
TRIVY_LIGHT: 'true'
TRIVY_IGNORE_UNFIXED: 'true'
TRIVY_REMOVED_PKGS: 'true'
steps:
- name: Install Trivy
run: |
mkdir -p $GITHUB_WORKSPACE/bin
echo "$GITHUB_WORKSPACE/bin" >> "$GITHUB_PATH"
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/master/contrib/install.sh | sh -s -- -b $GITHUB_WORKSPACE/bin
- name: Download Trivy DB
run: |
trivy image --download-db-only
- name: Scan vulnerabilities using Trivy
env:
TRIVY_SKIP_DIRS: 'usr/lib/ruby/gems/2.7.0/gems/jaeger-client-0.10.0/crossdock,usr/lib/ruby/gems/2.7.0/gems/jaeger-client-1.0.0/crossdock,usr/lib/ruby/gems/2.7.0/gems/jaeger-client-1.1.0/crossdock'
run: |
trivy --version
# semver sorting as per https://stackoverflow.com/a/40391207/2148786
ALL_IMAGES="$(curl -s https://hub.docker.com/v2/repositories/cmur2/dyndnsd/tags?page_size=1000 | jq -r '.results[].name | "cmur2/dyndnsd:" + .' | grep -e 'cmur2/dyndnsd:v' | sed '/-/!{s/$/_/}' | sort -r -V | sed 's/_$//')"
EXIT_CODE=0
set -e
for major_version in $(seq 1 10); do
for image in $ALL_IMAGES; do
if [[ "$image" = cmur2/dyndnsd:v$major_version.* ]]; then
echo -e "\nScanning newest patch release $image of major v$major_version...\n"
if ! trivy image --skip-update --exit-code 1 "$image"; then
EXIT_CODE=1
fi
break
fi
done
done
exit "$EXIT_CODE"

View File

@@ -1,10 +1,5 @@
require:
- rubocop-rake
- rubocop-rspec
AllCops:
TargetRubyVersion: '3.0'
NewCops: enable
TargetRubyVersion: '2.3'
Layout/EmptyLineAfterGuardClause:
Enabled: false
@@ -90,9 +85,3 @@ Style/SymbolArray:
Style/TrailingCommaInArrayLiteral:
Enabled: false
RSpec/ExampleLength:
Max: 20
RSpec/MultipleExpectations:
Max: 20

12
.travis.yml Normal file
View File

@@ -0,0 +1,12 @@
---
os: linux
language: ruby
rvm:
- 2.7
- 2.6
- 2.5
- 2.4
- 2.3
script:
- bundle exec rake travis

View File

@@ -1,48 +1,5 @@
# Changelog
## 3.3.0 (January 18, 2021)
OTHER:
- update base of Docker image to Alpine 3.13
## 3.2.0 (January 14, 2021)
IMPROVEMENTS:
- Add Ruby 3.0 support
## 3.1.3 (December 20, 2020)
OTHER:
- fix Docker image release process in Github Actions CI, 3.1.2 was not released as a Docker image
## 3.1.2 (December 20, 2020)
OTHER:
- fixes vulnerabilities in Docker image by using updated Alpine base image
- start using Github Actions CI for tests and drop Travis CI
## 3.1.1 (October 3, 2020)
IMPROVEMENTS:
- Use webrick gem which contains fixes against [CVE-2020-25613](https://www.ruby-lang.org/en/news/2020/09/29/http-request-smuggling-cve-2020-25613/)
## 3.1.0 (August 19, 2020)
IMPROVEMENTS:
- Add officially maintained [Docker image for dyndnsd](https://hub.docker.com/r/cmur2/dyndnsd)
## 3.0.0 (July 29, 2020)
IMPROVEMENTS:
- Drop EOL Ruby 2.4 and lower support, now minimum version supported is Ruby 2.5
## 2.3.1 (July 27, 2020)
IMPROVEMENTS:

View File

@@ -1,9 +1,10 @@
# dyndnsd.rb
![ci](https://github.com/cmur2/dyndnsd/workflows/ci/badge.svg) [![Dependencies](https://badges.depfu.com/badges/4f25da8493f7a29f652ac892fbf9227b/overview.svg)](https://depfu.com/github/cmur2/dyndnsd)
[![Build Status](https://travis-ci.org/cmur2/dyndnsd.svg?branch=dyndnsd-2.x)](https://travis-ci.org/cmur2/dyndnsd) [![Dependencies](https://badges.depfu.com/badges/4f25da8493f7a29f652ac892fbf9227b/overview.svg)](https://depfu.com/github/cmur2/dyndnsd)
A small, lightweight and extensible DynDNS server written with Ruby and Rack.
**Note:** a newer version of dyndnsd.rb is available on [branch master](https://github.com/cmur2/dyndnsd), see also the [changelog](https://github.com/cmur2/dyndnsd/blob/master/CHANGELOG.md).
## Description
@@ -64,42 +65,7 @@ users:
Run dyndnsd.rb by:
```bash
dyndnsd /path/to/config.yml
```
### Docker image
There is an officially maintained [Docker image for dyndnsd](https://hub.docker.com/r/cmur2/dyndnsd) available at Dockerhub. The goal is to have a minimal secured image available (currently based on Alpine) that works well for the `zone_transfer_server` updater use case.
Users can make extensions by deriving from the official Docker image or building their own.
The Docker image consumes the same configuration file in YAML format as the gem, inside the container it needs to be mounted/available as `/etc/dyndnsd/config.yml`. the following YAML should be used as a base and extended with user's settings:
```yaml
host: "0.0.0.0"
port: 8080
# omit the logfile: option so logging to STDOUT will happen automatically
db: "/var/lib/dyndnsd/db.json"
# User's settings for updater and permissions follow here!
```
more ports might be needed depending on if DNS zone transfer is needed
Run the Docker image exposing the DynDNS-API on host port 8080 via:
```bash
docker run -d --name dyndnsd \
-p 8080:8080 \
-v /host/path/to/dyndnsd/config.yml:/etc/dyndnsd/config.yml \
-v /host/ptherpath/to/dyndnsd/datadir:/var/lib/dyndnsd \
cmur2/dyndnsd:vX.Y.Z
```
*Note*: You may need to expose more then just port 8080 e.g. if you use the `zone_transfer_server` which can be done by appending additional `-p 5353:5353` flags to the `docker run` command.
dyndnsd /path/to/config.yaml
## Using dyndnsd.rb with any nameserver via DNS zone transfers (AXFR)
@@ -222,11 +188,9 @@ If you want to provide an additional IPv6 address as myip6 parameter, the myip p
Use a webserver as a proxy to handle SSL and/or multiple listen addresses and ports. DynDNS.com provides HTTP on port 80 and 8245 and HTTPS on port 443.
### Startup
### Init scripts
There is a [Dockerfile](docs/Dockerfile) that can be used to build a Docker image for running dyndnsd.rb.
The [Debian 6 init.d script](docs/debian-6-init-dyndnsd) assumes that dyndnsd.rb is installed into the system ruby (no RVM support) and the config.yaml is at /opt/dyndnsd/config.yaml. Modify to your needs.
The [Debian 6 init.d script](init.d/debian-6-dyndnsd) assumes that dyndnsd.rb is installed into the system ruby (no RVM support) and the config.yaml is at /opt/dyndnsd/config.yaml. Modify to your needs.
### Monitoring

View File

@@ -9,36 +9,16 @@ RSpec::Core::RakeTask.new(:spec)
RuboCop::RakeTask.new
Bundler::Audit::Task.new
desc 'Should be run by developer once to prepare initial solargraph usage (fill caches etc.)'
task :'solargraph:init' do
sh 'solargraph download-core'
end
desc 'Run experimental solargraph type checker'
task :solargraph do
task :'solargraph:tc' do
sh 'solargraph typecheck'
end
namespace :solargraph do
desc 'Should be run by developer once to prepare initial solargraph usage (fill caches etc.)'
task :init do
sh 'solargraph download-core'
end
end
task default: [:rubocop, :spec, 'bundle:audit']
desc 'Run hadolint for Dockerfile linting'
task :hadolint do
sh 'docker run --rm -i hadolint/hadolint:v1.18.0 hadolint --ignore DL3018 - < docker/Dockerfile'
end
desc 'Run experimental steep type checker'
task :steep do
sh 'steep check'
end
namespace :steep do
desc 'Output coverage stats from steep'
task :stats do
sh 'steep stats --log-level=fatal | awk -F\',\' \'{ printf "%-50s %-9s %-12s %-14s %-10s\n", $2, $3, $4, $5, $7 }\''
end
end
task default: [:rubocop, :spec, 'bundle:audit', :solargraph, :steep]
desc 'Run all tasks desired for CI'
task ci: ['solargraph:init', :default, :hadolint]
task travis: [:default, :'solargraph:tc']

View File

@@ -1,11 +0,0 @@
# frozen_string_literal: true
target :lib do
signature 'sig'
check 'lib'
ignore 'lib/dyndnsd/updater/zone_transfer_server.rb'
library 'date'
library 'forwardable'
end

View File

@@ -1,15 +0,0 @@
FROM alpine:3.13
EXPOSE 5353 8080
ARG DYNDNSD_VERSION=3.0.0
RUN apk --no-cache add openssl ca-certificates && \
apk --no-cache add ruby ruby-etc ruby-io-console ruby-json ruby-webrick && \
apk --no-cache add --virtual .build-deps ruby-dev build-base tzdata && \
gem install --no-document dyndnsd -v ${DYNDNSD_VERSION} && \
# set timezone to Berlin
cp /usr/share/zoneinfo/Europe/Berlin /etc/localtime && \
apk del .build-deps
ENTRYPOINT ["dyndnsd", "/etc/dyndnsd/config.yml"]

View File

@@ -25,24 +25,20 @@ Gem::Specification.new do |s|
s.executables = ['dyndnsd']
s.extra_rdoc_files = Dir['README.md', 'CHANGELOG.md', 'LICENSE']
s.required_ruby_version = '>= 3.0'
s.required_ruby_version = '>= 2.3'
s.add_runtime_dependency 'async-dns', '~> 1.2.0'
s.add_runtime_dependency 'jaeger-client', '~> 1.1.0'
s.add_runtime_dependency 'jaeger-client', '~> 0.10.0'
s.add_runtime_dependency 'metriks'
s.add_runtime_dependency 'opentracing', '~> 0.5.0'
s.add_runtime_dependency 'rack', '~> 2.0'
s.add_runtime_dependency 'rack-tracer', '~> 0.9.0'
s.add_runtime_dependency 'webrick', '>= 1.6.1'
s.add_development_dependency 'bundler'
s.add_development_dependency 'bundler-audit', '~> 0.7.0'
s.add_development_dependency 'rack-test'
s.add_development_dependency 'rake'
s.add_development_dependency 'rspec'
s.add_development_dependency 'rubocop', '~> 1.7.0'
s.add_development_dependency 'rubocop-rake', '~> 0.5.1'
s.add_development_dependency 'rubocop-rspec', '~> 2.1.0'
s.add_development_dependency 'solargraph', '~> 0.40.0'
s.add_development_dependency 'steep', '~> 0.39.0'
s.add_development_dependency 'rubocop', '~> 0.81.0'
s.add_development_dependency 'solargraph'
end

0
docs/debian-6-init-dyndnsd → init.d/debian-6-dyndnsd Executable file → Normal file
View File

View File

@@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'date'
require 'etc'
require 'logger'
require 'ipaddr'
@@ -81,7 +80,7 @@ module Dyndnsd
end
# @param env [Hash{String => String}]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def call(env)
return [422, {'X-DynDNS-Response' => 'method_forbidden'}, []] if env['REQUEST_METHOD'] != 'GET'
return [422, {'X-DynDNS-Response' => 'not_found'}, []] if env['PATH_INFO'] != '/nic/update'
@@ -135,7 +134,7 @@ module Dyndnsd
private
# @param params [Hash{String => String}]
# @return [Array<String>]
# @return [Array{String}]
def extract_v4_and_v6_address(params)
return [] if !(params['myip'])
begin
@@ -149,7 +148,7 @@ module Dyndnsd
# @param env [Hash{String => String}]
# @param params [Hash{String => String}]
# @return [Array<String>]
# @return [Array{String}]
def extract_myips(env, params)
# require presence of myip parameter as valid IPAddr (v4) and valid myip6
return extract_v4_and_v6_address(params) if params.key?('myip6')
@@ -165,8 +164,8 @@ module Dyndnsd
end
# @param hostnames [String]
# @param myips [Array<String>]
# @return [Array<Symbol>]
# @param myips [Array{String}]
# @return [Array{Symbol}]
def process_changes(hostnames, myips)
changes = []
Helper.span('process_changes') do |span|
@@ -201,7 +200,7 @@ module Dyndnsd
end
# @param env [Hash{String => String}]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def handle_dyndns_request(env)
params = Rack::Utils.parse_query(env['QUERY_STRING'])
@@ -246,7 +245,7 @@ module Dyndnsd
if config['logfile']
Dyndnsd.logger = Logger.new(config['logfile'])
else
Dyndnsd.logger = Logger.new($stdout)
Dyndnsd.logger = Logger.new(STDOUT)
end
Dyndnsd.logger.progname = 'dyndnsd'
@@ -276,7 +275,7 @@ module Dyndnsd
reporter = Metriks::Reporter::Graphite.new(host, port, options)
reporter.start
elsif config['textfile']
file = (config['textfile']['file'] || '/tmp/dyndnsd-metrics.prom').to_s
file = config['textfile']['file'] || '/tmp/dyndnsd-metrics.prom'
options = {}
options[:prefix] = config['textfile']['prefix'] if config['textfile']['prefix']
reporter = Dyndnsd::TextfileReporter.new(file, options)

View File

@@ -27,7 +27,7 @@ module Dyndnsd
ips.each do |ip|
ip = IPAddr.new(ip).native
type = ip.ipv6? ? 'AAAA' : 'A'
name = hostname.chomp(".#{@domain}")
name = hostname.chomp('.' + @domain)
out << "#{name} IN #{type} #{ip}"
end
end

View File

@@ -60,7 +60,7 @@ module Dyndnsd
message: e.message,
stack: e.backtrace&.join("\n") || ''
)
raise e
raise
ensure
scope.close
end

View File

@@ -9,7 +9,7 @@ module Dyndnsd
end
# @param env [Hash{String => String}]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def call(env)
@app.call(env).tap do |status_code, headers, body|
if headers.key?('X-DynDNS-Response')
@@ -24,34 +24,30 @@ module Dyndnsd
# @param status_code [Integer]
# @param headers [Hash{String => String}]
# @param body [Array<String>]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @param body [Array{String}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def decorate_dyndnsd_response(status_code, headers, body)
case status_code
when 200
if status_code == 200
[200, {'Content-Type' => 'text/plain'}, [get_success_body(body[0], body[1])]]
when 422
elsif status_code == 422
error_response_map[headers['X-DynDNS-Response']]
end
# TODO: possible nil response!
end
# @param status_code [Integer]
# @param headers [Hash{String => String}]
# @param _body [Array<String>]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @param _body [Array{String}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def decorate_other_response(status_code, headers, _body)
case status_code
when 400
if status_code == 400
[status_code, headers, ['Bad Request']]
when 401
elsif status_code == 401
[status_code, headers, ['badauth']]
end
# TODO: possible nil response!
end
# @param changes [Array<Symbol>]
# @param myips [Array<String>]
# @param changes [Array{Symbol}]
# @param myips [Array{String}]
# @return [String]
def get_success_body(changes, myips)
changes.map { |change| "#{change} #{myips.join(' ')}" }.join("\n")

View File

@@ -9,7 +9,7 @@ module Dyndnsd
end
# @param env [Hash{String => String}]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def call(env)
@app.call(env).tap do |status_code, headers, body|
if headers.key?('X-DynDNS-Response')
@@ -24,34 +24,30 @@ module Dyndnsd
# @param status_code [Integer]
# @param headers [Hash{String => String}]
# @param body [Array<String>]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @param body [Array{String}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def decorate_dyndnsd_response(status_code, headers, body)
case status_code
when 200
if status_code == 200
[200, {'Content-Type' => 'text/plain'}, [get_success_body(body[0], body[1])]]
when 422
elsif status_code == 422
error_response_map[headers['X-DynDNS-Response']]
end
# TODO: possible nil response!
end
# @param status_code [Integer]
# @param headers [Hash{String => String}]
# @param _body [Array<String>]
# @return [Array{Integer,Hash{String => String},Array<String>}]
# @param _body [Array{String}]
# @return [Array{Integer,Hash{String => String},Array{String}}]
def decorate_other_response(status_code, headers, _body)
case status_code
when 400
if status_code == 400
[status_code, headers, ['Bad Request']]
when 401
elsif status_code == 401
[status_code, headers, ['Unauthorized']]
end
# TODO: possible nil response!
end
# @param changes [Array<Symbol>]
# @param myips [Array<String>]
# @param changes [Array{Symbol}]
# @param myips [Array{String}]
# @return [String]
def get_success_body(changes, myips)
changes.map { |change| change == :good ? "Changed to #{myips.join(' ')}" : "No change needed for #{myips.join(' ')}" }.join("\n")

View File

@@ -18,7 +18,7 @@ module Dyndnsd
@registry = options[:registry] || Metriks::Registry.default
@interval = options[:interval] || 60
@on_error = options[:on_error] || proc { |ex| } # default: ignore errors
@on_error = options[:on_error] || proc { |ex| }
end
# @return [void]
@@ -28,9 +28,11 @@ module Dyndnsd
sleep @interval
Thread.new do
write
rescue StandardError => e
@on_error[e] rescue nil
begin
write
rescue StandardError => e
@on_error[e] rescue nil
end
end
end
end
@@ -91,11 +93,11 @@ module Dyndnsd
end
end
# @param file [File]
# @param file [String]
# @param base_name [String]
# @param metric [Object]
# @param keys [Array<Symbol>]
# @param snapshot_keys [Array<Symbol>]
# @param keys [Array{Symbol}]
# @param snapshot_keys [Array{Symbol}]
# @return [void]
def write_metric(file, base_name, metric, keys, snapshot_keys = [])
time = Time.now.to_i

View File

@@ -85,7 +85,7 @@ module Dyndnsd
# converts into suitable parameter form for Async::DNS::Resolver or Async::DNS::Server
#
# @param endpoint_list [Array<String>]
# @param endpoint_list [Array{String}]
# @return [Array{Array{Object}}]
def self.parse_endpoints(endpoint_list)
endpoint_list.map { |addr_string| addr_string.split('@') }
@@ -139,7 +139,7 @@ module Dyndnsd
# @param name [String]
# @param resource_class [Resolv::DNS::Resource]
# Since solargraph cannot parse this: param transaction [Async::DNS::Transaction]
# @param transaction [Async::DNS::Transaction]
# @return [void]
def process(name, resource_class, transaction)
if name != @domain || resource_class != Resolv::DNS::Resource::Generic::Type252_Class1

View File

@@ -1,5 +1,5 @@
# frozen_string_literal: true
module Dyndnsd
VERSION = '3.3.0'
VERSION = '2.3.1'
end

View File

@@ -1,69 +0,0 @@
module Dyndnsd
type config = Hash[String, untyped]
type env = Hash[String, String]
type headers = Hash[String, String]
type response = Array[int | Hash[string, string] | Array[string]]
interface _App
def call: (env env) -> response
end
# @return [Logger]
def self.logger: () -> untyped
# @param logger [Logger]
# @return [Logger]
def self.logger=: (untyped logger) -> untyped
class LogFormatter
# @param lvl [Object]
# @param _time [DateTime]
# @param _progname [String]
# @param msg [Object]
# @return [String]
def call: (untyped lvl, DateTime _time, String _progname, untyped msg) -> String
end
class Daemon
# @param config [Hash{String => Object}]
# @param db [Dyndnsd::Database]
# @param updater [#update]
def initialize: (untyped config, untyped db, untyped updater) -> void
# @param username [String]
# @param password [String]
# @return [Boolean]
def authorized?: (String username, String password) -> bool
def call: (env env) -> response
def self.run!: () -> void
private
# @param params [Hash{String => String}]
# @return [Array<String>]
def extract_v4_and_v6_address: (untyped params) -> (::Array[untyped] | untyped)
# @param env [Hash{String => String}]
# @param params [Hash{String => String}]
# @return [Array<String>]
def extract_myips: (untyped env, untyped params) -> (untyped | ::Array[untyped])
# @param hostnames [String]
# @param myips [Array<String>]
# @return [Array<Symbol>]
def process_changes: (untyped hostnames, untyped myips) -> untyped
def update_db: () -> void
def handle_dyndns_request: (env env) -> response
def self.setup_logger: (config config) -> void
def self.setup_traps: () -> void
def self.setup_monitoring: (config config) -> void
def self.setup_tracing: (config config) -> void
def self.setup_rack: (config config) -> void
end
end

View File

@@ -1,21 +0,0 @@
module Dyndnsd
class Database
extend Forwardable
def initialize: (string db_file) -> void
def load: () -> void
def save: () -> void
def changed?: () -> bool
def []: (string key) -> untyped
def []=: (string key, untyped value) -> void
def each: () { (string key, untyped value) -> void } -> void
def has_key?: (string key) -> bool
end
end

View File

@@ -1,9 +0,0 @@
module Dyndnsd
module Generator
class Bind
def initialize: (String domain, Hash[String, untyped] updater_params) -> void
def generate: (Dyndnsd::Database db) -> string
end
end
end

View File

@@ -1,32 +0,0 @@
module Dyndnsd
type users = Hash[String, Hash[String, String]]
type hosts = Hash[String, Array[String]]
class Helper
# @param hostname [String]
# @param domain [String]
# @return [Boolean]
def self.fqdn_valid?: (String hostname, String domain) -> bool
# @param ip [String]
# @return [Boolean]
def self.ip_valid?: (String ip) -> bool
# @param username [String]
# @param password [String]
# @param users [Hash]
# @return [Boolean]
def self.user_allowed?: (String username, String password, users users) -> bool
# @param hostname [String]
# @param myips [Array]
# @param hosts [Hash]
# @return [Boolean]
def self.changed?: (String hostname, Array[String] myips, hosts hosts) -> bool
# @param operation [String]
# @param block [Proc]
# @return [void]
def self.span: (String operation) { (untyped) -> untyped } -> untyped
end
end

View File

@@ -1,19 +0,0 @@
module Dyndnsd
module Responder
class DynDNSStyle
def initialize: (_App app) -> void
def call: (env env) -> response?
private
def decorate_dyndnsd_response: (int status_code, headers headers, Array[untyped] body) -> response?
def decorate_other_response: (int status_code, headers headers, Array[untyped] _body) -> response?
def get_success_body: (Array[Symbol] changes, Array[string] myips) -> string
def error_response_map: () -> Hash[string, response]
end
end
end

View File

@@ -1,19 +0,0 @@
module Dyndnsd
module Responder
class RestStyle
def initialize: (_App app) -> void
def call: (env env) -> response?
private
def decorate_dyndnsd_response: (int status_code, headers headers, Array[untyped] body) -> response?
def decorate_other_response: (int status_code, headers headers, Array[untyped] _body) -> response?
def get_success_body: (Array[Symbol] changes, Array[string] myips) -> string
def error_response_map: () -> Hash[string, response]
end
end
end

View File

@@ -1,17 +0,0 @@
module Dyndnsd
class TextfileReporter
attr_reader file: String
def initialize: (String file, ?Hash[Symbol, untyped] options) -> void
def start: () -> void
def stop: () -> void
def restart: () -> void
def write: () -> void
def write_metric: (File file, String base_name, untyped metric, Array[Symbol] keys, Array[Symbol] snapshot_keys) -> void
end
end

View File

@@ -1,9 +0,0 @@
module Dyndnsd
module Updater
class CommandWithBindZone
def initialize: (String domain, Hash[String, untyped] updater_params) -> void
def update: (Dyndnsd::Database db) -> void
end
end
end

View File

@@ -1,39 +0,0 @@
module Dyndnsd
module Updater
class ZoneTransferServer
DEFAULT_SERVER_LISTENS: Array[String]
def initialize: (String domain, Hash[String, untyped] updater_params) -> void
def update: (Dyndnsd::Database db) -> void
# converts into suitable parameter form for Async::DNS::Resolver or Async::DNS::Server
#
# @param endpoint_list [Array<String>]
# @return [Array{Array{Object}}]
def self.parse_endpoints: (Array[String] endpoint_list) -> Array[Array[untyped]]
private
# creates correct Resolv::DNS::Resource object for IP address type
#
# @param ip_string [String]
# @return [Resolv::DNS::Resource::IN::A,Resolv::DNS::Resource::IN::AAAA]
def create_addr_rr_for_ip: (String ip_string) -> untyped
def send_dns_notify: () -> void
end
class ZoneTransferServerHelper #< Async::DNS::Server
attr_accessor axfr_rrs: untyped
def initialize: (untyped endpoints, String domain) -> void
# @param name [String]
# @param resource_class [Resolv::DNS::Resource]
# Since solargraph cannot parse this: param transaction [Async::DNS::Transaction]
# @return [void]
def process: (String name, untyped resource_class, untyped transaction) -> void
end
end
end

View File

@@ -1,3 +0,0 @@
module Dyndnsd
VERSION: ::String
end

View File

@@ -1,12 +1,12 @@
# frozen_string_literal: true
require_relative '../spec_helper'
require_relative 'spec_helper'
describe Dyndnsd::Daemon do
include Rack::Test::Methods
def app
Dyndnsd.logger = Logger.new($stdout)
Dyndnsd.logger = Logger.new(STDOUT)
Dyndnsd.logger.level = Logger::UNKNOWN
config = {