pdns 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c548efb5322ae845a32fc76cda6c1f0f8adc57c8
4
+ data.tar.gz: ee2fece01f74c12190eb7aeead73e4d200254843
5
+ SHA512:
6
+ metadata.gz: c44a29803823cf7db534546d864c39c621487d0f41d3e304c32ef066adc6a4caa98e6d6e718e59407f9f409b8aa1d3a9d6f30f673d008b6d9c6445347abac713
7
+ data.tar.gz: 7c83b81f4bceea5bbcb859fc6d343e353094172f0d3fa6f027724cabf46517442f23c058f67bf1ab59682a2cb03963336ff3a951a86e2b89d1b5d7bcef500a00
@@ -0,0 +1,20 @@
1
+ Copyright 2017 linyows
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ PDNS
2
+ =======
3
+
4
+ The PDNS is PowerDNS API mountable engine for Rails.
5
+
6
+ [![Travis](https://img.shields.io/travis/linyows/pdns.svg?style=flat-square)](https://travis-ci.org/linyows/pdns)
7
+ [![ruby gem](https://img.shields.io/gem/v/pdns.svg?style=flat-square)](https://rubygems.org/gems/pdns)
8
+
9
+ Installation
10
+ ------------
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```rb
15
+ gem 'pdns'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```sh
21
+ $ bundle
22
+ ```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```sh
27
+ $ gem install pdns
28
+ ```
29
+
30
+ Usage
31
+ -----
32
+
33
+ config/routes.rb:
34
+
35
+ ```rb
36
+ mount PDNS::Engine, at: '/dns'
37
+ ```
38
+
39
+ setup:
40
+
41
+ ```sh
42
+ $ bin/rails pdns:install:migrations
43
+ ```
44
+
45
+ Development
46
+ -----------
47
+
48
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
49
+
50
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
51
+
52
+ Contributing
53
+ ------------
54
+
55
+ Bug reports and pull requests are welcome on GitHub at https://github.com/linyows/pdns.
56
+
57
+ Author
58
+ ------
59
+
60
+ - [linyows](https://github.com/linyows)
61
+
62
+ License
63
+ -------
64
+
65
+ The MIT License (MIT)
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'PDNS'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,4 @@
1
+ module PDNS
2
+ class ApplicationController < ActionController::API
3
+ end
4
+ end
@@ -0,0 +1,39 @@
1
+ require_dependency 'pdns/application_controller'
2
+
3
+ module PDNS
4
+ class DomainsController < ApplicationController
5
+ before_action :set_domain, only: %i(show destroy)
6
+
7
+ def show
8
+ render json: @domain, status: :ok
9
+ end
10
+
11
+ def create
12
+ @domain = Domain.new(domain_params)
13
+
14
+ if @domain.save
15
+ render json: @domain, status: :created
16
+ else
17
+ render json: @domain.errors, status: :unprocessable_entity
18
+ end
19
+ end
20
+
21
+ def destroy
22
+ @domain.destroy
23
+ head :no_content
24
+ end
25
+
26
+ private
27
+
28
+ def set_domain
29
+ @domain = Domain.find_by(name: params[:id])
30
+ raise ActiveRecord::RecordNotFound.new(
31
+ "#{params[:id]} not found"
32
+ ) if @domain.nil?
33
+ end
34
+
35
+ def domain_params
36
+ params[:domain].permit %i(name type)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,83 @@
1
+ require_dependency 'pdns/application_controller'
2
+
3
+ module PDNS
4
+ class RecordsController < ApplicationController
5
+ before_action :set_domain, only: %i(show create update destroy force_update_records)
6
+ before_action :set_record, only: %i(show update destroy)
7
+ before_action :delete_records, only: %i(create)
8
+
9
+ def show
10
+ render json: @record, status: :ok
11
+ end
12
+
13
+ def create
14
+ @record = @domain.records.create(record_params)
15
+
16
+ if @record.save
17
+ update_serial
18
+ render json: @record, status: :created
19
+ else
20
+ render json: @record.errors, status: :unprocessable_entity
21
+ end
22
+ end
23
+
24
+ def update
25
+ if @record.update(record_params)
26
+ update_serial
27
+ render json: @record, status: :ok
28
+ else
29
+ render json: @record.errors, status: :unprocessable_entity
30
+ end
31
+ end
32
+
33
+ def destroy
34
+ @record.destroy
35
+ update_serial
36
+ head :no_content
37
+ end
38
+
39
+ def force_update_records
40
+ type = params[:type] || 'A'
41
+ @domain.records.where(type: type).update_all(record_params)
42
+ render json: @domain.records.where(type: type), status: :ok
43
+ end
44
+
45
+ private
46
+
47
+ def set_domain
48
+ @domain = Domain.find_by(name: params[:domain_id])
49
+ raise ActiveRecord::RecordNotFound.new(
50
+ "#{params[:domain_id]} not found"
51
+ ) if @domain.nil?
52
+ end
53
+
54
+ def set_record
55
+ permitted = params.permit %i(id type content ttl prio)
56
+ permitted[:name] = permitted.delete :id
57
+
58
+ record = @domain.records.where(permitted)
59
+ raise ActiveRecord::RecordNotFound.new(
60
+ "record not found"
61
+ ) if record.empty?
62
+
63
+ raise ActiveRecord::ActiveRecordError.new(
64
+ "record not unique"
65
+ ) unless record.one?
66
+ @record = record.first
67
+ end
68
+
69
+ def record_params
70
+ params[:record].permit %i(name type content ttl prio)
71
+ end
72
+
73
+ def delete_records
74
+ params['before_delete_conditions'].each do |condition|
75
+ condition.each { |k, v| @domain.records.where(k => v).destroy_all }
76
+ end if params['before_delete_conditions'].present?
77
+ end
78
+
79
+ def update_serial
80
+ @record.update_serial if params[:skip_update_serial].nil?
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,6 @@
1
+ module PDNS
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ establish_connection PDNS.db_conf[Rails.env.to_s]
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module PDNS
2
+ class Domain < ApplicationRecord
3
+ self.table_name = :domains
4
+ self.inheritance_column = :_type_disabled
5
+ has_many :records, dependent: :destroy
6
+
7
+ validates :name, presence: true, uniqueness: true,
8
+ format: { with: PDNS.domain_format }
9
+ validates :type, presence: true, inclusion: {
10
+ in: %w(NATIVE MASTER SLAVE SUPERSLAVE)
11
+ }
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module PDNS
2
+ class Record < ApplicationRecord
3
+ self.table_name = :records
4
+ self.inheritance_column = :_type_disabled
5
+ belongs_to :domain
6
+
7
+ validates :domain_id, presence: true
8
+ validates :name, presence: true,
9
+ format: { with: PDNS.domain_format },
10
+ uniqueness: { scope: [:type, :content] }
11
+ validates :type, presence: true, inclusion: {
12
+ in: %w(SOA NS A CNAME MX TXT SRV PTR AAAA LOC SPF SSHFP)
13
+ }
14
+ validates :content, presence: true
15
+ validates :ttl, numericality: true, presence: true
16
+ validates :prio, numericality: { if: :mx? }, presence: { if: :mx? }
17
+
18
+ before_update :set_change_date
19
+
20
+ def mx?
21
+ self.type == 'MX'
22
+ end
23
+
24
+ def update_serial
25
+ soa = Record.where(domain_id: domain_id, type: 'SOA').first
26
+ unless soa.nil?
27
+ list = soa.content.split(' ')
28
+ serial = list[2]
29
+ list[2] = serial.to_i + 1
30
+ soa.update_column(:content, list.join(' '))
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def set_change_date
37
+ self.change_date = Time.now.to_i
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,6 @@
1
+ PDNS::Engine.routes.draw do
2
+ resources :domains, only: %i(create show destroy), id: PDNS.domain_format_for_routes do
3
+ resources :records, except: %i(index new edit), id: PDNS.domain_format_for_routes
4
+ put 'force_update_records', to: 'records#force_update_records'
5
+ end
6
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(version: 20130429134229) do
15
+ create_table 'domains', force: true do |t|
16
+ t.string 'name'
17
+ t.string 'master'
18
+ t.integer 'last_check'
19
+ t.string 'type', default: 'NATIVE'
20
+ t.integer 'notified_serial'
21
+ t.string 'account'
22
+ t.integer 'ttl', default: 86400
23
+ t.datetime 'created_at', null: false
24
+ t.datetime 'updated_at', null: false
25
+ t.integer 'user_id'
26
+ t.text 'notes'
27
+ end
28
+
29
+ add_index 'domains', %w(name), name: 'index_domains_on_name'
30
+
31
+ create_table 'records', force: true do |t|
32
+ t.integer 'domain_id', null: false
33
+ t.string 'name', null: false
34
+ t.string 'type', null: false
35
+ t.string 'content', null: false
36
+ t.integer 'ttl', null: false
37
+ t.integer 'prio'
38
+ t.integer 'change_date', null: false
39
+ t.datetime 'created_at'
40
+ t.datetime 'updated_at'
41
+ end
42
+
43
+ add_index 'records', %w(domain_id), name: 'index_records_on_domain_id'
44
+ add_index 'records', %w(name type), name: 'index_records_on_name_and_type'
45
+ add_index 'records', %w(name), name: 'index_records_on_name'
46
+ end
@@ -0,0 +1,12 @@
1
+ module PDNS
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path('../../templates', __FILE__)
4
+
5
+ desc 'Creates a PDNS initializer.'
6
+
7
+ def copy_initializer
8
+ template 'pdns.rb', 'config/initializers/pdns.rb'
9
+ template 'database.yml', "config/database-#{PDNS.db_name}.yml"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,38 @@
1
+ sqlite: &sqlite
2
+ adapter: sqlite3
3
+ database: db/development.sqlite3
4
+
5
+ mysql: &mysql
6
+ adapter: mysql2
7
+ username: root
8
+ host: localhost
9
+ password:
10
+ database: pdns_development
11
+ encoding: utf8
12
+
13
+ postgresql: &postgresql
14
+ pool: 16
15
+ timeout: 5000
16
+ adapter: postgresql
17
+ encoding: unicode
18
+ username: postgres
19
+ password:
20
+ database: pdns_development
21
+ min_messages: ERROR
22
+
23
+ default: &default
24
+ <<: *mysql
25
+
26
+ development:
27
+ <<: *default
28
+
29
+ test:
30
+ <<: *default
31
+ database: pdns_test
32
+
33
+ production:
34
+ <<: *default
35
+ database: pdns
36
+ host: "<%= ENV['DB_HOST'] %>"
37
+ username: "<%= ENV['DB_USER'] %>"
38
+ password: "<%= ENV['DB_PASS'] %>"
@@ -0,0 +1,8 @@
1
+ PDNS.setup do |c|
2
+ # Defaults:
3
+ # c.domain_format = /\A[^-][a-z0-9\-\._]*[^-]\.[a-z0-9-]{2,}\Z/
4
+ # c.domain_format_for_routes = /[a-z0-9\-\._]*\.[a-z0-9-]{2,}/
5
+ # c.db_name = :pdns
6
+ # c.db_conf_path = "config/database-#{self.db_name}.yml"
7
+ # c.db_dir_path = File.expand_path('../../db', __FILE__)
8
+ end
@@ -0,0 +1,28 @@
1
+ require 'pdns/engine'
2
+
3
+ module PDNS
4
+ mattr_accessor :domain_format
5
+ self.domain_format = /\A[^-][a-z0-9\-\._]*[^-]\.[a-z0-9-]{2,}\Z/
6
+
7
+ mattr_accessor :domain_format_for_routes
8
+ self.domain_format_for_routes = /[a-z0-9\-\._]*\.[a-z0-9-]{2,}/
9
+
10
+ mattr_accessor :db_name
11
+ self.db_name = :pdns
12
+
13
+ mattr_accessor :db_conf_path
14
+ self.db_conf_path = "config/database-#{self.db_name}.yml"
15
+
16
+ mattr_accessor :db_dir_path
17
+ self.db_dir_path = File.expand_path('../../db', __FILE__)
18
+
19
+ class << self
20
+ def setup
21
+ yield self
22
+ end
23
+
24
+ def db_conf
25
+ @db_conf ||= ::YAML::load(ERB.new(IO.read(self.db_conf_path.to_s)).result)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,5 @@
1
+ module PDNS
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace PDNS
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module PDNS
2
+ VERSION = '0.3.0'
3
+ end
@@ -0,0 +1,26 @@
1
+ require 'pdns'
2
+ include ActiveRecord::Tasks
3
+
4
+ namespace :pdns do
5
+ task :prepare do
6
+ DatabaseTasks.database_configuration = PDNS.db_conf
7
+ DatabaseTasks.db_dir = PDNS.db_dir_path
8
+ ActiveRecord::Base.configurations = DatabaseTasks.database_configuration
9
+ DatabaseTasks.current_config = DatabaseTasks.database_configuration[Rails.env]
10
+ end
11
+
12
+ desc 'Create database for PDNS'
13
+ task create: %i(prepare) do
14
+ DatabaseTasks.create_current
15
+ end
16
+
17
+ desc 'Drop database for PDNS'
18
+ task drop: %i(prepare) do
19
+ DatabaseTasks.drop_current
20
+ end
21
+
22
+ desc 'Setup database for PDNS'
23
+ task setup: %i(prepare) do
24
+ DatabaseTasks.load_schema_current(:ruby)
25
+ end
26
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pdns
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0
5
+ platform: ruby
6
+ authors:
7
+ - linyows
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.2.7
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.7
27
+ - !ruby/object:Gem::Dependency
28
+ name: mysql2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: The Pengin is PowerDNS API mountable engine for Rails.
56
+ email:
57
+ - linyows@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - MIT-LICENSE
63
+ - README.md
64
+ - Rakefile
65
+ - app/controllers/pdns/application_controller.rb
66
+ - app/controllers/pdns/domains_controller.rb
67
+ - app/controllers/pdns/records_controller.rb
68
+ - app/models/pdns/application_record.rb
69
+ - app/models/pdns/domain.rb
70
+ - app/models/pdns/record.rb
71
+ - config/routes.rb
72
+ - db/schema.rb
73
+ - lib/generators/pdns/install_generator.rb
74
+ - lib/generators/templates/database.yml
75
+ - lib/generators/templates/pdns.rb
76
+ - lib/pdns.rb
77
+ - lib/pdns/engine.rb
78
+ - lib/pdns/version.rb
79
+ - lib/tasks/pdns_tasks.rake
80
+ homepage: https://github.com/linyows/pdns
81
+ licenses:
82
+ - MIT
83
+ metadata: {}
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: '0'
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.5.1
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: The Pengin is PowerDNS API mountable engine for Rails.
104
+ test_files: []