195 lines
6.9 KiB
Ruby
195 lines
6.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "../spec_helper"
|
|
|
|
RSpec.describe KubernetesCluster do
|
|
subject(:kc) {
|
|
project = Project.create(name: "test")
|
|
private_subnet = PrivateSubnet.create(project_id: project.id, name: "test", location_id: Location::HETZNER_FSN1_ID, net6: "fe80::/64", net4: "192.168.0.0/24")
|
|
described_class.create(
|
|
name: "kc-name",
|
|
version: "v1.32",
|
|
location_id: Location::HETZNER_FSN1_ID,
|
|
cp_node_count: 3,
|
|
project_id: project.id,
|
|
private_subnet_id: private_subnet.id,
|
|
target_node_size: "standard-2"
|
|
)
|
|
}
|
|
|
|
it "displays location properly" do
|
|
expect(kc.display_location).to eq("eu-central-h1")
|
|
end
|
|
|
|
it "returns path" do
|
|
expect(kc.path).to eq("/location/eu-central-h1/kubernetes-cluster/kc-name")
|
|
end
|
|
|
|
it "initiates a new health monitor session" do
|
|
sshable = instance_double(Sshable)
|
|
expect(kc).to receive(:sshable).and_return(sshable)
|
|
expect(sshable).to receive(:start_fresh_session)
|
|
kc.init_health_monitor_session
|
|
end
|
|
|
|
it "checks pulse" do
|
|
session = {
|
|
ssh_session: instance_double(Net::SSH::Connection::Session)
|
|
}
|
|
pulse = {
|
|
reading: "down",
|
|
reading_rpt: 5,
|
|
reading_chg: Time.now - 30
|
|
}
|
|
|
|
expect(kc).to receive(:incr_sync_kubernetes_services)
|
|
client = instance_double(Kubernetes::Client)
|
|
expect(kc).to receive(:client).and_return(client)
|
|
expect(client).to receive(:any_lb_services_modified?).and_return(true)
|
|
|
|
expect(kc.check_pulse(session: session, previous_pulse: pulse)[:reading]).to eq("up")
|
|
end
|
|
|
|
it "checks pulse on with no changes to the internal services" do
|
|
session = {
|
|
ssh_session: instance_double(Net::SSH::Connection::Session)
|
|
}
|
|
pulse = {
|
|
reading: "up",
|
|
reading_rpt: 5,
|
|
reading_chg: Time.now - 30
|
|
}
|
|
|
|
client = instance_double(Kubernetes::Client)
|
|
expect(kc).to receive(:client).and_return(client)
|
|
expect(client).to receive(:any_lb_services_modified?).and_return(false)
|
|
|
|
expect(kc.check_pulse(session: session, previous_pulse: pulse)[:reading]).to eq("up")
|
|
end
|
|
|
|
it "checks pulse and fails" do
|
|
session = {
|
|
ssh_session: instance_double(Net::SSH::Connection::Session)
|
|
}
|
|
pulse = {
|
|
reading: "down",
|
|
reading_rpt: 5,
|
|
reading_chg: Time.now - 30
|
|
}
|
|
|
|
client = instance_double(Kubernetes::Client)
|
|
expect(kc).to receive(:client).and_return(client)
|
|
expect(client).to receive(:any_lb_services_modified?).and_raise Sshable::SshError
|
|
|
|
expect(kc.check_pulse(session: session, previous_pulse: pulse)[:reading]).to eq("down")
|
|
end
|
|
|
|
describe "#kubectl" do
|
|
it "create a new client" do
|
|
session = instance_double(Net::SSH::Connection::Session)
|
|
expect(kc.client(session: session)).to be_an_instance_of(Kubernetes::Client)
|
|
end
|
|
end
|
|
|
|
describe "#validate" do
|
|
it "validates cp_node_count" do
|
|
kc.cp_node_count = 0
|
|
expect(kc.valid?).to be false
|
|
expect(kc.errors[:cp_node_count]).to eq(["must be a positive integer"])
|
|
|
|
kc.cp_node_count = 2
|
|
expect(kc.valid?).to be true
|
|
end
|
|
|
|
it "validates version" do
|
|
kc.version = "v1.34"
|
|
expect(kc.valid?).to be false
|
|
expect(kc.errors[:version]).to eq(["must be a valid Kubernetes version"])
|
|
|
|
kc.version = "v1.32"
|
|
expect(kc.valid?).to be true
|
|
end
|
|
|
|
it "adds error if cp_node_count is nil" do
|
|
kc.cp_node_count = nil
|
|
expect(kc.valid?).to be false
|
|
expect(kc.errors[:cp_node_count]).to include("must be a positive integer")
|
|
end
|
|
|
|
it "adds error if cp_node_count is not an integer" do
|
|
kc.cp_node_count = "three"
|
|
expect(kc.valid?).to be false
|
|
expect(kc.errors[:cp_node_count]).to include("must be a positive integer")
|
|
end
|
|
end
|
|
|
|
describe "#kubeconfig" do
|
|
kubeconfig = <<~YAML
|
|
apiVersion: v1
|
|
kind: Config
|
|
users:
|
|
- name: admin
|
|
user:
|
|
client-certificate-data: "mocked_cert_data"
|
|
client-key-data: "mocked_key_data"
|
|
YAML
|
|
let(:sshable) { instance_double(Sshable) }
|
|
let(:vm) { instance_double(Vm, sshable: sshable) }
|
|
let(:cp_vms) { [vm] }
|
|
|
|
it "removes client certificate and key data from users and adds an RBAC token to users" do
|
|
expect(kc).to receive(:cp_vms).and_return(cp_vms)
|
|
expect(sshable).to receive(:cmd).with("kubectl --kubeconfig <(sudo cat /etc/kubernetes/admin.conf) -n kube-system get secret k8s-access -o jsonpath='{.data.token}' | base64 -d", log: false).and_return("mocked_rbac_token")
|
|
expect(sshable).to receive(:cmd).with("sudo cat /etc/kubernetes/admin.conf", log: false).and_return(kubeconfig)
|
|
customer_config = kc.kubeconfig
|
|
YAML.safe_load(customer_config)["users"].each do |user|
|
|
expect(user["user"]).not_to have_key("client-certificate-data")
|
|
expect(user["user"]).not_to have_key("client-key-data")
|
|
expect(user["user"]["token"]).to eq("mocked_rbac_token")
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "vm_diff_for_lb" do
|
|
it "finds the extra and missing vms" do
|
|
lb = Prog::Vnet::LoadBalancerNexus.assemble(kc.private_subnet.id, name: kc.services_load_balancer_name, src_port: 443, dst_port: 8443).subject
|
|
extra_vm = Prog::Vm::Nexus.assemble("k y", kc.project.id, name: "extra-vm", private_subnet_id: kc.private_subnet.id).subject
|
|
missing_vm = Prog::Vm::Nexus.assemble("k y", kc.project.id, name: "missing-vm", private_subnet_id: kc.private_subnet.id).subject
|
|
lb.add_vm(extra_vm)
|
|
np = instance_double(KubernetesNodepool, vms: [missing_vm])
|
|
expect(kc).to receive(:nodepools).and_return([np])
|
|
extra_vms, missing_vms = kc.vm_diff_for_lb(lb)
|
|
expect(extra_vms.count).to eq(1)
|
|
expect(extra_vms[0].id).to eq(extra_vm.id)
|
|
expect(missing_vms.count).to eq(1)
|
|
expect(missing_vms[0].id).to eq(missing_vm.id)
|
|
end
|
|
end
|
|
|
|
describe "port_diff_for_lb" do
|
|
it "finds the extra and missing vms" do
|
|
lb = Prog::Vnet::LoadBalancerNexus.assemble(kc.private_subnet.id, name: kc.services_load_balancer_name, src_port: 80, dst_port: 8000).subject
|
|
extra_ports, missing_ports = kc.port_diff_for_lb(lb, [[443, 8443]])
|
|
expect(extra_ports.count).to eq(1)
|
|
expect(extra_ports[0].src_port).to eq(80)
|
|
expect(missing_ports.count).to eq(1)
|
|
expect(missing_ports[0][0]).to eq(443)
|
|
end
|
|
end
|
|
|
|
describe "#all_vms" do
|
|
it "returns all VMs in the cluster, including CP and worker nodes" do
|
|
expect(kc).to receive(:cp_vms).and_return([1, 2])
|
|
expect(kc).to receive(:nodepools).and_return([instance_double(KubernetesNodepool, vms: [3, 4]), instance_double(KubernetesNodepool, vms: [5, 6])])
|
|
expect(kc.all_vms).to eq([1, 2, 3, 4, 5, 6])
|
|
end
|
|
end
|
|
|
|
describe "#worker_vms" do
|
|
it "returns all worker VMs in the cluster" do
|
|
expect(kc).to receive(:nodepools).and_return([instance_double(KubernetesNodepool, vms: [3, 4]), instance_double(KubernetesNodepool, vms: [5, 6])])
|
|
expect(kc.worker_vms).to eq([3, 4, 5, 6])
|
|
end
|
|
end
|
|
end
|