Files
ubicloud/spec/model/kubernetes/kubernetes_cluster_spec.rb
Jeremy Evans 9d5f0a2cbc Validate Vm#public_key when saving
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.
2025-04-26 05:34:41 +09:00

168 lines
5.8 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 greater than 0"])
kc.cp_node_count = 2
expect(kc.valid?).to be true
end
it "validates version" do
kc.version = "v1.33"
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
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
end