lib/sct/commands/cluster.rb in sct-0.1.14 vs lib/sct/commands/cluster.rb in sct-0.1.15

- old
+ new

@@ -3,15 +3,15 @@ module Sct class ClusterCommand IS_PUBLIC_COMMAND = true - SYNTAX = 'sct cluster up | sct cluster down | sct cluster reset | sct cluster update-config' - SUMMARY = 'Starts/stops/resets or updates the config of the minikube cluster.' - EXAMPLE = 'sct cluster up | sct cluster down | sct cluster reset | sct cluster update-config' - EXAMPLE_DESCRIPTION = 'Starts/stops/resets or updates the config of the minikube cluster.' - DESCRIPTION = "sct cluster allows you to start, stop, reset or update the config of the Spend Cloud minikube cluster." + SYNTAX = 'sct cluster up | sct cluster down | sct cluster setup | sct cluster reset | sct cluster update-config | sct cluster delete-stalled-pods' + SUMMARY = 'Perform actions on the minikube cluster.' + EXAMPLE = 'sct cluster up | sct cluster down | sct cluster setup | sct cluster reset | sct cluster update-config | sct cluster delete-stalled-pods' + EXAMPLE_DESCRIPTION = 'Perform actions on the minikube cluster.' + DESCRIPTION = "sct cluster allows you to start, stop, setup/reset, update the config, or delete the stalled pods of the Spend Cloud minikube cluster." OPTIONS = [] def execute(args, options) return puts "SCT has not been initialized. Run 'sct init' first.".red unless Sct::Config.exists @@ -21,89 +21,169 @@ up when "down" down when "update-config" update_config - when "reset" + when "setup", "reset" reset + when "delete-stalled-pods" + delete_stalled_pods(feedback: true) else - puts "Unknown or missing argument. Please run 'sct cluster up','sct cluster down' or 'sct cluster update-config'".red + puts "Unknown or missing argument. Please run 'sct cluster up', 'sct cluster down', 'sct cluster setup', 'sct cluster reset', 'sct cluster update-config', or 'sct cluster delete-stalled-pods'.".red end end def up start - system "kubectl delete pod -n kube-system $(kubectl get pods -n kube-system | grep registry-creds | awk '{print $1}')" - system "kubectl rollout status -n kube-system deployment/registry-creds" + 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" post_start end def down - system "#{minikube} stop" + run_command "#{minikube} stop" end + def reset + run_command "#{minikube} delete" + start + create_secrets + run_command "#{minikube} addons enable registry-creds" + run_command "#{minikube} addons enable ingress" + run_command "kubectl rollout status -n kube-system deployment/registry-creds" + run_command "kubectl rollout status -n kube-system deployment/nginx-ingress-controller" + 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 update_config if Sct::Helpers.operatingSystem == Sct::Helpers::WINDOWS windows_home_path = Sct::Helpers.windowsHomePath kube_file_path = windows_home_path+"/.kube/config" if !File.exists?(kube_file_path) return puts "#{kube_file_path} doesn't exist".red end - system("sed -e 's~\\\\~/~g' -e 's~C:~/mnt/c~g' < #{kube_file_path} > ~/.kube/minikube-config") + run_command "sed -e 's~\\\\~/~g' -e 's~C:~/mnt/c~g' < #{kube_file_path} > ~/.kube/minikube-config" puts "#{kube_file_path} copied to ~/.kube/minikube-config".green end - system "kubectl config use-context minikube" + 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 delete pod -n kube-system #{pods("kube-system").map { |pod| pod[:name] if pod[:name].start_with? "coredns" } .compact.join(" ")}" + run_command "kubectl rollout status -n kube-system deployment/coredns" end - def reset - system "#{minikube} delete" - start - system "kubectl create secret generic gcloud-credentials --from-file=\"$(echo ~)/.config/gcloud/application_default_credentials.json\"" - system "kubectl create secret generic -n kube-system registry-creds-dpr --from-literal DOCKER_PRIVATE_REGISTRY_PASSWORD=changeme --from-literal DOCKER_PRIVATE_REGISTRY_SERVER=changeme --from-literal DOCKER_PRIVATE_REGISTRY_USER=changeme" - system "kubectl patch secret -n kube-system registry-creds-dpr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"dpr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" - system "kubectl create secret generic -n kube-system registry-creds-ecr --from-literal AWS_ACCESS_KEY_ID=changeme --from-literal AWS_SECRET_ACCESS_KEY=changeme --from-literal AWS_SESSION_TOKEN=\"\" --from-literal aws-account=changeme --from-literal aws-assume-role=changeme --from-literal aws-region=changeme" - system "kubectl patch secret -n kube-system registry-creds-ecr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"ecr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" - system "kubectl create secret generic -n kube-system registry-creds-gcr --from-file=\"$(echo ~)/.config/gcloud/application_default_credentials.json\" --from-literal=gcrurl=\"https://eu.gcr.io\"" - system "kubectl patch secret -n kube-system registry-creds-gcr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"gcr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" - system "kubectl create secret generic -n kube-system registry-creds-acr --from-literal ACR_PASSWORD=changeme --from-literal ACR_CLIENT_ID=changeme --from-literal ACR_URL=changeme" - system "kubectl patch secret -n kube-system registry-creds-acr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"acr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" - system "#{minikube} addons enable registry-creds" - system "#{minikube} addons enable ingress" - system "kubectl rollout status -n kube-system deployment/registry-creds" - system "kubectl rollout status -n kube-system deployment/nginx-ingress-controller" - wait_for_gcr_secret - system "kubectl apply -f ~/development/spend-cloud/k8s/" - post_start + def delete_stalled_pods(feedback: false) + stalled_pods = pods.select { |pod| pod[:stalled] } + + if stalled_pods.empty? + puts "There are no stalled pods.".green if feedback + else + run_command "kubectl delete pods #{stalled_pods.map { |pod| pod[:name] } .join(" ")}" + end end def start - system "#{minikube} start --cpus=$(cat /proc/cpuinfo | grep processor | wc -l) --memory=16G" - system "#{minikube} ssh -- 'sudo su -c \"echo 10048576 > /proc/sys/fs/inotify/max_user_watches\"'" + if Sct::Helpers.operatingSystem == Sct::Helpers::MAC_OS + run_command "#{minikube} start --cpus=$(sysctl -n hw.ncpu) --memory=8G" + else + run_command "#{minikube} start --cpus=$(cat /proc/cpuinfo | grep processor | wc -l) --memory=10G" + end + run_command "#{minikube} ssh -- 'sudo su -c \"echo 10048576 > /proc/sys/fs/inotify/max_user_watches\"'" update_config end def post_start - system "kubectl rollout status deployment/spend-cloud-api" - system "sudo sct hostfile" - puts "\nāœ”ļø You can visit your environment at šŸ‘‰ https://spend-cloud.spend.cloud.local šŸ‘Œ (might still take a few minutes)" + wait_for_pods + run_command "sudo sct hostfile" + puts "\nāœ”ļø You can visit your environment at šŸ‘‰ https://spend-cloud.spend.cloud.local šŸ‘Œ" end + def create_secrets + run_command "kubectl create secret generic gcloud-credentials --from-file=\"$(echo ~)/.config/gcloud/application_default_credentials.json\"" + run_command "kubectl create secret generic -n kube-system registry-creds-dpr --from-literal DOCKER_PRIVATE_REGISTRY_PASSWORD=changeme --from-literal DOCKER_PRIVATE_REGISTRY_SERVER=changeme --from-literal DOCKER_PRIVATE_REGISTRY_USER=changeme" + run_command "kubectl patch secret -n kube-system registry-creds-dpr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"dpr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" + run_command "kubectl create secret generic -n kube-system registry-creds-ecr --from-literal AWS_ACCESS_KEY_ID=changeme --from-literal AWS_SECRET_ACCESS_KEY=changeme --from-literal AWS_SESSION_TOKEN=\"\" --from-literal aws-account=changeme --from-literal aws-assume-role=changeme --from-literal aws-region=changeme" + run_command "kubectl patch secret -n kube-system registry-creds-ecr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"ecr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" + run_command "kubectl create secret generic -n kube-system registry-creds-gcr --from-file=\"$(echo ~)/.config/gcloud/application_default_credentials.json\" --from-literal=gcrurl=\"https://eu.gcr.io\"" + run_command "kubectl patch secret -n kube-system registry-creds-gcr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"gcr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" + run_command "kubectl create secret generic -n kube-system registry-creds-acr --from-literal ACR_PASSWORD=changeme --from-literal ACR_CLIENT_ID=changeme --from-literal ACR_URL=changeme" + run_command "kubectl patch secret -n kube-system registry-creds-acr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"acr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'" + end + def wait_for_gcr_secret puts "Waiting for Google Cloud Registry secret to become available...".yellow - while true - secrets = `kubectl get secrets` + while ! `kubectl get secrets`.include? "gcr-secret" + sleep 5 + end - if secrets.include? "gcr-secret" - puts "Google Cloud Registry secret is now available.".green - break - else - sleep 1 - end + puts "Google Cloud Registry secret is now available.".green + end + + def wait_for_ingress_ip + puts "Waiting for ingress IP to become available...".yellow + + while `kubectl describe ingress | grep "Address" | awk '{print $2}'`.empty? + sleep 5 + end + + puts "Ingress IP is now available.".green + end + + def wait_for_pods + puts "Waiting for pods to become ready...".yellow + + while ! pods.all? { |pod| pod[:status] == "Running" } + delete_stalled_pods + + sleep 5 + end + + puts "Pods are now ready.".green + end + + def pods(namespace = nil) + if namespace + output = `kubectl get pods -n #{namespace}` + else + output = `kubectl get pods` + end + + # split output lines + lines = output.split "\n" + + # exclude first line (table header) + lines = lines[1..-1] + + # get name and status of each pod + lines.map do |line| + columns = line.split(" ") + + name = columns[0] + status = columns[2] + stalled = status == "ErrImagePull" || status == "ImagePullBackOff" + + { + name: name, + status: status, + stalled: stalled + } + end + end + + def run_command command + if ! system command + raise command.red end end def minikube if Sct::Helpers.operatingSystem == Sct::Helpers::WINDOWS