Files
ubicloud/spec/prog/aws/instance_spec.rb
Furkan Sahin f85be7e4c5 Integrate PG with AWS instance sizes
On the AWS side, we are limited on the VM size configuration with disk
sizes. Therefore, we are introducing the limitations here. We are also
making only standard SKU available. For now, we will only support a
single disk size per instance size which also is supported up to 16
vcpu.
2025-04-02 12:34:20 +02:00

133 lines
5.4 KiB
Ruby

# frozen_string_literal: true
RSpec.describe Prog::Aws::Instance do
subject(:nx) {
described_class.new(st)
}
let(:st) {
Strand.create_with_id(prog: "Aws::Instance", stack: [{"subject_id" => vm.id}], label: "start")
}
let(:vm) {
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 }
Prog::Vm::Nexus.assemble("dummy-public-key", prj.id, location_id: loc.id, unix_user: "test-user-aws", boot_image: "ami-030c060f85668b37d").subject
}
let(:client) {
Aws::EC2::Client.new(stub_responses: true)
}
let(:user_data) {
<<~USER_DATA
#!/bin/bash
custom_user="test-user-aws"
# Create the custom user
adduser $custom_user --disabled-password --gecos ""
# Add the custom user to the sudo group
usermod -aG sudo $custom_user
# disable password for the custom user
echo "$custom_user ALL=(ALL:ALL) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/$custom_user
# Set up SSH access for the custom user
mkdir -p /home/$custom_user/.ssh
cp /home/ubuntu/.ssh/authorized_keys /home/$custom_user/.ssh/
chown -R $custom_user:$custom_user /home/$custom_user/.ssh
chmod 700 /home/$custom_user/.ssh
chmod 600 /home/$custom_user/.ssh/authorized_keys
echo dummy-public-key > /home/$custom_user/.ssh/authorized_keys
usermod -L ubuntu
USER_DATA
}
before do
allow(nx).to receive(:vm).and_return(vm)
expect(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 "#start" do
it "creates an instance" do
client.stub_responses(:run_instances, instances: [{instance_id: "i-0123456789abcdefg"}])
expect(vm).to receive(:vcpus).and_return(2)
expect(vm).to receive(:sshable).and_return(instance_double(Sshable, keys: [instance_double(SshKey, public_key: "dummy-public-key")]))
expect(client).to receive(:run_instances).with({
image_id: "ami-030c060f85668b37d",
instance_type: "m6id.large",
block_device_mappings: [
{
device_name: "/dev/sda1",
ebs: {
encrypted: true,
delete_on_termination: true,
iops: 3000,
volume_size: 40,
volume_type: "gp3",
throughput: 125
}
}
],
network_interfaces: [
{
network_interface_id: vm.nics.first.name,
device_index: 0
}
],
private_dns_name_options: {
hostname_type: "ip-name",
enable_resource_name_dns_a_record: false,
enable_resource_name_dns_aaaa_record: false
},
min_count: 1,
max_count: 1,
user_data: Base64.encode64(user_data),
tag_specifications: [{resource_type: "instance", tags: [{key: "Ubicloud", value: "true"}]}]
}).and_call_original
expect(vm).to receive(:update).with(name: "i-0123456789abcdefg")
expect { nx.start }.to hop("wait_instance_created")
end
end
describe "#wait_instance_created" do
before do
client.stub_responses(:describe_instances, reservations: [{instances: [{state: {name: "running"}, network_interfaces: [{association: {public_ip: "1.2.3.4"}, ipv_6_addresses: [{ipv_6_address: "2a01:4f8:173:1ed3:aa7c::/79"}]}]}]}])
end
it "updates the vm with the instance id" do
time = Time.now
expect(Time).to receive(:now).and_return(time).at_least(:once)
expect(vm.strand).to receive(:stack).and_return([{"storage_volumes" => [{"boot" => false, "size_gib" => 10}]}], label: "start").at_least(:once)
expect(client).to receive(:describe_instances).with({filters: [{name: "instance-id", values: [vm.name]}, {name: "tag:Ubicloud", values: ["true"]}]}).and_call_original
expect(vm).to receive(:update).with(cores: 1, allocated_at: time, ephemeral_net6: "2a01:4f8:173:1ed3:aa7c::/79")
expect { nx.wait_instance_created }.to exit({"msg" => "vm created"})
expect(VmStorageVolume.count).to eq(1)
expect(VmStorageVolume.first).to have_attributes(size_gib: 10, boot: false, use_bdev_ubi: false, disk_index: 1)
end
it "doesn't create vm_storage_volumes if there are no storage volumes" do
time = Time.now
expect(Time).to receive(:now).and_return(time).at_least(:once)
sshable = instance_double(Sshable)
expect(vm).to receive(:sshable).and_return(sshable)
expect(sshable).to receive(:update).with(host: "1.2.3.4")
expect(vm.strand).to receive(:stack).and_return([{"storage_volumes" => [{"boot" => true, "size_gib" => 10}]}], label: "start").at_least(:once)
expect(vm).to receive(:update).with(cores: 1, allocated_at: time, ephemeral_net6: "2a01:4f8:173:1ed3:aa7c::/79")
expect { nx.wait_instance_created }.to exit({"msg" => "vm created"})
expect(VmStorageVolume.count).to eq(0)
end
it "naps if the instance is not running" do
client.stub_responses(:describe_instances, reservations: [{instances: [{state: {name: "pending"}}]}])
expect { nx.wait_instance_created }.to nap(1)
end
end
describe "#destroy" do
it "deletes the instance" do
expect(client).to receive(:terminate_instances).with({instance_ids: [vm.name]})
expect { nx.destroy }.to exit({"msg" => "vm destroyed"})
end
end
end