smart_proxy_ipam 0.0.4 → 0.0.5
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 +4 -4
- data/README.md +7 -3
- data/lib/smart_proxy_ipam/ipam_http_config.ru +1 -6
- data/lib/smart_proxy_ipam/phpipam/phpipam_api.rb +149 -31
- data/lib/smart_proxy_ipam/phpipam/phpipam_client.rb +80 -14
- data/lib/smart_proxy_ipam/version.rb +1 -1
- data/settings.d/external_ipam.yml +0 -4
- data/settings.d/external_ipam.yml.example +0 -4
- metadata +2 -3
- data/lib/smart_proxy_ipam/ipam/ipam_api.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f64f77c875cf2954bfe2d9fb2e1c56e1848e402ec8259959382771da8cd7158b
|
4
|
+
data.tar.gz: a4e3900fd2ad8a2ec16e9ab3887dd6412ce567b16f7cdb98278407c80add8e9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3608be9d60dda80356bdf9e9c59f79cf0edcd1c69210cb7c10aa818237ec85e1485e8fd12d2ee1c1d527ca3ab926d1090ef20c2a6bc4faf8f2c4b262f86df44c
|
7
|
+
data.tar.gz: a99d59aab8ce7b3f1a1b6d4b90e861fef90435c9071e0b42d3f7863834a660050d8e96af471473b4e6f0a0b8db8b1f1d212502e01ac80073e79a1542d731fff6
|
data/README.md
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
#
|
1
|
+
# smart_proxy_ipam
|
2
2
|
|
3
|
-
Foreman Smart Proxy plugin for IPAM integration with
|
3
|
+
Foreman Smart Proxy plugin for IPAM integration with various IPAM providers.
|
4
|
+
|
5
|
+
Currently supported Providers:
|
6
|
+
1. [phpIPAM](https://phpipam.net/).
|
7
|
+
|
8
|
+
Provides a basic Dashboard for viewing phpIPAM sections, subnets. Also supports obtaining of the next available IPv4 address for a given subnet(via [IPAM Smart Proxy Plugin](https://github.com/grizzthedj/smart_proxy_ipam)).
|
4
9
|
|
5
|
-
Used for obtaining the next available IPv4 address from phpIPAM, for a given subnet.
|
6
10
|
|
7
11
|
## Installation
|
8
12
|
|
@@ -3,11 +3,27 @@ require 'smart_proxy_ipam/ipam'
|
|
3
3
|
require 'smart_proxy_ipam/ipam_main'
|
4
4
|
require 'smart_proxy_ipam/phpipam/phpipam_client'
|
5
5
|
|
6
|
+
# TODO: Refactor later to handle multiple IPAM providers. For now, it is
|
7
|
+
# just phpIPAM that is supported
|
6
8
|
module Proxy::Phpipam
|
7
9
|
class Api < ::Sinatra::Base
|
8
10
|
include ::Proxy::Log
|
9
11
|
helpers ::Proxy::Helpers
|
10
12
|
|
13
|
+
get '/providers' do
|
14
|
+
content_type :json
|
15
|
+
{ipam_providers: ['phpIPAM']}.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
# Gets the next available IP address based on a given subnet
|
19
|
+
#
|
20
|
+
# Input: cidr(string): CIDR address in the format: "100.20.20.0/24"
|
21
|
+
# Returns: Hash with "next_ip", or hash with "error"
|
22
|
+
# Examples:
|
23
|
+
# Response if success:
|
24
|
+
# {"cidr":"100.20.20.0/24","next_ip":"100.20.20.11"}
|
25
|
+
# Response if error:
|
26
|
+
# {"error":"The specified subnet does not exist in phpIPAM."}
|
11
27
|
get '/next_ip' do
|
12
28
|
content_type :json
|
13
29
|
|
@@ -22,10 +38,10 @@ module Proxy::Phpipam
|
|
22
38
|
response = phpipam_client.get_subnet(cidr)
|
23
39
|
|
24
40
|
if response['message'] && response['message'].downcase == "no subnets found"
|
25
|
-
return {error: "The specified subnet does not exist in
|
41
|
+
return {error: "The specified subnet does not exist in External IPAM."}.to_json
|
26
42
|
end
|
27
43
|
|
28
|
-
subnet_id = response[
|
44
|
+
subnet_id = JSON.parse(response)[0]['id']
|
29
45
|
response = phpipam_client.get_next_ip(subnet_id)
|
30
46
|
|
31
47
|
if response['message'] && response['message'].downcase == "no free addresses found"
|
@@ -34,10 +50,29 @@ module Proxy::Phpipam
|
|
34
50
|
|
35
51
|
{cidr: cidr, next_ip: response['data']}.to_json
|
36
52
|
rescue Errno::ECONNREFUSED
|
37
|
-
return {error: "Unable to connect to
|
53
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
38
54
|
end
|
39
55
|
end
|
40
56
|
|
57
|
+
# Gets the subnet from phpIPAM
|
58
|
+
#
|
59
|
+
# Input: cidr(string): CIDR address in the format: "100.20.20.0/24"
|
60
|
+
# Returns: JSON with "data" key on success, or JSON with "error" key when there is an error
|
61
|
+
# Examples:
|
62
|
+
# Response if subnet exists:
|
63
|
+
# {
|
64
|
+
# "code":200,"success":true,"data":[{"id":"12","subnet":"100.30.30.0","mask":"24",
|
65
|
+
# "sectionId":"5", "description":"Test Subnet","linked_subnet":null,"firewallAddressObject":null,
|
66
|
+
# "vrfId":"0","masterSubnetId":"0","allowRequests":"0","vlanId":"0","showName":"0","device":"0",
|
67
|
+
# "permissions":"[]","pingSubnet":"0","discoverSubnet":"0","DNSrecursive":"0","DNSrecords":"0",
|
68
|
+
# "nameserverId":"0","scanAgent":"0","isFolder":"0","isFull":"0","tag":"2","threshold":"0",
|
69
|
+
# "location":"0","editDate":null,"lastScan":null,"lastDiscovery":null}],"time":0.009
|
70
|
+
# }
|
71
|
+
#
|
72
|
+
# Response if subnet not exists):
|
73
|
+
# {
|
74
|
+
# "code":200,"success":0,"message":"No subnets found","time":0.01
|
75
|
+
# }
|
41
76
|
get '/get_subnet' do
|
42
77
|
content_type :json
|
43
78
|
|
@@ -52,10 +87,22 @@ module Proxy::Phpipam
|
|
52
87
|
subnet = phpipam_client.get_subnet(cidr)
|
53
88
|
subnet.to_json
|
54
89
|
rescue Errno::ECONNREFUSED
|
55
|
-
return {error: "Unable to connect to
|
90
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
56
91
|
end
|
57
92
|
end
|
58
93
|
|
94
|
+
# Get a list of sections from external ipam
|
95
|
+
#
|
96
|
+
# Input: None
|
97
|
+
# Returns: An array of sections on success, hash with "error" key otherwise
|
98
|
+
# Examples
|
99
|
+
# Response if success: [
|
100
|
+
# {"id":"5","name":"Awesome Section","description":"A totally awesome Section","masterSection":"0",
|
101
|
+
# "permissions":"[]","strictMode":"1","subnetOrdering":"default","order":null,
|
102
|
+
# "editDate":"2019-04-19 21:49:55","showVLAN":"1","showVRF":"1","showSupernetOnly":"1","DNS":null}]
|
103
|
+
# ]
|
104
|
+
# Response if error:
|
105
|
+
# {"error":"Unable to connect to phpIPAM server"}
|
59
106
|
get '/sections' do
|
60
107
|
content_type :json
|
61
108
|
|
@@ -64,10 +111,65 @@ module Proxy::Phpipam
|
|
64
111
|
sections = phpipam_client.get_sections
|
65
112
|
sections.to_json
|
66
113
|
rescue Errno::ECONNREFUSED
|
67
|
-
return {error: "Unable to connect to
|
114
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
68
115
|
end
|
69
116
|
end
|
70
117
|
|
118
|
+
# Get a list of subnets for given external ipam section
|
119
|
+
#
|
120
|
+
# Input: section_id(integer). The id of the external ipam section
|
121
|
+
# Returns: Array of subnets(as json) in "data" key on success, hash with error otherwise
|
122
|
+
# Examples:
|
123
|
+
# Response if success:
|
124
|
+
# {
|
125
|
+
# "code":200,
|
126
|
+
# "success":true,
|
127
|
+
# "data":[
|
128
|
+
# {
|
129
|
+
# "id":"24",
|
130
|
+
# "subnet":"100.10.10.0",
|
131
|
+
# "mask":"24",
|
132
|
+
# "sectionId":"10",
|
133
|
+
# "description":"wrgwgwefwefw",
|
134
|
+
# "linked_subnet":null,
|
135
|
+
# "firewallAddressObject":null,
|
136
|
+
# "vrfId":"0",
|
137
|
+
# "masterSubnetId":"0",
|
138
|
+
# "allowRequests":"0",
|
139
|
+
# "vlanId":"0",
|
140
|
+
# "showName":"0",
|
141
|
+
# "device":"0",
|
142
|
+
# "permissions":"[]",
|
143
|
+
# "pingSubnet":"0",
|
144
|
+
# "discoverSubnet":"0",
|
145
|
+
# "DNSrecursive":"0",
|
146
|
+
# "DNSrecords":"0",
|
147
|
+
# "nameserverId":"0",
|
148
|
+
# "scanAgent":"0",
|
149
|
+
# "isFolder":"0",
|
150
|
+
# "isFull":"0",
|
151
|
+
# "tag":"2",
|
152
|
+
# "threshold":"0",
|
153
|
+
# "location":"0",
|
154
|
+
# "editDate":null,
|
155
|
+
# "lastScan":null,
|
156
|
+
# "lastDiscovery":null,
|
157
|
+
# "usage":{
|
158
|
+
# "used":"0",
|
159
|
+
# "maxhosts":"254",
|
160
|
+
# "freehosts":"254",
|
161
|
+
# "freehosts_percent":100,
|
162
|
+
# "Offline_percent":0,
|
163
|
+
# "Used_percent":0,
|
164
|
+
# "Reserved_percent":0,
|
165
|
+
# "DHCP_percent":0
|
166
|
+
# }
|
167
|
+
# }
|
168
|
+
# ],
|
169
|
+
# "time":0.012
|
170
|
+
# }
|
171
|
+
# Response if error:
|
172
|
+
# {"error":"Unable to connect to phpIPAM server"}
|
71
173
|
get '/sections/:section_id/subnets' do
|
72
174
|
content_type :json
|
73
175
|
|
@@ -82,10 +184,20 @@ module Proxy::Phpipam
|
|
82
184
|
subnets = phpipam_client.get_subnets(section_id)
|
83
185
|
subnets.to_json
|
84
186
|
rescue Errno::ECONNREFUSED
|
85
|
-
return {error: "Unable to connect to
|
187
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
86
188
|
end
|
87
189
|
end
|
88
190
|
|
191
|
+
# Checks whether an IP address has already been taken in external ipam.
|
192
|
+
#
|
193
|
+
# Inputs: 1. ip(string). IP address to be checked.
|
194
|
+
# 2. cidr(string): CIDR address in the format: "100.20.20.0/24"
|
195
|
+
# Returns: JSON object with 'exists' field being either true or false
|
196
|
+
# Example:
|
197
|
+
# Response if exists:
|
198
|
+
# {"ip":"100.20.20.18","exists":true}
|
199
|
+
# Response if not exists:
|
200
|
+
# {"ip":"100.20.20.18","exists":false}
|
89
201
|
get '/ip_exists' do
|
90
202
|
content_type :json
|
91
203
|
|
@@ -100,31 +212,27 @@ module Proxy::Phpipam
|
|
100
212
|
subnet = phpipam_client.get_subnet(cidr)
|
101
213
|
|
102
214
|
if subnet['message'] && subnet['message'].downcase == "no subnets found"
|
103
|
-
return {error: "The specified subnet does not exist in
|
215
|
+
return {error: "The specified subnet does not exist in External IPAM."}.to_json
|
104
216
|
end
|
105
217
|
|
106
|
-
subnet_id = subnet[
|
107
|
-
|
108
|
-
|
109
|
-
# We need to check subnet usage first in the case there are zero ips in the subnet. Checking
|
110
|
-
# the ip existence on an empty subnet returns a malformed response from phpIPAM, containing
|
111
|
-
# HTML in the JSON response.
|
112
|
-
if usage['data']['used'] == "0"
|
113
|
-
return {ip: ip, exists: false}.to_json
|
114
|
-
else
|
115
|
-
response = phpipam_client.ip_exists(ip, subnet_id)
|
116
|
-
|
117
|
-
if response && response['message'] && response['message'].downcase == 'no addresses found'
|
118
|
-
return {ip: ip, exists: false}.to_json
|
119
|
-
else
|
120
|
-
return {ip: ip, exists: true}.to_json
|
121
|
-
end
|
122
|
-
end
|
218
|
+
subnet_id = JSON.parse(subnet)[0]['id']
|
219
|
+
phpipam_client.ip_exists(ip, subnet_id)
|
123
220
|
rescue Errno::ECONNREFUSED
|
124
|
-
return {error: "Unable to connect to
|
221
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
125
222
|
end
|
126
223
|
end
|
127
224
|
|
225
|
+
# Adds an IP address to the specified subnet
|
226
|
+
#
|
227
|
+
# Inputs: 1. ip(string). IP address to be added.
|
228
|
+
# 2. subnet_id(integer). The id of the external ipam subnet
|
229
|
+
# 3. description(string). IP address description
|
230
|
+
# Returns: Hash with "message" on success, or hash with "error"
|
231
|
+
# Examples:
|
232
|
+
# Response if success:
|
233
|
+
# {"message":"IP 100.10.10.123 added to subnet 100.10.10.0/24 successfully."}
|
234
|
+
# Response if error:
|
235
|
+
# {"error":"The specified subnet does not exist in phpIPAM."}
|
128
236
|
post '/add_ip_to_subnet' do
|
129
237
|
content_type :json
|
130
238
|
|
@@ -139,19 +247,29 @@ module Proxy::Phpipam
|
|
139
247
|
response = phpipam_client.get_subnet(cidr)
|
140
248
|
|
141
249
|
if response['message'] && response['message'].downcase == "no subnets found"
|
142
|
-
return {error: "The specified subnet does not exist in
|
250
|
+
return {error: "The specified subnet does not exist in External IPAM."}.to_json
|
143
251
|
end
|
144
252
|
|
145
|
-
subnet_id = response[
|
253
|
+
subnet_id = JSON.parse(response)[0]['id']
|
146
254
|
|
147
255
|
phpipam_client.add_ip_to_subnet(ip, subnet_id, 'Address auto added by Foreman')
|
148
256
|
|
149
257
|
{message: "IP #{ip} added to subnet #{cidr} successfully."}.to_json
|
150
258
|
rescue Errno::ECONNREFUSED
|
151
|
-
return {error: "Unable to connect to
|
259
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
152
260
|
end
|
153
261
|
end
|
154
262
|
|
263
|
+
# Deletes IP address from a given subnet
|
264
|
+
#
|
265
|
+
# Inputs: 1. ip(string). IP address to be checked.
|
266
|
+
# 2. cidr(string): CIDR address in the format: "100.20.20.0/24"
|
267
|
+
# Returns: JSON object
|
268
|
+
# Example:
|
269
|
+
# Response if success:
|
270
|
+
# {"code": 200, "success": true, "message": "Address deleted", "time": 0.017}
|
271
|
+
# Response if error:
|
272
|
+
# {"code": 404, "success": 0, "message": "Address does not exist", "time": 0.008}
|
155
273
|
post '/delete_ip_from_subnet' do
|
156
274
|
content_type :json
|
157
275
|
|
@@ -166,16 +284,16 @@ module Proxy::Phpipam
|
|
166
284
|
response = phpipam_client.get_subnet(cidr)
|
167
285
|
|
168
286
|
if response['message'] && response['message'].downcase == "no subnets found"
|
169
|
-
return {error: "The specified subnet does not exist in
|
287
|
+
return {error: "The specified subnet does not exist in External IPAM."}.to_json
|
170
288
|
end
|
171
289
|
|
172
|
-
subnet_id = response[
|
290
|
+
subnet_id = JSON.parse(response)[0]['id']
|
173
291
|
|
174
292
|
phpipam_client.delete_ip_from_subnet(ip, subnet_id)
|
175
293
|
|
176
294
|
{message: "IP #{ip} deleted from subnet #{cidr} successfully."}.to_json
|
177
295
|
rescue Errno::ECONNREFUSED
|
178
|
-
return {error: "Unable to connect to
|
296
|
+
return {error: "Unable to connect to External IPAM server"}.to_json
|
179
297
|
end
|
180
298
|
end
|
181
299
|
|
@@ -6,22 +6,40 @@ require 'smart_proxy_ipam/ipam'
|
|
6
6
|
require 'smart_proxy_ipam/ipam_main'
|
7
7
|
|
8
8
|
module Proxy::Phpipam
|
9
|
-
class PhpipamClient
|
9
|
+
class PhpipamClient
|
10
10
|
def initialize
|
11
11
|
conf = Proxy::Ipam.get_config[:phpipam]
|
12
12
|
@phpipam_config = {url: conf[:url], user: conf[:user], password: conf[:password]}
|
13
|
-
@api_base = conf[:url]
|
13
|
+
@api_base = "#{conf[:url]}/api/#{conf[:user]}/"
|
14
14
|
@token = nil
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
19
|
-
get(url)
|
17
|
+
def init_reservations
|
18
|
+
@@ipam_reservations = {}
|
20
19
|
end
|
21
20
|
|
22
|
-
def
|
23
|
-
url =
|
24
|
-
get(url)
|
21
|
+
def get_subnet(cidr)
|
22
|
+
url = "subnets/cidr/#{cidr.to_s}"
|
23
|
+
subnets = get(url)
|
24
|
+
response = []
|
25
|
+
|
26
|
+
if subnets
|
27
|
+
if subnets['message'] && subnets['message'].downcase == 'no subnets found'
|
28
|
+
return {"message": "no subnets found"}.to_json
|
29
|
+
else
|
30
|
+
# Only return the relevant fields to Foreman
|
31
|
+
subnets['data'].each do |subnet|
|
32
|
+
response.push({
|
33
|
+
"id": subnet['id'],
|
34
|
+
"subnet": subnet['subnet'],
|
35
|
+
"description": subnet['description'],
|
36
|
+
"mask": subnet['mask']
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
return response.to_json
|
41
|
+
end
|
42
|
+
end
|
25
43
|
end
|
26
44
|
|
27
45
|
def add_ip_to_subnet(ip, subnet_id, desc)
|
@@ -30,26 +48,74 @@ module Proxy::Phpipam
|
|
30
48
|
end
|
31
49
|
|
32
50
|
def get_sections
|
33
|
-
get('sections/')['data']
|
51
|
+
sections = get('sections/')['data']
|
52
|
+
response = []
|
53
|
+
|
54
|
+
if sections
|
55
|
+
sections.each do |section|
|
56
|
+
response.push({
|
57
|
+
"id": section['id'],
|
58
|
+
"name": section['name'],
|
59
|
+
"description": section['description']
|
60
|
+
})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
response
|
34
65
|
end
|
35
66
|
|
36
67
|
def get_subnets(section_id)
|
37
|
-
get(
|
68
|
+
subnets = get("sections/#{section_id.to_s}/subnets/")
|
69
|
+
response = []
|
70
|
+
|
71
|
+
if subnets && subnets['data']
|
72
|
+
# Only return the relevant data
|
73
|
+
subnets['data'].each do |subnet|
|
74
|
+
response.push({
|
75
|
+
"id": subnet['id'],
|
76
|
+
"subnet": subnet['subnet'],
|
77
|
+
"mask": subnet['mask'],
|
78
|
+
"sectionId": subnet['sectionId'],
|
79
|
+
"description": subnet['description']
|
80
|
+
})
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
response
|
38
85
|
end
|
39
86
|
|
40
87
|
def ip_exists(ip, subnet_id)
|
41
|
-
|
88
|
+
usage = get_subnet_usage(subnet_id)
|
89
|
+
|
90
|
+
# We need to check subnet usage first in the case there are zero ips in the subnet. Checking
|
91
|
+
# the ip existence on an empty subnet returns a malformed response from phpIPAM, containing
|
92
|
+
# HTML in the JSON response.
|
93
|
+
if usage['data']['used'] == "0"
|
94
|
+
return {ip: ip, exists: false}.to_json
|
95
|
+
else
|
96
|
+
response = get("subnets/#{subnet_id.to_s}/addresses/#{ip}/")
|
97
|
+
|
98
|
+
if response && response['message'] && response['message'].downcase == 'no addresses found'
|
99
|
+
return {ip: ip, exists: false}.to_json
|
100
|
+
else
|
101
|
+
return {ip: ip, exists: true}.to_json
|
102
|
+
end
|
103
|
+
end
|
42
104
|
end
|
43
105
|
|
106
|
+
|
44
107
|
def get_subnet_usage(subnet_id)
|
45
|
-
get(
|
108
|
+
get("subnets/#{subnet_id.to_s}/usage/")
|
46
109
|
end
|
47
110
|
|
48
111
|
def delete_ip_from_subnet(ip, subnet_id)
|
49
|
-
delete(
|
112
|
+
delete("addresses/#{ip}/#{subnet_id.to_s}/")
|
50
113
|
end
|
51
114
|
|
52
|
-
|
115
|
+
def get_next_ip(subnet_id)
|
116
|
+
url = "subnets/#{subnet_id.to_s}/first_free/"
|
117
|
+
get(url)
|
118
|
+
end
|
53
119
|
|
54
120
|
def get(path, body=nil)
|
55
121
|
authenticate
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: smart_proxy_ipam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-07-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Smart proxy plugin for IPAM integration with various IPAM providers
|
14
14
|
email: chrisjsmith001@gmail.com
|
@@ -23,7 +23,6 @@ files:
|
|
23
23
|
- bundler.d/ipam.rb
|
24
24
|
- lib/smart_proxy_ipam.rb
|
25
25
|
- lib/smart_proxy_ipam/ipam.rb
|
26
|
-
- lib/smart_proxy_ipam/ipam/ipam_api.rb
|
27
26
|
- lib/smart_proxy_ipam/ipam_http_config.ru
|
28
27
|
- lib/smart_proxy_ipam/ipam_main.rb
|
29
28
|
- lib/smart_proxy_ipam/phpipam/phpipam_api.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require 'smart_proxy_ipam/ipam'
|
3
|
-
require 'smart_proxy_ipam/ipam_main'
|
4
|
-
|
5
|
-
module Proxy::Ipam
|
6
|
-
class Api < ::Sinatra::Base
|
7
|
-
include ::Proxy::Log
|
8
|
-
helpers ::Proxy::Helpers
|
9
|
-
|
10
|
-
get '/providers' do
|
11
|
-
content_type :json
|
12
|
-
{ipam_providers: ['phpIPAM']}.to_json
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|