phpipam2masq 1.0.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bdfa6fce3a2f12fbfe0844ee15c9d331ad43e4e4a267490ab32f184136e105ed
4
+ data.tar.gz: f437e08008dd874957fdc6f4dc422ee210313bb9824fb1bbc9124223b19ab795
5
+ SHA512:
6
+ metadata.gz: 730fe2449828280400e396c20eb2b40ec1f6a4f0d3d1ca94227a6113fca47053b7e3c313ee32bfdbb65ad97c89bb9a47400a5a31cf5c2047941476742bdaab2e
7
+ data.tar.gz: 5ad003c92a6163d912adff30a15808d7ca7fc2348f31c4206d264b243146711ace2dcf43bd9137fade3b6bb7fef294dbfb13dbfed31052a4d9944c631b7c0445
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+ source 'http://gemserver.priv.svdasein.net:8088'
3
+
4
+ # Specify your gem's dependencies in phpipam2masq.gemspec
5
+ gem "pry"
6
+ gem "pry-rescue"
7
+ gem "pry-stack_explorer"
8
+ gem "geminabox"
9
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,76 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ phpipam2masq (0.1.4)
5
+ awesome_print (~> 1.0)
6
+ facets (~> 3.0)
7
+ faraday (~> 0.15)
8
+ ipaddress (~> 0.8)
9
+ json (~> 2.0)
10
+ sinatra (~> 2.0)
11
+ trollop (~> 2.1)
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ remote: http://gemserver.priv.svdasein.net:8088/
16
+ specs:
17
+ awesome_print (1.8.0)
18
+ binding_of_caller (0.8.0)
19
+ debug_inspector (>= 0.0.1)
20
+ builder (3.2.3)
21
+ coderay (1.1.2)
22
+ debug_inspector (0.0.3)
23
+ facets (3.1.0)
24
+ faraday (0.15.2)
25
+ multipart-post (>= 1.2, < 3)
26
+ geminabox (1.1.0)
27
+ builder
28
+ faraday
29
+ httpclient (>= 2.2.7)
30
+ nesty
31
+ reentrant_flock
32
+ sinatra (>= 1.2.7)
33
+ httpclient (2.8.3)
34
+ interception (0.5)
35
+ ipaddress (0.8.3)
36
+ json (2.1.0)
37
+ method_source (0.9.0)
38
+ multipart-post (2.0.0)
39
+ mustermann (1.0.2)
40
+ nesty (1.0.2)
41
+ pry (0.11.3)
42
+ coderay (~> 1.1.0)
43
+ method_source (~> 0.9.0)
44
+ pry-rescue (1.4.5)
45
+ interception (>= 0.5)
46
+ pry
47
+ pry-stack_explorer (0.4.9.2)
48
+ binding_of_caller (>= 0.7)
49
+ pry (>= 0.9.11)
50
+ rack (2.0.5)
51
+ rack-protection (2.0.3)
52
+ rack
53
+ rake (10.5.0)
54
+ reentrant_flock (0.1.1)
55
+ sinatra (2.0.3)
56
+ mustermann (~> 1.0)
57
+ rack (~> 2.0)
58
+ rack-protection (= 2.0.3)
59
+ tilt (~> 2.0)
60
+ tilt (2.0.8)
61
+ trollop (2.1.2)
62
+
63
+ PLATFORMS
64
+ ruby
65
+
66
+ DEPENDENCIES
67
+ bundler (~> 1.9)
68
+ geminabox
69
+ phpipam2masq!
70
+ pry
71
+ pry-rescue
72
+ pry-stack_explorer
73
+ rake (~> 10.0)
74
+
75
+ BUNDLED WITH
76
+ 1.16.2
data/Procfile ADDED
@@ -0,0 +1 @@
1
+ updater: bundle exec rackup -o 0.0.0.0 -p 4567
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # phpipam2masq
2
+
3
+ phpipam2masq is a small application that generates dnsmasq configuration files from a [phpipam](https://phpipam.net/) instance. It's appropriate for SOHO use as it is and can (with some hacking) be made to work "ok" in a larger environment.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'phpipam2masq'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install phpipam2masq
20
+
21
+ ## Configuration
22
+
23
+ Before using it, you must create a new api key in phpipam for the application:
24
+
25
+ ![API Key screenshot](img/apikey.png)
26
+
27
+ You should also add a few custom fields to your phpipam installation:
28
+
29
+ ![Custom Fields screenshot](img/customfields.png)
30
+
31
+ On your dnsmasq system (where you'll be running phpipam2masq), you need to make a configration
32
+ destination directory. It should look like this:
33
+
34
+ dest/
35
+ dest/dnsmasq.d/
36
+
37
+ If you take the defaults (see below), dest is /etc and dnsmasq.d will likely already be there.
38
+
39
+ The following files will be generated:
40
+
41
+ dest/dnsmasq.d/ranges
42
+ dest/dnsmasq.d/cnames
43
+ dest/dnsmasq-hosts.conf
44
+ dest/dnsmasq-dhcp-hosts.conf
45
+
46
+ Finally, configure dnsmasq to point at the generated files:
47
+
48
+ addn-hosts=dest/dnsmasq-hosts.conf
49
+ dhcp-hostsfile=dest/dnsmasq-dhcp-hosts.conf
50
+ conf-dir=dest/dnsmasq.d
51
+
52
+ ## Usage
53
+
54
+ phpipam2masq options can be specified entirely on the command line or in a configuration file. Command line switches override config file settings.
55
+
56
+ Usage: phpipam2masq [options]
57
+
58
+ Options:
59
+ -c, --config=<s> Config file path
60
+ -t, --destdir=<s> Destination dir
61
+ -a, --apiurl=<s> API URL
62
+ -u, --apiuser=<s> Database user
63
+ -p, --apipass=<s> Database password
64
+ -s, --sections=<s> Section IDs (comma sep)
65
+ -d, --dhcptag=<i> DHCP Tag value
66
+ -v, --verbose Verbose output
67
+ -h, --help Show this message
68
+
69
+ Default values are:
70
+
71
+ defaults = {
72
+ :config => '/etc/phpipam2masq.conf',
73
+ :destdir => '/etc',
74
+ :apiurl => 'http://localhost/api',
75
+ :apiuser=> '',
76
+ :apipass => '',
77
+ :section => '0',
78
+ :dhcptag => '4'
79
+ }
80
+
81
+ The configuration file format is yaml:
82
+
83
+ ---
84
+ apiurl: http://myhost/phpipam/api/masq (or the app name you chose)/
85
+ apiuser: myuser
86
+ apipass: mypass
87
+ sections: "<csv list of phpipam section numbers>"
88
+
89
+ phpipam2masq re-generates all the files listed above each time you execute it.
90
+
91
+ I've included a very slapped together web interface for this thing that you can use to update your dnsmasq configuration from a browser. See the .ru in conf/ and the corresponding thing in exe/. It's not secure and it's not elegant but it does the job for my home lab. Feel free to embellish it. I put a link to this in my phpipam "Instructions" page that pops up a little window that shows command output - very handy.
92
+
93
+
94
+ ## Development
95
+
96
+ 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.
97
+
98
+ 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).
99
+
100
+ ## Contributing
101
+
102
+ Bug reports and pull requests are welcome on GitHub at https://gitlab.com/svdasein/phpipam2masq.
103
+
104
+
105
+ ## License
106
+
107
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
108
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "phpipam2masq"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ version = ">= 0.a"
3
+ gem 'phpipam2masq', version
4
+ require Gem.bin_path('phpipam2masq', 'dnsmasqconfigupdater.rb', version)
5
+ run Sinatra::Application
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'sinatra'
4
+
5
+ set :bind, '0.0.0.0'
6
+
7
+ get '/updateDnsmasq' do
8
+ output = String.new
9
+ output += Time.now.to_s
10
+ output += "\n#{%x(phpipam2masq.rb 2>&1)}"
11
+ output += Time.now.to_s
12
+ %Q(<pre>#{output}</pre>)
13
+ end
14
+
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'faraday'
4
+ require 'json'
5
+ require 'trollop'
6
+ require 'facets'
7
+ require 'awesome_print'
8
+ require 'ipaddress'
9
+ require 'yaml'
10
+
11
+ defaults = {
12
+ :config => '/etc/phpipam2masq.conf',
13
+ :destdir => '/etc',
14
+ :apiurl => 'http://localhost/api',
15
+ :apiuser=> '',
16
+ :apipass => '',
17
+ :section => '0',
18
+ :dhcptag => '4'
19
+ }
20
+
21
+ opts = Trollop::options do
22
+ usage '[options]'
23
+ #version %Q{Version #{Gestio2masq::VERSION}}
24
+ opt :config, 'Config file path', :short => 'c', :type => :string
25
+ opt :destdir, 'Destination dir', :short => 't', :type => :string
26
+ opt :apiurl, 'API URL', :short => 'a', :type => :string
27
+ opt :apiuser, 'Database user', :short => 'u', :type => :string
28
+ opt :apipass, 'Database password', :short => 'p', :type => :string
29
+ opt :sections , "Section IDs (comma sep)", :short => 's', :type=>:string
30
+ opt :dhcptag , "DHCP Tag value", :short => 'd', :type=>:integer
31
+ opt :verbose, 'Verbose output', :short => 'v'
32
+ end
33
+
34
+ config_file = opts[:config]||defaults[:config]
35
+
36
+ config = nil
37
+ if File.exist?(config_file)
38
+ begin
39
+ config = YAML.load(File.read(config_file))
40
+ rescue => detail
41
+ puts detail.backtrace
42
+ puts %Q(Error reading config from file #{config_file})
43
+ exit(1)
44
+ end
45
+ end
46
+
47
+ if config.nil? or (config.class != Hash)
48
+ config = Hash.new
49
+ else
50
+ # symbolize hash keys (json format compatibility)
51
+ config = Hash[config.map { |(k, v)| [k.to_sym, v] }]
52
+ end
53
+
54
+ # Precedence (low to high): defaults, config file, command line
55
+ config = defaults.merge(config).merge(Hash(opts.select { |k, v| !v.nil? }))
56
+
57
+
58
+ conn = Faraday.new(:url=>config[:apiurl])
59
+ conn.basic_auth(config[:apiuser],config[:apipass])
60
+ auth = conn.post('user/')
61
+ auth = JSON.parse(auth.body)
62
+ conn.headers['token'] = auth['data']['token']
63
+
64
+ subnets = Hash.new
65
+ config[:sections].split(',').each { |subnetid|
66
+ JSON.parse(conn.get("sections/#{subnetid}/subnets/").body)['data'].each { |subnet|
67
+ subnets[subnet['id']] = subnet.symbolize_keys
68
+ }
69
+ }
70
+
71
+ addresses = Hash.new
72
+ subnets.keys.each { |subnetid|
73
+ resp = JSON.parse(conn.get("subnets/#{subnetid}/addresses/").body)
74
+ if resp.has_key?('data')
75
+ resp['data'].each { |addr|
76
+ addr.symbolize_keys!
77
+ if not addr[:id].nil?
78
+ addresses[addr[:id]] = addr
79
+ addresses[addr[:id]][:subnet] = subnets[subnetid]
80
+ end
81
+ }
82
+ end
83
+ }
84
+
85
+
86
+ # Convert all the addreses keys to symbols
87
+
88
+ hosts_entries = Array.new
89
+ dhcp_hosts_entries = Array.new
90
+ cnames_entries = Array.new
91
+ addresses.values.each { |host|
92
+ if host[:tag] != config[:dhcptag] and host[:hostname].size > 0
93
+ if host[:mac] and host[:mac].size > 0
94
+ # static dhcp assignment
95
+ if host[:optiontag]
96
+ dhcp_hosts_entries.push("#{host[:mac]},set:#{host[:optiontag]},#{host[:hostname].split('.').shift},#{host[:ip]},#{host[:subnet][:leasetime]}")
97
+ else
98
+ dhcp_hosts_entries.push("#{host[:mac]},#{host[:hostname].split('.').shift},#{host[:ip]},#{host[:subnet][:leasetime]}")
99
+ end
100
+ end
101
+ # hostname
102
+ if host[:subnet] and host[:subnet][:Domain]
103
+ hosts_entries.push("#{host[:ip]}\t#{host[:hostname]}.#{host[:subnet][:Domain]}")
104
+ else
105
+ hosts_entries.push("#{host[:ip]}\t#{host[:hostname]}")
106
+ end
107
+ # cnames
108
+ if host[:CNAMEs]
109
+ host[:CNAMEs].split(',').each { |cname|
110
+ if host[:subnet] and host[:subnet][:Domain]
111
+ cnames_entries.push("cname=#{cname},#{host[:hostname]}.#{host[:subnet][:Domain]}")
112
+ else
113
+ cnames_entries.push("cname=#{cname},#{host[:hostname]}")
114
+ end
115
+ }
116
+ end
117
+ end
118
+ }
119
+
120
+ # This monster produces a hash, one kv for each subnet, where the v contains an array of ranges for the subnet in question. This works
121
+ # under the presumption that the phpipam api produces an ordered list of addresses when one dumps all addresses from a subnet (which
122
+ # as of this writing appears to be true)
123
+ subnetranges = Hash.new
124
+ subnets.keys.each { |subnetid|
125
+ subnetranges[subnetid] = Array.new
126
+ rawrange = addresses.values.select {|each| each[:subnet][:id] == subnetid}.chunk {|each| each[:tag] == config[:dhcptag]}.select {|isDhcp,ary| isDhcp}
127
+ if rawrange.size > 0
128
+ # This next one ensures that we're dealing with immediately adjacent ip addresses by looking a the last octet of two in the list and
129
+ # seeing if they're immediately next to each other. If they are not we have multiple chunks in this subnet.
130
+ ranges = rawrange[0][1].chunk_while { |a,b| a[:ip].split('.').pop.to_i + 1 == b[:ip].split('.').pop.to_i}
131
+ ranges.to_a.each {|range|
132
+ subnetranges[subnetid].push(range)
133
+ }
134
+ end
135
+ }
136
+
137
+
138
+ ranges_entries = Array.new
139
+ subnetranges.each_pair { |subnetid,ranges|
140
+ subnet = subnets[subnetid]
141
+ subnettag = subnet[:subnettag]
142
+ next if not subnettag or ranges.size == 0
143
+ ranges.each { |range|
144
+ first = range.first
145
+ last = range.last
146
+ mask = IPAddress.parse("#{subnet[:subnet]}/#{subnet[:mask]}").netmask
147
+ ranges_entries.push("dhcp-range=#{subnettag},#{first[:ip]},#{last[:ip]},#{mask},#{subnet[:dynleasetime]}")
148
+ }
149
+ }
150
+
151
+
152
+ puts "="*80 if config[:verbose]
153
+ puts "RANGES: #{ranges_entries.size}"
154
+ File.new(%Q(#{config[:destdir]}/dnsmasq.d/ranges), 'w').puts(ranges_entries.join("\n"))
155
+ puts(ranges_entries.join("\n")) if config[:verbose]
156
+ puts "="*80 if config[:verbose]
157
+ puts "CNAMES: #{cnames_entries.size}"
158
+ File.new(%Q(#{config[:destdir]}/dnsmasq.d/cnames), 'w').puts(cnames_entries.join("\n"))
159
+ puts(cnames_entries.join("\n")) if config[:verbose]
160
+ puts "="*80 if config[:verbose]
161
+ puts "DHCP HOSTS: #{dhcp_hosts_entries.size}"
162
+ File.new(%Q(#{config[:destdir]}/dnsmasq-dhcp-hosts.conf), 'w').puts(dhcp_hosts_entries.join("\n"))
163
+ puts(dhcp_hosts_entries.join("\n")) if config[:verbose]
164
+ puts "="*80 if config[:verbose]
165
+ puts "HOSTS: #{hosts_entries.size}"
166
+ File.new(%Q(#{config[:destdir]}/dnsmasq-hosts.conf), 'w').puts(hosts_entries.join("\n"))
167
+ puts(hosts_entries.join("\n")) if config[:verbose]
168
+
169
+
data/img/apikey.png ADDED
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ require "phpipam2masq/version"
2
+
3
+ module Phpipam2masq
4
+ # Your code goes here...
5
+ end
@@ -0,0 +1,3 @@
1
+ module Phpipam2masq
2
+ VERSION = "1.0.3"
3
+ end
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'phpipam2masq/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "phpipam2masq"
8
+ spec.version = Phpipam2masq::VERSION
9
+ spec.authors = ["Dave Parker"]
10
+ spec.email = ["daveparker01@gmail.com"]
11
+
12
+ spec.summary = %q{Logic to push phpipam configuration to a dnsmasq configuration}
13
+ spec.homepage = "https://gitlab.com/svdasein/phpipam2masq"
14
+ spec.license = "MIT"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against " \
22
+ "public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.9"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_runtime_dependency 'faraday', '~> 0.15'
35
+ spec.add_runtime_dependency 'json', '~> 2.0'
36
+ spec.add_runtime_dependency 'trollop', '~> 2.1'
37
+ spec.add_runtime_dependency 'facets', '~> 3.0'
38
+ spec.add_runtime_dependency 'awesome_print', '~> 1.0'
39
+ spec.add_runtime_dependency 'ipaddress', '~> 0.8'
40
+ spec.add_runtime_dependency 'sinatra', '~> 2.0'
41
+ end
metadata ADDED
@@ -0,0 +1,187 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phpipam2masq
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Dave Parker
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-07-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.9'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.15'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.15'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: trollop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: facets
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: awesome_print
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: ipaddress
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.8'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.8'
125
+ - !ruby/object:Gem::Dependency
126
+ name: sinatra
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '2.0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '2.0'
139
+ description:
140
+ email:
141
+ - daveparker01@gmail.com
142
+ executables:
143
+ - dnsmasqconfigupdater.rb
144
+ - phpipam2masq.rb
145
+ extensions: []
146
+ extra_rdoc_files: []
147
+ files:
148
+ - Gemfile
149
+ - Gemfile.lock
150
+ - Procfile
151
+ - README.md
152
+ - bin/console
153
+ - bin/setup
154
+ - conf/dnsmasq-config-updater.ru
155
+ - exe/dnsmasqconfigupdater.rb
156
+ - exe/phpipam2masq.rb
157
+ - img/apikey.png
158
+ - img/customfields.png
159
+ - lib/phpipam2masq.rb
160
+ - lib/phpipam2masq/version.rb
161
+ - phpipam2masq.gemspec
162
+ homepage: https://gitlab.com/svdasein/phpipam2masq
163
+ licenses:
164
+ - MIT
165
+ metadata:
166
+ allowed_push_host: https://rubygems.org
167
+ post_install_message:
168
+ rdoc_options: []
169
+ require_paths:
170
+ - lib
171
+ required_ruby_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ required_rubygems_version: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ requirements: []
182
+ rubyforge_project:
183
+ rubygems_version: 2.7.7
184
+ signing_key:
185
+ specification_version: 4
186
+ summary: Logic to push phpipam configuration to a dnsmasq configuration
187
+ test_files: []