This implements a fairly loose validation of the public key format. It does not check specific key types, nor try to decode the base64 key and check it for validity. It does check that the format in general is valid, and that at least one valid key is present. It will reject public keys, because those don't have a space. This requires changes to many specs to have them use a valid public key format. In many cases, that is done by changing a single dash to a space.
506 lines
20 KiB
Ruby
506 lines
20 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
RSpec.describe Prog::Vnet::UpdateLoadBalancerNode do
|
|
subject(:nx) {
|
|
described_class.new(st)
|
|
}
|
|
|
|
let(:st) {
|
|
Strand.create(prog: "Vnet::UpdateLoadBalancerNode", stack: [{"subject_id" => vm.id, "load_balancer_id" => lb.id}], label: "update_load_balancer")
|
|
}
|
|
let(:prj) {
|
|
Project.create(name: "test-prj")
|
|
}
|
|
let(:ps) {
|
|
Prog::Vnet::SubnetNexus.assemble(prj.id, name: "test-ps").subject
|
|
}
|
|
|
|
let(:lb) {
|
|
lb = Prog::Vnet::LoadBalancerNexus.assemble(ps.id, name: "test-lb", src_port: 80, dst_port: 8080).subject
|
|
dz = DnsZone.create(name: "test-dns-zone", project_id: prj.id)
|
|
cert = Prog::Vnet::CertNexus.assemble("test-host-name", dz.id).subject
|
|
lb.add_cert(cert)
|
|
lb
|
|
}
|
|
let(:vm) {
|
|
nic = Prog::Vnet::NicNexus.assemble(ps.id, ipv4_addr: "192.168.1.0/32", ipv6_addr: "fd10:9b0b:6b4b:8fbb::/64").subject
|
|
Prog::Vm::Nexus.assemble("pub key", lb.project_id, name: "vm1", private_subnet_id: lb.private_subnet.id, nic_id: nic.id).subject
|
|
}
|
|
let(:neighbor_vm) {
|
|
nic = Prog::Vnet::NicNexus.assemble(ps.id, ipv4_addr: "172.10.1.0/32", ipv6_addr: "fd10:9b0b:6b4b:aaa::/64").subject
|
|
Prog::Vm::Nexus.assemble("pub key", lb.project_id, name: "vm2", private_subnet_id: lb.private_subnet.id, nic_id: nic.id).subject
|
|
}
|
|
let(:vmh) {
|
|
vmh = instance_double(VmHost, sshable: instance_double(Sshable))
|
|
allow(vm).to receive(:vm_host).and_return(vmh)
|
|
vmh
|
|
}
|
|
|
|
before do
|
|
lb.add_vm(vm)
|
|
allow(nx).to receive_messages(vm: vm, load_balancer: lb)
|
|
allow(vm).to receive_messages(ephemeral_net4: NetAddr::IPv4Net.parse("100.100.100.100/32"), ephemeral_net6: NetAddr::IPv6Net.parse("2a02:a464:deb2:a000::/64"))
|
|
allow(vm).to receive(:vm_host).and_return(instance_double(VmHost, sshable: instance_double(Sshable)))
|
|
end
|
|
|
|
describe ".before_run" do
|
|
it "simply pops if VM is destroyed" do
|
|
expect(nx).to receive(:vm).and_return(nil)
|
|
|
|
expect { nx.before_run }.to exit({"msg" => "VM is destroyed"})
|
|
end
|
|
|
|
it "doesn't do anything if the VM is not destroyed" do
|
|
expect(nx).to receive(:vm).and_return(vm)
|
|
|
|
expect { nx.before_run }.not_to exit
|
|
end
|
|
end
|
|
|
|
describe "#update_load_balancer" do
|
|
context "when no healthy vm exists" do
|
|
it "hops to remove load balancer" do
|
|
expect(lb).to receive(:active_vm_ports).and_return([])
|
|
expect { nx.update_load_balancer }.to hop("remove_load_balancer")
|
|
end
|
|
|
|
it "removes the VM from load balancer if the VM is detaching" do
|
|
LoadBalancerVmPort.where(id: lb.vm_ports_dataset.map(&:id)).update(state: "detaching")
|
|
expect(lb).to receive(:remove_vm_port).with(lb.vm_ports_dataset.first)
|
|
expect { nx.update_load_balancer }.to hop("remove_load_balancer")
|
|
end
|
|
end
|
|
|
|
context "when a single vm exists and it is the subject" do
|
|
before do
|
|
LoadBalancerVmPort.where(id: lb.vm_ports_dataset.map(&:id)).update(state: "up")
|
|
end
|
|
|
|
it "does not hop to remove load balancer and creates basic load balancing with nat" do
|
|
expect(vmh.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 192.168.1.0 . 8080 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 2a02:a464:deb2:a000::2 . 8080 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "does not hop to remove load balancer and creates basic load balancing with nat specifically for ipv4" do
|
|
lb.update(stack: "ipv4")
|
|
expect(vmh.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 192.168.1.0 . 8080 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "creates basic load balancing with hashing with multiple ports" do
|
|
lb.add_port(443, 8443)
|
|
lb.reload
|
|
port = LoadBalancerPort.where(load_balancer_id: lb.id, src_port: 443).first
|
|
LoadBalancerVmPort.where(load_balancer_port_id: port.id).update(state: "up")
|
|
expect(vmh.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 192.168.1.0 . 8080 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
ip daddr 100.100.100.100/32 tcp dport 443 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 443 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 192.168.1.0 . 8443 }
|
|
ip daddr 192.168.1.0 tcp dport 443 ct state established,related,new counter dnat to 192.168.1.0:8443
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 2a02:a464:deb2:a000::2 . 8080 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 443 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 443 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 2a02:a464:deb2:a000::2 . 8443 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 443 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8443
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
ip daddr @neighbor_ips_v4 tcp dport 443 ct state established,related,new counter snat to 192.168.1.0
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 443 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "creates basic load balancing with hashing" do
|
|
lb.update(algorithm: "hash_based")
|
|
expect(vmh.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to jhash ip saddr . tcp sport . ip daddr . tcp dport mod 1 map { 0 : 192.168.1.0 . 8080 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to jhash ip6 saddr . tcp sport . ip6 daddr . tcp dport mod 1 map { 0 : 2a02:a464:deb2:a000::2 . 8080 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
end
|
|
|
|
context "when multiple vms exist" do
|
|
before do
|
|
lb.add_vm(neighbor_vm)
|
|
LoadBalancerVmPort.map { |lbvmport| lbvmport.update(state: "up") }
|
|
end
|
|
|
|
it "creates load balancing with multiple vms if all active" do
|
|
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
elements = {172.10.1.0}
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
elements = {fd10:9b0b:6b4b:aaa::2}
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 2 map { 0 : 172.10.1.0 . 80, 1 : 192.168.1.0 . 8080 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 2 map { 0 : 2a02:a464:deb2:a000::2 . 8080, 1 : fd10:9b0b:6b4b:aaa::2 . 80 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "creates load balancing with multiple vms if all active ipv6 only" do
|
|
lb.update(stack: "ipv6")
|
|
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
elements = {172.10.1.0}
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
elements = {fd10:9b0b:6b4b:aaa::2}
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 2 map { 0 : 2a02:a464:deb2:a000::2 . 8080, 1 : fd10:9b0b:6b4b:aaa::2 . 80 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "creates load balancing with multiple vms if the vm we work on is down" do
|
|
LoadBalancerVmPort.where(load_balancer_vm_id: vm.load_balancers_vms.id).update(state: "down")
|
|
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
elements = {172.10.1.0}
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
elements = {fd10:9b0b:6b4b:aaa::2}
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 172.10.1.0 . 80 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : fd10:9b0b:6b4b:aaa::2 . 80 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "creates load balancing with multiple vms if the vm we work on is up but the neighbor is down" do
|
|
LoadBalancerVmPort.where(load_balancer_vm_id: neighbor_vm.load_balancers_vms.id).update(state: "down")
|
|
expect(vm.vm_host.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table inet nat {
|
|
set neighbor_ips_v4 {
|
|
type ipv4_addr;
|
|
|
|
}
|
|
|
|
set neighbor_ips_v6 {
|
|
type ipv6_addr;
|
|
|
|
}
|
|
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip daddr 100.100.100.100/32 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 192.168.1.0 . 8080 }
|
|
ip daddr 192.168.1.0 tcp dport 80 ct state established,related,new counter dnat to 192.168.1.0:8080
|
|
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 meta mark set 0x00B1C100D
|
|
ip6 daddr 2a02:a464:deb2:a000::2 tcp dport 80 ct state established,related,new counter dnat to numgen inc mod 1 map { 0 : 2a02:a464:deb2:a000::2 . 8080 }
|
|
ip6 daddr fd10:9b0b:6b4b:8fbb::2 tcp dport 80 ct state established,related,new counter dnat to [2a02:a464:deb2:a000::2]:8080
|
|
|
|
|
|
# Basic NAT for public IPv4 to private IPv4
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip daddr @neighbor_ips_v4 tcp dport 80 ct state established,related,new counter snat to 192.168.1.0
|
|
ip6 daddr @neighbor_ips_v6 tcp dport 80 ct state established,related,new counter snat to fd10:9b0b:6b4b:8fbb::2
|
|
|
|
# Basic NAT for private IPv4 to public IPv4
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
LOAD_BALANCER
|
|
|
|
expect { nx.update_load_balancer }.to exit({"msg" => "load balancer is updated"})
|
|
end
|
|
|
|
it "raises exception if the algorithm is not supported" do
|
|
expect(lb).to receive(:algorithm).and_return("least_conn").at_least(:once)
|
|
expect { nx.update_load_balancer }.to raise_error("Unsupported load balancer algorithm: least_conn")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#remove_load_balancer" do
|
|
it "creates basic nat rules" do
|
|
expect(vmh.sshable).to receive(:cmd).with("sudo ip netns exec #{vm.inhost_name} nft --file -", stdin: <<REMOVE_LOAD_BALANCER)
|
|
table ip nat;
|
|
delete table ip nat;
|
|
table inet nat;
|
|
delete table inet nat;
|
|
table ip nat {
|
|
chain prerouting {
|
|
type nat hook prerouting priority dstnat; policy accept;
|
|
ip daddr 100.100.100.100/32 dnat to 192.168.1.0
|
|
}
|
|
chain postrouting {
|
|
type nat hook postrouting priority srcnat; policy accept;
|
|
ip saddr 192.168.1.0 ip daddr != { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } snat to 100.100.100.100/32
|
|
ip saddr 192.168.1.0 ip daddr 192.168.1.0 snat to 100.100.100.100/32
|
|
}
|
|
}
|
|
REMOVE_LOAD_BALANCER
|
|
expect { nx.remove_load_balancer }.to exit({"msg" => "load balancer is removed"})
|
|
end
|
|
end
|
|
|
|
it "returns load_balancer" do
|
|
expect(nx).to receive(:load_balancer).and_call_original
|
|
expect(nx.load_balancer.id).to eq(lb.id)
|
|
end
|
|
end
|