cluster/lib/cluster/runner.rb in sct-0.1.28 vs cluster/lib/cluster/runner.rb in sct-0.1.29

- old
+ new

@@ -1,120 +1,159 @@ module Cluster class Runner - def launch - return UI.error("SCT has not been initialized. Run 'sct init' first.") unless SctCore::Config.exists + def start + SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on + + existing_cluster = cluster_exists? + start_cluster - run_command "kubectl delete pod -n kube-system #{pods("kube-system").map { |pod| pod[:name] if pod[:name].start_with? "registry-creds" } .compact.join(" ")}" - run_command "kubectl rollout status -n kube-system deployment/registry-creds" + + if existing_cluster + run_command "kubectl rollout restart -n kube-system deployment registry-creds" + run_command "kubectl rollout status -n kube-system deployment registry-creds" + else + create_secrets + enable_addons + wait_for_gcr_secret + run_command "kubectl apply -f ~/development/spend-cloud/k8s/ingress.yml" + wait_for_ingress_ip + run_command "kubectl apply -f ~/development/spend-cloud/k8s/dependencies.yml" + wait_for_pods + run_command "kubectl apply -f ~/development/spend-cloud/k8s/" + end + post_start end + def stop + run_command "minikube stop" + end + + def restart + SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on + + stop + start + end + + def delete + run_command "minikube delete" + end + + def reset + SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on + + delete + start + end + + def status + print_contexts + print_minikube_status + + if get_minikube_status.find_all { |status| status[1] == 'Stopped' }.count == 0 + print_pods_status("kube-system") + print_pods_status + else + UI.important("Please check your minikube status. If all services are stopped you should start the minikube first.") + end + end + + def update_config + run_command "kubectl config use-context minikube" + + run_command "kubectl replace -n kube-system -f #{File.expand_path('resources/corefile.yml', __dir__)}" + run_command "kubectl rollout restart -n kube-system deployment coredns" + run_command "kubectl rollout status -n kube-system deployment coredns" + end + + def apply_deployments + run_command "kubectl apply -f ~/development/spend-cloud/k8s/" + end + + + def cluster_exists? + if system "minikube status", { out: "/dev/null" } + # cluster exists and is running + return true + end + + if $?.exitstatus == 85 + # cluster does not exist + return false + end + + # cluster exists but is stopped + return true + end + def start_cluster if SctCore::Helper.operatingSystem == SctCore::Helper::MAC_OS - run_command "#{SctCore::Helper.minikube} start --cpus=$(sysctl -n hw.ncpu) --memory=8G" + run_command "minikube start --driver=docker --cpus=$(sysctl -n hw.ncpu) --memory=8G" else - run_command "#{SctCore::Helper.minikube} start --cpus=$(cat /proc/cpuinfo | grep processor | wc -l) --memory=10G" + run_command "minikube start --driver=docker --cpus=$(cat /proc/cpuinfo | grep processor | wc -l) --memory=3G" end - run_command "#{SctCore::Helper.minikube} ssh -- 'sudo su -c \"echo 10048576 > /proc/sys/fs/inotify/max_user_watches\"'" update_config end def post_start wait_for_pods run_command "sudo sct hostfile" + run_command "minikube tunnel &", { out: "/dev/null", err: "/dev/null" } if SctCore::Helper::is_windows? # leave this running detached forever in the background UI.success("\nāœ”ļø You can visit your environment at šŸ‘‰ https://spend-cloud.spend.cloud.local šŸ‘Œ") end - def down - run_command "#{SctCore::Helper.minikube} stop" - end - - def reset - run_command "#{SctCore::Helper.minikube} delete" - start_cluster - create_secrets - enable_addons - wait_for_gcr_secret - run_command "kubectl apply -f ~/development/spend-cloud/k8s/ingress.yml" - wait_for_ingress_ip - run_command "kubectl apply -f ~/development/spend-cloud/k8s/dependencies.yml" - wait_for_pods - run_command "kubectl apply -f ~/development/spend-cloud/k8s/" - post_start - end - def enable_addons enable_addon "registry-creds" enable_addon "ingress" end def enable_addon(addon) - run_command "#{SctCore::Helper.minikube} addons enable #{addon}" + run_command "minikube addons enable #{addon}" deployment = deployments("kube-system").find { |deployment| deployment[:name].include? addon } - run_command "kubectl rollout status -n kube-system deployment/#{deployment[:name]}" + run_command "kubectl rollout status -n kube-system deployment #{deployment[:name]}" end def wait_for_pods UI.important("Waiting for pods to become ready...") - while ! pods.all? { |pod| pod[:status] == "Running" } - delete_stalled_pods + previous_lines = 0 - sleep 5 - end + while ! pods.all? { |pod| pod[:ready] } + pods_status_lines = get_pods_status.to_s.lines.map { |line| line.chomp } - UI.success("Pods are now ready.") - end + current_lines = pods_status_lines.length - def delete_stalled_pods(feedback: false) + line_difference = current_lines - previous_lines - return UI.success("No stalled pods found") unless !pods.to_a.empty? + if line_difference < 0 # there are now less lines than before + line_difference.abs.times do + print "\033[1A\033[K" # move the cursor up a line and clear the line + end - stalled_pods = pods.select { |pod| pod[:stalled] } + print "\033[#{current_lines}A" # move the cursor all the way up to the start of the table + elsif previous_lines > 0 + print "\033[#{previous_lines}A" # move the cursor all the way up to the start of the table + end - if stalled_pods.empty? - UI.success("There are no stalled pods.") if feedback - else - run_command "kubectl delete pods #{stalled_pods.map { |pod| pod[:name] } .join(" ")}" - end - end - - def delete_all_pods - run_command "kubectl delete pods --all" - end - - def delete_pods(args) - run_command "kubectl delete pods #{args.join(" ")}" - end - - def apply_pods - run_command "kubectl apply -f ~/development/spend-cloud/k8s/" - end - - def update_config - if SctCore::Helper.operatingSystem == SctCore::Helper::WINDOWS - windows_home_path = SctCore::Helper.windowsHomePath - kube_file_path = windows_home_path+"/.kube/config" - - if !File.exists?(kube_file_path) - return UI.error("#{kube_file_path} doesn't exist") + pods_status_lines.each do |line| + print "#{line}\033[K#{$/}" # print the content of the line, clear remaining characters and add a new line end - run_command "sed -e 's~\\\\~/~g' -e 's~C:~/mnt/c~g' < #{kube_file_path} > ~/.kube/minikube-config" + previous_lines = current_lines - UI.success("#{kube_file_path} copied to ~/.kube/minikube-config") + sleep 5 end - run_command "kubectl config use-context minikube" + previous_lines.times do + print "\033[1A\033[K" # move the cursor up a line and clear the line + end - run_command "kubectl replace -n kube-system -f #{File.expand_path('resources/corefile.yml', __dir__)}" - old_list = pods("kube-system").map { |pod| pod[:name] if pod[:name].start_with? "coredns" }.compact - run_command "kubectl delete pod -n kube-system #{old_list.join(" ")}" unless old_list.to_a.empty? - run_command "kubectl rollout status -n kube-system deployment/coredns" + UI.success("Pods are now ready.") end def deployments(namespace = "default") output = `kubectl get deployments -n #{namespace}` @@ -148,17 +187,19 @@ # get name and status of each pod lines.map do |line| columns = line.split(" ") name = columns[0] + ready = columns[1].split("/").reduce { |l, r| l == r } + replicas = columns[1] status = columns[2] - stalled = status == "ErrImagePull" || status == "ImagePullBackOff" { name: name, - status: status, - stalled: stalled + ready: ready, + replicas: replicas, + status: status } end end def create_secrets @@ -191,22 +232,10 @@ end UI.success("Ingress IP is now available.") end - def status - print_contexts - print_minikube_status - - if get_minikube_status.find_all { |status| status[1] == 'Stopped' }.count == 0 - print_pods_status("kube-system") - print_pods_status - else - UI.important("Please check your minikube status. If all services are stopped you should start the minikube first.") - end - end - def print_contexts output = `kubectl config get-contexts` lines = output.split "\n" lines = lines[1..-1] @@ -221,16 +250,15 @@ puts Terminal::Table.new title: "Contexts".green, headings: ['Cluster', 'Using context'], rows: rows end def print_minikube_status - puts Terminal::Table.new title: "Minikube status".green, headings: ['Name', 'Status'], rows: get_minikube_status end def get_minikube_status - output = `#{SctCore::Helper.minikube} status` + output = `minikube status` lines = output.split "\n" rows = lines.map do |line| columns = line.split(" ") @@ -238,28 +266,35 @@ [columns[0][0..-2], columns[1]] end end def print_pods_status(namespace = "default") + output = get_pods_status(namespace) - pods_list = pods(namespace) + puts output if output + end - if pods_list.to_a.empty? - return - end + def get_pods_status(namespace = "default") + rows = pods(namespace).map do |pod| + status = pod[:status] + replicas = pod[:replicas] - rows = pods_list.map do |pod| [ pod[:name], - pod[:status] == "Running" ? pod[:status].green : pod[:status].red + status == "Running" ? status.green : status.red, + pod[:ready] ? replicas.green : replicas.red ] end - puts Terminal::Table.new title: "Pods (namespace: #{namespace})".green, headings: ['Name', 'Status'], rows: rows + if rows.empty? + return + end + + return Terminal::Table.new title: "Pods (namespace: #{namespace})".green, headings: ['Name', 'Status', 'Replicas ready'], rows: rows end - def run_command command - if ! system command + def run_command command, options = {} + if ! system command, options raise command.red end end end end