Files
ubicloud/spec/prog/aws/nic_spec.rb
Furkan Sahin 880dfe0e1d Provision AWS Network Interface instead of Ubicloud NICs
Nics are logical entities in Ubicloud which we use to configure TAP
devices later on. In AWS, they are similar, but they also get the public
IP addresses assigned. In Ubicloud, they are mostly related to private
networking. Here in this commit, we introduce the logic to prepare an
AWS network interface to be used by a VM. The only missing piece is the
private IPv6 element. We'll skip that for now.
2025-04-02 12:34:20 +02:00

92 lines
5.1 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Prog::Aws::Nic do
subject(:nx) {
described_class.new(st)
}
let(:st) {
Strand.create_with_id(prog: "Aws::Nic", stack: [{"subject_id" => nic.id}], label: "create_network_interface")
}
let(:nic) {
prj = Project.create_with_id(name: "test-prj")
loc = Location.create_with_id(name: "us-east-1", provider: "aws", project_id: prj.id, display_name: "aws-us-east-1", ui_name: "AWS US East 1", visible: true)
LocationCredential.create_with_id(access_key: "test-access-key", secret_key: "test-secret-key") { _1.id = loc.id }
ps = Prog::Vnet::SubnetNexus.assemble(prj.id, name: "test-ps", location_id: loc.id).subject
PrivateSubnetAwsResource.create(subnet_id: "subnet-0123456789abcdefg", security_group_id: "sg-0123456789abcdefg") { _1.id = ps.id }
Prog::Vnet::NicNexus.assemble(ps.id, name: "test-nic").subject
}
let(:client) {
Aws::EC2::Client.new(stub_responses: true)
}
before do
allow(nx).to receive(:nic).and_return(nic)
allow(Aws::EC2::Client).to receive(:new).with(access_key_id: "test-access-key", secret_access_key: "test-secret-key", region: "us-east-1").and_return(client)
end
describe "#create_network_interface" do
it "creates a network interface" do
client.stub_responses(:create_network_interface, network_interface: {network_interface_id: "eni-0123456789abcdefg"})
client.stub_responses(:assign_ipv_6_addresses)
expect(client).to receive(:create_network_interface).with({subnet_id: "subnet-0123456789abcdefg", private_ip_address: nic.private_ipv4.network.to_s, ipv_6_prefix_count: 1, groups: ["sg-0123456789abcdefg"], tag_specifications: [{resource_type: "network-interface", tags: [{key: "Ubicloud", value: "true"}]}]}).and_call_original
expect(client).to receive(:assign_ipv_6_addresses).with({network_interface_id: "eni-0123456789abcdefg", ipv_6_address_count: 1}).and_call_original
expect(nic).to receive(:update).with(name: "eni-0123456789abcdefg")
expect { nx.create_network_interface }.to hop("wait_network_interface_created")
end
end
describe "#wait_network_interface_created" do
it "checks if network interface is available, if not naps" do
client.stub_responses(:describe_network_interfaces, network_interfaces: [{status: "pending"}])
expect(client).to receive(:describe_network_interfaces).with({filters: [{name: "network-interface-id", values: [nic.name]}, {name: "tag:Ubicloud", values: ["true"]}]}).and_call_original
expect { nx.wait_network_interface_created }.to nap(1)
end
it "checks if network interface is available, if it is, it allocates an elastic ip and associates it with the network interface" do
client.stub_responses(:describe_network_interfaces, network_interfaces: [{status: "available"}])
client.stub_responses(:allocate_address, allocation_id: "eip-0123456789abcdefg")
client.stub_responses(:associate_address)
expect(client).to receive(:describe_network_interfaces).with({filters: [{name: "network-interface-id", values: [nic.name]}, {name: "tag:Ubicloud", values: ["true"]}]}).and_call_original
expect(client).to receive(:associate_address).with({allocation_id: "eip-0123456789abcdefg", network_interface_id: nic.name}).and_call_original
expect { nx.wait_network_interface_created }.to exit({"msg" => "nic created"})
end
end
describe "#destroy" do
it "deletes the network interface" do
client.stub_responses(:delete_network_interface)
expect(client).to receive(:delete_network_interface).with({network_interface_id: nic.name}).and_call_original
expect { nx.destroy }.to hop("release_eip")
end
it "hops to release_eip if the network interface is not found" do
client.stub_responses(:delete_network_interface, Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound.new(nil, "The network interface 'eni-0123456789abcdefg' does not exist."))
expect { nx.destroy }.to hop("release_eip")
end
end
describe "#release_eip" do
it "releases the elastic ip" do
client.stub_responses(:describe_addresses, addresses: [{allocation_id: "eip-0123456789abcdefg"}])
client.stub_responses(:release_address)
expect(client).to receive(:describe_addresses).with({filters: [{name: "network-interface-id", values: [nic.name]}]}).and_call_original
expect(client).to receive(:release_address).with({allocation_id: "eip-0123456789abcdefg"}).and_call_original
expect { nx.release_eip }.to exit({"msg" => "nic destroyed"})
end
it "pops if the network interface is not found" do
client.stub_responses(:describe_addresses, addresses: [])
expect { nx.release_eip }.to exit({"msg" => "nic destroyed"})
end
it "pops if the address is already released" do
client.stub_responses(:describe_addresses, addresses: [{allocation_id: "eip-0123456789abcdefg"}])
client.stub_responses(:release_address, Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound.new(nil, "The network interface 'eni-0123456789abcdefg' does not exist."))
expect { nx.release_eip }.to exit({"msg" => "nic destroyed"})
end
end
end