construqt 0.0.1
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 +7 -0
- data/lib/construqt/addresses.rb +204 -0
- data/lib/construqt/bgps.rb +164 -0
- data/lib/construqt/cables.rb +47 -0
- data/lib/construqt/firewalls.rb +247 -0
- data/lib/construqt/flavour/ciscian/ciscian.rb +687 -0
- data/lib/construqt/flavour/ciscian/dialect_dlink-dgs15xx.rb +235 -0
- data/lib/construqt/flavour/ciscian/dialect_hp-2510g.rb +114 -0
- data/lib/construqt/flavour/delegates.rb +448 -0
- data/lib/construqt/flavour/flavour.rb +97 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik.rb +417 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_bgp.rb +134 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_interface.rb +79 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_ipsec.rb +65 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_result.rb +182 -0
- data/lib/construqt/flavour/mikrotik/flavour_mikrotik_schema.rb +355 -0
- data/lib/construqt/flavour/plantuml/plantuml.rb +462 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu.rb +381 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_bgp.rb +117 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_dns.rb +97 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_firewall.rb +300 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_ipsec.rb +144 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_opvn.rb +60 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_result.rb +537 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_services.rb +115 -0
- data/lib/construqt/flavour/ubuntu/flavour_ubuntu_vrrp.rb +52 -0
- data/lib/construqt/flavour/unknown/unknown.rb +175 -0
- data/lib/construqt/hostid.rb +42 -0
- data/lib/construqt/hosts.rb +98 -0
- data/lib/construqt/interfaces.rb +166 -0
- data/lib/construqt/ipsecs.rb +64 -0
- data/lib/construqt/networks.rb +81 -0
- data/lib/construqt/regions.rb +32 -0
- data/lib/construqt/resource.rb +42 -0
- data/lib/construqt/services.rb +53 -0
- data/lib/construqt/tags.rb +61 -0
- data/lib/construqt/templates.rb +37 -0
- data/lib/construqt/tests/test_addresses.rb +50 -0
- data/lib/construqt/tests/test_bgps.rb +24 -0
- data/lib/construqt/tests/test_hostid.rb +32 -0
- data/lib/construqt/tests/test_hosts.rb +23 -0
- data/lib/construqt/tests/test_utils.rb +76 -0
- data/lib/construqt/users.rb +19 -0
- data/lib/construqt/util.rb +163 -0
- data/lib/construqt/version.rb +3 -0
- data/lib/construqt/vlans.rb +51 -0
- data/lib/construqt.rb +92 -0
- metadata +105 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module Construqt
|
2
|
+
class Services
|
3
|
+
|
4
|
+
class DhcpV4Relay
|
5
|
+
attr_accessor :servers, :name
|
6
|
+
def initialize(name)
|
7
|
+
self.name = name
|
8
|
+
self.servers = []
|
9
|
+
end
|
10
|
+
def add_server(ip)
|
11
|
+
ip = IPAddress.parse(ip)
|
12
|
+
throw "ip must be a v4 address" unless ip.ipv4?
|
13
|
+
self.servers << ip
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class DhcpV6Relay
|
18
|
+
attr_accessor :servers, :name
|
19
|
+
def initialize(name)
|
20
|
+
self.name = name
|
21
|
+
self.servers = []
|
22
|
+
end
|
23
|
+
def add_server(ip)
|
24
|
+
ip = IPAddress.parse(ip)
|
25
|
+
throw "ip must be a v6 address" unless ip.ipv6?
|
26
|
+
self.servers << ip
|
27
|
+
self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
class Radvd
|
31
|
+
attr_accessor :servers, :name
|
32
|
+
def initialize(name)
|
33
|
+
self.name = name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize
|
38
|
+
@services = {}
|
39
|
+
end
|
40
|
+
|
41
|
+
def find(name)
|
42
|
+
found = @services[name]
|
43
|
+
throw "service with name #{name} not found" unless found
|
44
|
+
found
|
45
|
+
end
|
46
|
+
|
47
|
+
def add(service)
|
48
|
+
@services[service.name] = service
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
module Construqt
|
3
|
+
module Tags
|
4
|
+
@tags = {}
|
5
|
+
@object_id_tags = {}
|
6
|
+
def self.add(tag_str, &block)
|
7
|
+
(name, *tags) = tag_str.split(/\s*#\s*/)
|
8
|
+
obj = block.call(name, tags)
|
9
|
+
#binding.pry
|
10
|
+
tags && tags.uniq.each do |tag|
|
11
|
+
@tags[tag] ||= []
|
12
|
+
@tags[tag] << obj unless @tags[tag].include?(obj)
|
13
|
+
end
|
14
|
+
if obj.respond_to? :tags
|
15
|
+
obj.tags = tags
|
16
|
+
end
|
17
|
+
@object_id_tags[obj.object_id] ||= []
|
18
|
+
@object_id_tags[obj.object_id] = (@object_id_tags[obj.object_id] + tags).uniq
|
19
|
+
[name, obj]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from(obj)
|
23
|
+
@object_id_tags[obj.object_id]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.find(tag, clazz = nil)
|
27
|
+
#binding.pry
|
28
|
+
ret = (@tags[tag] || []).select{|o| clazz.nil? || o.kind_of?(clazz) }
|
29
|
+
Construqt.logger.warn("tag #{tag} #{clazz.inspect} empty result") if ret.empty?
|
30
|
+
ret
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.ips_net(tag, family)
|
34
|
+
ip_module = family==Construqt::Addresses::IPV4 ? IPAddress::IPv4: IPAddress::IPv6
|
35
|
+
IPAddress::IPv4::summarize(*(@tags[tag]||[]).map do |obj|
|
36
|
+
if obj.kind_of?(IPAddress)
|
37
|
+
obj
|
38
|
+
elsif obj.respond_to? :ips
|
39
|
+
obj.ips
|
40
|
+
elsif obj.kind_of?(Construqt::Flavour::HostDelegate)
|
41
|
+
#binding.pry
|
42
|
+
res = obj.interfaces.values.map do |i|
|
43
|
+
i.delegate.address.ips.map do |a|
|
44
|
+
prefix = a.ipv4? ? 32 : 128
|
45
|
+
ret = IPAddress.parse("#{a.to_s}/#{prefix}")
|
46
|
+
puts "ADR=#{tag} #{ret.to_string} #{a.to_s}"
|
47
|
+
ret
|
48
|
+
end
|
49
|
+
end.flatten
|
50
|
+
puts "HOST=>#{tag} #{res.map{|i| i.to_string }}"
|
51
|
+
res
|
52
|
+
else
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end.flatten.compact.select do |i|
|
56
|
+
(family==Construqt::Addresses::IPV4 && i.ipv4?) ||
|
57
|
+
(family==Construqt::Addresses::IPV6 && i.ipv6?)
|
58
|
+
end)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module Construqt
|
3
|
+
class Templates
|
4
|
+
def initialize(region)
|
5
|
+
@region = region
|
6
|
+
@templates = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
class Template < OpenStruct
|
10
|
+
def initialize(cfg)
|
11
|
+
super(cfg)
|
12
|
+
end
|
13
|
+
|
14
|
+
def is_tagged?(vlan_id)
|
15
|
+
self.vlans.each do |vlan|
|
16
|
+
return vlan.tagged? if vlan.vlan_id == vlan_id
|
17
|
+
end
|
18
|
+
|
19
|
+
throw "vlan with id #{vlan_id} not found in template #{self}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def find(name)
|
24
|
+
ret = @templates[name]
|
25
|
+
throw "template with name #{name} not found" unless @templates[name]
|
26
|
+
ret
|
27
|
+
end
|
28
|
+
|
29
|
+
def add(name, cfg)
|
30
|
+
throw "template with name #{name} exists" if @templates[name]
|
31
|
+
cfg['name'] = name
|
32
|
+
ret = Template.new(cfg)
|
33
|
+
@templates[name] = ret
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
addresses = Construqt::Addresses.new(7)
|
3
|
+
|
4
|
+
assert_eq(addresses.network, 7)
|
5
|
+
|
6
|
+
adr = addresses.create
|
7
|
+
|
8
|
+
assert_eq(addresses.all.length, 0)
|
9
|
+
|
10
|
+
adr.set_name("jojo")
|
11
|
+
assert_eq(adr.name, "jojo")
|
12
|
+
|
13
|
+
adr.name = "jojojo"
|
14
|
+
assert_eq(adr.name, "jojojo")
|
15
|
+
|
16
|
+
adr.add_ip("192.168.0.1")
|
17
|
+
assert_eq(adr.all.length, 1)
|
18
|
+
assert_eq(adr.v4s.length, 1)
|
19
|
+
assert_eq(adr.v6s.length, 0)
|
20
|
+
|
21
|
+
adr.add_ip("192.168.0.2")
|
22
|
+
assert_eq(adr.all.length, 2)
|
23
|
+
assert_eq(adr.v4s.length, 2)
|
24
|
+
assert_eq(adr.v6s.length, 0)
|
25
|
+
|
26
|
+
adr.add_ip("2000::/27")
|
27
|
+
assert_eq(adr.all.length, 3)
|
28
|
+
assert_eq(adr.v4s.length, 2)
|
29
|
+
assert_eq(adr.v6s.length, 1)
|
30
|
+
|
31
|
+
adr.add_ip("2001::/27")
|
32
|
+
assert_eq(adr.all.length, 4)
|
33
|
+
assert_eq(adr.v4s.length, 2)
|
34
|
+
assert_eq(adr.v6s.length, 2)
|
35
|
+
|
36
|
+
assert_eq(adr.first_ipv4, "192.168.0.1")
|
37
|
+
assert_eq(adr.first_ipv6, "2001::/27")
|
38
|
+
|
39
|
+
assert_eq(adr.dhcpv4?, false)
|
40
|
+
adr.add_ip(DHCPV4)
|
41
|
+
assert_eq(adr.dhcpv4?, true)
|
42
|
+
|
43
|
+
assert_eq(adr.dhcpv6?, false)
|
44
|
+
adr.add_ip(DHCPV6)
|
45
|
+
assert_eq(adr.dhcpv6?, true)
|
46
|
+
|
47
|
+
assert_eq(adr.loopback?, false)
|
48
|
+
adr.add_ip(LOOPBACK)
|
49
|
+
assert_eq(adr.loopback?, true)
|
50
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
Construqt::Bgps.add_as(93925993, "redistribute-connected" => true,
|
3
|
+
"redistribute-static" => true,
|
4
|
+
"redistribute-other-bgp" => true,
|
5
|
+
"description" => "test-93925993")
|
6
|
+
|
7
|
+
Construqt::Bgps.add_as(73925993, "redistribute-connected" => true,
|
8
|
+
"redistribute-static" => true,
|
9
|
+
"redistribute-other-bgp" => true,
|
10
|
+
"description" => "test-73925993")
|
11
|
+
|
12
|
+
Construqt::Bgps.connection("name_it",
|
13
|
+
"password" => "geheim",
|
14
|
+
"left" => {
|
15
|
+
"as" => Construqt::Bgps::find_as(93925993),
|
16
|
+
"my" => ipsec.left.interface,
|
17
|
+
"filter" => { "in" => Construqt::Bgps.find_filter('mgmt_net_in'), "out" => Construqt::Bgps.find_filter('mgmt_net_out') },
|
18
|
+
},
|
19
|
+
"right" => {
|
20
|
+
"as" => Construqt::Bgps::find_as(73925993),
|
21
|
+
"my" => ipsec.right.interface,
|
22
|
+
"filter" => { "in" => Construqt::Bgps.find_filter('mgmt_net_in'), "out" => Construqt::Bgps.find_filter('mgmt_net_out') },
|
23
|
+
}
|
24
|
+
)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
id = Construqt::HostId.create do |block|
|
4
|
+
assert_eq(block.interfaces.length, 0)
|
5
|
+
end
|
6
|
+
|
7
|
+
assert_eq(id.first_ipv6!, nil)
|
8
|
+
assert_eq(id.first_ipv4!, nil)
|
9
|
+
|
10
|
+
begin
|
11
|
+
id.first_ipv4
|
12
|
+
assert("should not happend")
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
id.first_ipv6
|
18
|
+
assert("should not happend")
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
|
22
|
+
iface = XXXXX
|
23
|
+
id = Construqt::HostId.create do |block|
|
24
|
+
assert_eq(block.interfaces.length, 0)
|
25
|
+
block.interfaces << iface
|
26
|
+
end
|
27
|
+
|
28
|
+
assert_eq(id.first_ipv6!, iface.first_ipv6)
|
29
|
+
assert_eq(id.first_ipv4!, iface.first_ipv4)
|
30
|
+
|
31
|
+
assert_eq(id.first_ipv6, iface.first_ipv6)
|
32
|
+
assert_eq(id.first_ipv4, iface.first_ipv4)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
hosts = Hosts.new(19)
|
3
|
+
|
4
|
+
assert_eq(hosts.region, 19)
|
5
|
+
|
6
|
+
hosts.set_default_password("9339")
|
7
|
+
assert_eq(hosts.default_password, "9339")
|
8
|
+
|
9
|
+
assert_eq(hosts.get_hosts.length, 0)
|
10
|
+
|
11
|
+
begin
|
12
|
+
hosts.add("test", "lutz" => "fuchs") do |host|
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
hosts.add("test", "lutz" => "fuchs") do |host|
|
18
|
+
end
|
19
|
+
assert("Should not happend")
|
20
|
+
raise
|
21
|
+
end
|
22
|
+
|
23
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
class Test
|
3
|
+
include Chainable
|
4
|
+
#def initialize
|
5
|
+
# puts ">>>test instance=#{"%x"%self.object_id} class=#{"%x"%self.class.object_id}"
|
6
|
+
#end
|
7
|
+
attr_reader :sideeffect
|
8
|
+
chainable_attr :bloed0
|
9
|
+
chainable_attr :bloed1
|
10
|
+
chainable_attr :test, 1, 2
|
11
|
+
chainable_attr :testbool, false, true
|
12
|
+
chainable_attr :testbool2, true, true
|
13
|
+
chainable_attr :testside, 1, 2, lambda {|i| @sideeffect ||= 9; @sideeffect += 1 }
|
14
|
+
end
|
15
|
+
class Test2
|
16
|
+
include Chainable
|
17
|
+
#def initialize
|
18
|
+
# puts ">>>test instance=#{"%x"%self.object_id} class=#{"%x"%self.class.object_id}"
|
19
|
+
#end
|
20
|
+
attr_reader :sideeffect
|
21
|
+
chainable_attr :bloed0
|
22
|
+
chainable_attr :bloed1
|
23
|
+
chainable_attr :test, 3, 4
|
24
|
+
chainable_attr :testbool, true, false
|
25
|
+
chainable_attr :testside, 3, 4, lambda {|i| @sideeffect ||= 5; @sideeffect += 1 }
|
26
|
+
end
|
27
|
+
def self.test
|
28
|
+
3.times do |i|
|
29
|
+
t = Test.new
|
30
|
+
#throw "chainable failed input_only" unless t.input_only? == true
|
31
|
+
#throw "chainable failed output_only" unless t.output_only? == true
|
32
|
+
|
33
|
+
#puts "#{i}=>#{t.testbool?} #{t.testbool2?}"
|
34
|
+
throw "chainable failed test should 2 #{t.get_test.inspect}" if t.get_test != 2
|
35
|
+
t.test
|
36
|
+
throw "chainable failed this should be 1 " if t.get_test != 1
|
37
|
+
t.test(3)
|
38
|
+
throw "chainable failed" if t.get_test != 3
|
39
|
+
|
40
|
+
throw "chainable failed test should 2 #{t.get_testside.inspect}" if t.get_testside != 2
|
41
|
+
throw "chainable failed sideeffect should 1 nil #{t.sideeffect.inspect}" if !t.sideeffect.nil?
|
42
|
+
t.testside
|
43
|
+
throw "chainable failed this should be 1 " if t.get_testside != 1
|
44
|
+
throw "chainable failed sideeffect should 2 nil #{t.sideeffect.inspect}" if t.sideeffect != 10
|
45
|
+
t.testside(3)
|
46
|
+
throw "chainable failed" if t.get_testside != 3
|
47
|
+
throw "chainable failed sideeffect should 2 nil #{t.sideeffect.inspect}" if t.sideeffect != 11
|
48
|
+
|
49
|
+
throw "chainable failed true" unless t.testbool? == true
|
50
|
+
t.testbool
|
51
|
+
throw "chainable failed false" unless t.testbool? == false
|
52
|
+
t.testbool(4)
|
53
|
+
throw "chainable failed 4" unless t.testbool? == 4
|
54
|
+
t.testbool
|
55
|
+
throw "chainable failed false" unless t.testbool? == false
|
56
|
+
|
57
|
+
throw "chainable failed 2 true" unless t.testbool2? == true
|
58
|
+
t.testbool2
|
59
|
+
throw "chainable failed 2 false" unless t.testbool2? == true
|
60
|
+
t.testbool2(4)
|
61
|
+
throw "chainable failed 2 4" unless t.testbool2? == 4
|
62
|
+
t.testbool2
|
63
|
+
throw "chainable failed 2 false" unless t.testbool2? == true
|
64
|
+
end
|
65
|
+
a=[Test.new,Test.new,Test.new]
|
66
|
+
a[0].testbool(0)
|
67
|
+
throw "chainable failed 0" unless a[0].testbool? == 0
|
68
|
+
throw "chainable failed 1" unless a[1].testbool? == true
|
69
|
+
a[2].testbool
|
70
|
+
throw "chainable failed 2" unless a[2].testbool? == false
|
71
|
+
|
72
|
+
throw "chainable failed 0" unless a[0].testbool? == 0
|
73
|
+
throw "chainable failed 1" unless a[1].testbool? == true
|
74
|
+
throw "chainable failed 2" unless a[2].testbool? == false
|
75
|
+
end
|
76
|
+
@test = self.test
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Construqt
|
2
|
+
class Users
|
3
|
+
def initialize(region)
|
4
|
+
@region = region
|
5
|
+
@users = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(name, cfg)
|
9
|
+
throw "user exists #{name}" if @users[name]
|
10
|
+
cfg['name'] = name
|
11
|
+
cfg['yubikey'] ||= nil
|
12
|
+
@users[name] = OpenStruct.new(cfg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
@users.values
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Construqt
|
2
|
+
module Util
|
3
|
+
module Chainable
|
4
|
+
|
5
|
+
def self.included(other)
|
6
|
+
#puts "Chainable #{other.name}"
|
7
|
+
other.class.send("define_method", "chainable_attr") do |*args|
|
8
|
+
#puts "chainable_attr:#{self.name} #{args.inspect}"
|
9
|
+
Chainable.chainable_attr(self, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
other.class.send("define_method", "chainable_attr_value") do |*args|
|
13
|
+
#puts "chainable_attr_value:#{self.name} #{args.inspect}"
|
14
|
+
Chainable.chainable_attr_value(self, *args)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.chainable_attr_value(clazz, arg, init = nil)
|
19
|
+
instance_variable_name = "@#{arg}".to_sym
|
20
|
+
self.instance_variable_set(instance_variable_name, init)
|
21
|
+
define_method(arg.to_s) do |val|
|
22
|
+
self.instance_variable_set(instance_variable_name, val)
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method("get_#{arg}") do
|
27
|
+
self.instance_variable_get(instance_variable_name.to_sym)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.chainable_attr(clazz, arg, set_value = true, init = false, aspect = lambda{|i|})
|
32
|
+
instance_variable_name = "@#{arg}".to_sym
|
33
|
+
# puts ">>>chainable_attr #{"%x"%self.object_id} init=#{init}"
|
34
|
+
# self.instance_variable_set(instance_variable_name, init)
|
35
|
+
#puts "self.chainable_attr #{clazz.name} #{arg.to_sym} #{set_value} #{init}"
|
36
|
+
clazz.send("define_method", arg.to_sym) do |*args|
|
37
|
+
instance_eval(&aspect)
|
38
|
+
self.instance_variable_set(instance_variable_name, args.length>0 ? args[0] : set_value)
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
if ((set_value.kind_of?(true.class) || set_value.kind_of?(false.class)) &&
|
43
|
+
(init.kind_of?(true.class) || init.kind_of?(false.class)))
|
44
|
+
get_name = "#{arg}?"
|
45
|
+
else
|
46
|
+
get_name = "get_#{arg}"
|
47
|
+
end
|
48
|
+
|
49
|
+
get_name_proc = Proc.new do
|
50
|
+
unless self.instance_variables.include?(instance_variable_name)
|
51
|
+
#puts "init #{get_name} #{instance_variable_name} #{defined?(instance_variable_name)} #{set_value} #{init}"
|
52
|
+
self.instance_variable_set(instance_variable_name, init)
|
53
|
+
end
|
54
|
+
|
55
|
+
ret = self.instance_variable_get(instance_variable_name)
|
56
|
+
#puts "#{self.class.name} #{get_name} #{set_value} #{init} => #{ret.inspect}"
|
57
|
+
ret
|
58
|
+
end
|
59
|
+
|
60
|
+
clazz.send("define_method", get_name, get_name_proc)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.write_str(str, *path)
|
65
|
+
path = File.join("cfgs", *path)
|
66
|
+
FileUtils.mkdir_p(File.dirname(path))
|
67
|
+
File.open(path, 'w') {|f| f.write(str) }
|
68
|
+
Construqt.logger.info "Write:#{path}"
|
69
|
+
return str
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.password(a)
|
73
|
+
a
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.add_gre_prefix(name)
|
77
|
+
unless name.start_with?("gt")
|
78
|
+
return "gt"+name
|
79
|
+
end
|
80
|
+
|
81
|
+
name
|
82
|
+
end
|
83
|
+
|
84
|
+
@clean_if = []
|
85
|
+
def self.add_clean_ip_pattern(pat)
|
86
|
+
@clean_if << pat
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.clean_if(prefix, name)
|
90
|
+
unless name.start_with?(prefix)
|
91
|
+
name = prefix+name
|
92
|
+
end
|
93
|
+
|
94
|
+
name = name.gsub(/[^a-z0-9]/, '')
|
95
|
+
@clean_if.each { |pat| name.gsub!(pat, '') }
|
96
|
+
name
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.clean_bgp(name)
|
100
|
+
name.gsub(/[^a-z0-9]/, '_')
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.portNeighbors?(port1, port2)
|
104
|
+
port2.succ == port1 || port1.succ == port2
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.createRangeDefinition(ports)
|
108
|
+
ranges=[]
|
109
|
+
lastPort=nil
|
110
|
+
|
111
|
+
#remove duplicates
|
112
|
+
ports.uniq.sort do |l,r|
|
113
|
+
fc = l.to_s.length <=> r.to_s.length
|
114
|
+
fc!=0 ? fc : l<=>r
|
115
|
+
end.each do |port|
|
116
|
+
port = port.to_s
|
117
|
+
if (ranges.length>0 && portNeighbors?(port, ranges[ranges.length-1]["to"]))
|
118
|
+
ranges[ranges.length-1]["to"] = port
|
119
|
+
else
|
120
|
+
ranges << {"from" => port, "to" => port}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
ranges = ranges.map do |range|
|
125
|
+
range["from"] == range["to"] ? range["from"] : range["from"] +"-"+range["to"]
|
126
|
+
end
|
127
|
+
#puts "self.createRangeDefinition[#{ports}]=>#{ranges}"
|
128
|
+
ranges.join(",")
|
129
|
+
end
|
130
|
+
|
131
|
+
PORTS_DEF_REGEXP = "([^\\d\\s]*[\\d,-]+)+"
|
132
|
+
PORT_NAME_REGEXP="^(.*?)(\\d+)$"
|
133
|
+
def self.expandRangeDefinition(list_str)
|
134
|
+
ports = list_str.strip.split(",").map do |range_def|
|
135
|
+
range = range_def.split("-")
|
136
|
+
if (range.length==1)
|
137
|
+
range
|
138
|
+
elsif (range.length==2)
|
139
|
+
range[0]=~/#{PORT_NAME_REGEXP}/
|
140
|
+
prefix_from=$1
|
141
|
+
from = $2
|
142
|
+
range[1]=~/#{PORT_NAME_REGEXP}/
|
143
|
+
prefix_to=$1
|
144
|
+
to = $2
|
145
|
+
throw "port prefixes differ" unless prefix_from==prefix_to
|
146
|
+
(from.to_i .. to.to_i).map {|n| prefix_from + n.to_s }
|
147
|
+
else
|
148
|
+
throw "invalid range found #{range_def}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
ports.flatten
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.generate_mac_address_from_name(name)
|
155
|
+
# http://www.iana.org/assignments/ethernet-numbers/ethernet-numbers.xhtml
|
156
|
+
'8f:'+Digest::SHA256.hexdigest("#{name}").scan(/../)[0,5].join(':')
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.indent(body, ident)
|
160
|
+
body.lines.map { |line| ident+line }.join("\n")
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
|
2
|
+
module Construqt
|
3
|
+
class Vlans
|
4
|
+
def initialize(region)
|
5
|
+
@region = region
|
6
|
+
@vlans_id = {}
|
7
|
+
@vlans_description = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
class Vlan < OpenStruct
|
11
|
+
def initialize(cfg)
|
12
|
+
super(cfg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tagged?
|
16
|
+
@tagged
|
17
|
+
end
|
18
|
+
|
19
|
+
def tagged
|
20
|
+
@tagged=true
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def untagged?
|
25
|
+
!@tagged
|
26
|
+
end
|
27
|
+
|
28
|
+
def untagged
|
29
|
+
@tagged = false
|
30
|
+
self
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(vlan, cfg)
|
35
|
+
throw "vlan has to be a fixnum #{vlan}" unless vlan.kind_of?(Fixnum)
|
36
|
+
throw "vlan need #{vlan} description" unless cfg['description']
|
37
|
+
throw "vlan with id #{vlan} exists" if @vlans_id[vlan]
|
38
|
+
throw "vlan with description #{vlan} exists" if @vlans_description[cfg['description']]
|
39
|
+
cfg['vlan_id'] = vlan
|
40
|
+
ret = Vlan.new(cfg)
|
41
|
+
@vlans_id[vlan] = ret
|
42
|
+
@vlans_description[cfg['description']] = ret
|
43
|
+
ret
|
44
|
+
end
|
45
|
+
|
46
|
+
def clone(key)
|
47
|
+
throw "vlan clone key not found #{key}" unless @vlans_id[key] || @vlans_description[key]
|
48
|
+
(@vlans_id[key] || @vlans_description[key]).clone
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/construqt.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
require 'ipaddress'
|
7
|
+
require 'digest/sha1'
|
8
|
+
require 'digest/md5'
|
9
|
+
require "base64"
|
10
|
+
require 'securerandom'
|
11
|
+
|
12
|
+
|
13
|
+
module Construqt
|
14
|
+
|
15
|
+
@logger = Logger.new(STDOUT)
|
16
|
+
@logger.level = Logger::DEBUG
|
17
|
+
|
18
|
+
def self.log_level(level)
|
19
|
+
@logger.level = level
|
20
|
+
end
|
21
|
+
|
22
|
+
if !IPAddress::IPv6.instance_methods.include?(:rev_domains)
|
23
|
+
@logger.fatal "you need the right ipaddress version from https://github.com/mabels/ipaddress"
|
24
|
+
end
|
25
|
+
|
26
|
+
if !OpenStruct.instance_methods.include?(:to_h)
|
27
|
+
OpenStruct.class_eval do
|
28
|
+
def to_h
|
29
|
+
@table.dup
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
@logger.warn "Your running a patched version of OpenStruct"
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.logger
|
37
|
+
@logger
|
38
|
+
end
|
39
|
+
|
40
|
+
# ugly but i need the logger during initialization
|
41
|
+
require_relative 'construqt/util.rb'
|
42
|
+
require_relative 'construqt/services.rb'
|
43
|
+
require_relative 'construqt/networks.rb'
|
44
|
+
require_relative 'construqt/addresses.rb'
|
45
|
+
require_relative 'construqt/bgps.rb'
|
46
|
+
require_relative 'construqt/users.rb'
|
47
|
+
require_relative 'construqt/firewalls.rb'
|
48
|
+
require_relative 'construqt/flavour/delegates.rb'
|
49
|
+
require_relative 'construqt/resource.rb'
|
50
|
+
require_relative 'construqt/hostid.rb'
|
51
|
+
require_relative 'construqt/hosts.rb'
|
52
|
+
require_relative 'construqt/interfaces.rb'
|
53
|
+
require_relative 'construqt/cables.rb'
|
54
|
+
require_relative 'construqt/ipsecs.rb'
|
55
|
+
require_relative 'construqt/firewalls.rb'
|
56
|
+
require_relative 'construqt/templates.rb'
|
57
|
+
require_relative 'construqt/regions.rb'
|
58
|
+
require_relative 'construqt/vlans.rb'
|
59
|
+
require_relative 'construqt/tags.rb'
|
60
|
+
require_relative 'construqt/flavour/flavour.rb'
|
61
|
+
|
62
|
+
require_relative 'construqt/flavour/unknown/unknown.rb'
|
63
|
+
[
|
64
|
+
'construqt/flavour/ciscian/ciscian.rb',
|
65
|
+
'construqt/flavour/plantuml/plantuml.rb',
|
66
|
+
'construqt/flavour/mikrotik/flavour_mikrotik.rb',
|
67
|
+
'construqt/flavour/ubuntu/flavour_ubuntu.rb'].each do |fname|
|
68
|
+
begin
|
69
|
+
require_relative fname
|
70
|
+
rescue LoadError
|
71
|
+
Construqt::logger.warn("can not load driver:#{fname}")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.produce(region_or_hosts)
|
76
|
+
hosts = false
|
77
|
+
hosts = region_or_hosts if region_or_hosts.kind_of?(Array)
|
78
|
+
hosts = region_or_hosts.hosts.get_hosts if region_or_hosts.kind_of?(Construqt::Regions::Region)
|
79
|
+
throw "need a region or hosts list" unless hosts
|
80
|
+
Construqt::Ipsecs.build_config()
|
81
|
+
Construqt::Bgps.build_config()
|
82
|
+
hosts.inject({}) do |r, host|
|
83
|
+
r[host.region.name] ||= []
|
84
|
+
r[host.region.name] << host
|
85
|
+
r
|
86
|
+
end.values.each do |hosts|
|
87
|
+
hosts.first.region.hosts.build_config(hosts)
|
88
|
+
hosts.first.region.interfaces.build_config(hosts)
|
89
|
+
hosts.first.region.hosts.commit(hosts)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|