Skip to content

Commit

Permalink
[364_cli] Add check before dev cluster start
Browse files Browse the repository at this point in the history
  • Loading branch information
zipofar committed Dec 14, 2023
1 parent 45f77be commit 8bef3ba
Show file tree
Hide file tree
Showing 21 changed files with 291 additions and 132 deletions.
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ services:
- ~/.ssh:/root/.ssh
- ~/.bash_history:/root/.bash_history
- ~/.config/uffizzi:/root/.config/uffizzi
- ~/test/uffizzi_app/charts/uffizzi-app:/gem/tmp/charts/uffizzi_app
- ~/test/uffizzi_controller_os/charts/uffizzi-controller:/gem/tmp/charts/uffizzi-controller
- bundle_cache:/bundle_cache
environment:
- BUNDLE_PATH=/bundle_cache
Expand Down
1 change: 1 addition & 0 deletions lib/uffizzi/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def handle_repl_exceptions(exception)
when Interrupt
nil
when StandardError
puts exception.backtrace
raise Uffizzi::CliError.new(exception.message)
else
raise exception
Expand Down
28 changes: 10 additions & 18 deletions lib/uffizzi/cli/cluster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,29 +166,21 @@ def handle_describe_command(command_args)
def handle_delete_command(command_args)
cluster_name = command_args[:cluster_name]
is_delete_kubeconfig = options[:'delete-config']
cluster_data = ClusterService.fetch_cluster_data(command_args[:cluster_name], **cluster_api_connection_params)

return handle_delete_cluster(cluster_name) unless is_delete_kubeconfig
return handle_delete_dev_cluster(cluster_name) if ClusterService.dev_cluster?(cluster_data)
return ClusterDeleteService.delete(cluster_name, cluster_api_connection_params) unless is_delete_kubeconfig

cluster_data = ClusterService.fetch_cluster_data(command_args[:cluster_name], **cluster_api_connection_params)
kubeconfig = ClusterCommonService.parse_kubeconfig(cluster_data[:kubeconfig])

handle_delete_cluster(cluster_name)
ClusterDeleteService.delete(cluster_name, cluster_api_connection_params)
ClusterDeleteService.exclude_kubeconfig(cluster_data[:id], kubeconfig) if kubeconfig.present?
DevService.clear_dev_environment_config if DevService.dev_environment[:cluster_name] == cluster_name
end

def handle_delete_cluster(cluster_name)
params = {
cluster_name: cluster_name,
oidc_token: oidc_token,
}
response = delete_cluster(server, project_slug, params)
def handle_delete_dev_cluster(cluster_name)
question = 'You delete dev cluster. Continue?'
return unless Uffizzi.prompt.yes?(question)

if ResponseHelper.no_content?(response)
Uffizzi.ui.say("Cluster #{cluster_name} deleted")
else
ResponseHelper.handle_failed_response(response)
end
ClusterDeleteService.delete(cluster_name, cluster_api_connection_params)
end

def handle_update_kubeconfig_command(command_args)
Expand Down Expand Up @@ -216,7 +208,7 @@ def handle_update_kubeconfig_command(command_args)
new_kubeconfig
end

ClusterCommonService.update_clusters_config(cluster_data[:id], kubeconfig_path: kubeconfig_path)
ClusterCommonService.update_clusters_config(cluster_data[:id], name: cluster_data[:name], kubeconfig_path: kubeconfig_path)

return if options[:quiet]

Expand Down Expand Up @@ -335,7 +327,7 @@ def handle_succeed_create_response(cluster_data)

Uffizzi.ui.say(rendered_cluster_data) if Uffizzi.ui.output_format

ClusterCreateService.save_kubeconfig(parsed_kubeconfig, kubeconfig_path, is_update_current_context)
ClusterCreateService.save_kubeconfig(parsed_kubeconfig, kubeconfig_path, update_current_context: is_update_current_context)
ClusterCommonService.update_clusters_config(cluster_data[:id], name: cluster_data[:name], kubeconfig_path: kubeconfig_path)
GithubService.write_to_github_env(rendered_cluster_data) if GithubService.github_actions_exists?
end
Expand Down
131 changes: 46 additions & 85 deletions lib/uffizzi/cli/dev.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'uffizzi/services/cluster_service'
require 'uffizzi/services/cluster/delete_service'
require 'uffizzi/services/dev_service'
require 'uffizzi/services/kubeconfig_service'
require 'uffizzi/auth_helper'
Expand Down Expand Up @@ -55,16 +56,34 @@ def run(command, command_args = {})
end

def handle_start_command(command_args)
config_path = command_args[:config_path]
DevService.check_skaffold_existence
DevService.check_no_running_process!

config_path = command_args[:config_path]
DevService.check_skaffold_config_existence(config_path)
dev_cluster = DevService.account_user_project_dev_cluster(server, account_id, project_slug)

if try_to_start_second_dev_env?(dev_cluster)
msg = 'Dev cluster already exists. ' \
"Before you create a new dev cluster, you must delete the existing one: $ uffizzi cluster delete #{dev_cluster[:name]}"
Uffizzi.ui.say_error_and_exit(msg)
end

if dev_cluster_already_deleted?(dev_cluster)
DevService.clear_after_delete(dev_environment[:cluster_id], dev_environment[:encoded_kubeconfig])
answer = Uffizzi.prompt.yes?('The previous development environment has been deleted. Do you want to start a new one?')

if dev_environment.empty?
return unless answer
end

DevService.check_no_running_process!

unless DevService.dev_environment_exist?
DevService.set_startup_state
cluster_name = start_create_cluster
wait_cluster_creation(cluster_name)
DevService.set_dev_environment_config(cluster_name, config_path, options)
cluster_data = wait_cluster_creation(cluster_name)
DevService.set_dev_environment_config(cluster_name, config_path: config_path,
cluster_id: cluster_data[:id],
encoded_kubeconfig: cluster_data[:kubeconfig])
DevService.set_cluster_deployed_state
end

Expand Down Expand Up @@ -101,8 +120,8 @@ def handle_delete_command
end

cluster_data = fetch_dev_env_cluster!
handle_delete_cluster(cluster_data)
DevService.clear_dev_environment_config
ClusterDeleteService.delete(cluster_data[:name], cluster_api_connection_params)
DevService.clear_after_delete(cluster_data[:id], cluster_data[:kubeconfig])
end

def start_create_cluster
Expand All @@ -127,33 +146,15 @@ def wait_cluster_creation(cluster_name)

def handle_succeed_cluster_creation(cluster_data)
kubeconfig_path = options[:kubeconfig] || KubeconfigService.default_path
parsed_kubeconfig = parse_kubeconfig(cluster_data[:kubeconfig])
parsed_kubeconfig = ClusterCommonService.parse_kubeconfig(cluster_data[:kubeconfig])
cluster_name = cluster_data[:name]

Uffizzi.ui.say("Cluster with name: #{cluster_name} was created.")

save_kubeconfig(parsed_kubeconfig, kubeconfig_path)
update_clusters_config(cluster_data[:id], name: cluster_name, kubeconfig_path: kubeconfig_path)
end

def save_kubeconfig(kubeconfig, kubeconfig_path)
KubeconfigService.save_to_filepath(kubeconfig_path, kubeconfig) do |kubeconfig_by_path|
merged_kubeconfig = KubeconfigService.merge(kubeconfig_by_path, kubeconfig)
ClusterCreateService.save_kubeconfig(parsed_kubeconfig, kubeconfig_path, update_current_context: true)
ClusterCommonService.update_clusters_config(cluster_data[:id], name: cluster_name, kubeconfig_path: kubeconfig_path)

new_current_context = KubeconfigService.get_current_context(kubeconfig)
new_kubeconfig = KubeconfigService.update_current_context(merged_kubeconfig, new_current_context)

next new_kubeconfig if kubeconfig_by_path.nil?

previous_current_context = KubeconfigService.get_current_context(kubeconfig_by_path)
save_previous_current_context(kubeconfig_path, previous_current_context)
new_kubeconfig
end
end

def update_clusters_config(id, params)
clusters_config = Uffizzi::ConfigHelper.update_clusters_config_by_id(id, params)
ConfigFile.write_option(:clusters, clusters_config)
cluster_data
end

def cluster_creation_params
Expand All @@ -163,66 +164,12 @@ def cluster_creation_params
manifest: nil,
creation_source: ClusterService::MANUAL_CREATION_SOURCE,
k8s_version: options[:"k8s-version"],
kind: ClusterService::DEV_CLUSTER_KIND,
},
token: oidc_token,
}
end

def handle_delete_cluster(cluster_data)
cluster_id = cluster_data[:id]
cluster_name = cluster_data[:name]
kubeconfig = parse_kubeconfig(cluster_data[:kubeconfig])

exclude_kubeconfig(cluster_id, kubeconfig) if kubeconfig.present?

params = {
cluster_name: cluster_name,
oidc_token: oidc_token,
}
response = delete_cluster(server, project_slug, params)

if ResponseHelper.no_content?(response)
Uffizzi.ui.say("Cluster #{cluster_name} deleted")
else
ResponseHelper.handle_failed_response(response)
end
end

def exclude_kubeconfig(cluster_id, kubeconfig)
cluster_config = Uffizzi::ConfigHelper.cluster_config_by_id(cluster_id)
return if cluster_config.nil?

kubeconfig_path = cluster_config[:kubeconfig_path]
ConfigFile.write_option(:clusters, Uffizzi::ConfigHelper.clusters_config_without(cluster_id))

KubeconfigService.save_to_filepath(kubeconfig_path, kubeconfig) do |kubeconfig_by_path|
return if kubeconfig_by_path.nil?

new_kubeconfig = KubeconfigService.exclude(kubeconfig_by_path, kubeconfig)
new_current_context = find_previous_current_context(new_kubeconfig, kubeconfig_path)
KubeconfigService.update_current_context(new_kubeconfig, new_current_context)
end
end

def find_previous_current_context(kubeconfig, kubeconfig_path)
prev_current_context = Uffizzi::ConfigHelper.previous_current_context_by_path(kubeconfig_path)&.fetch(:current_context, nil)

if KubeconfigService.find_cluster_contexts_by_name(kubeconfig, prev_current_context).present?
prev_current_context
end
end

def save_previous_current_context(kubeconfig_path, current_context)
previous_current_contexts = Uffizzi::ConfigHelper.set_previous_current_context_by_path(kubeconfig_path, current_context)
ConfigFile.write_option(:previous_current_contexts, previous_current_contexts)
end

def parse_kubeconfig(kubeconfig)
return if kubeconfig.nil?

Psych.safe_load(Base64.decode64(kubeconfig))
end

def launch_demonise_skaffold(config_path)
Uffizzi.process.daemon(true)

Expand All @@ -233,6 +180,7 @@ def launch_demonise_skaffold(config_path)
DevService.save_pid
File.delete(DevService.logs_path) if File.exist?(DevService.logs_path)
DevService.start_check_pid_file_existence
DevService.run_check_cluster_existence(server, account_id, project_slug)
DevService.start_demonised_skaffold(config_path, options)
rescue StandardError => e
File.open(DevService.logs_path, 'a') { |f| f.puts(e.message) }
Expand All @@ -245,6 +193,7 @@ def launch_basic_skaffold(config_path)

DevService.save_pid
DevService.start_check_pid_file_existence
DevService.run_check_cluster_existence(server, account_id, project_slug)
DevService.start_basic_skaffold(config_path, options)
end

Expand All @@ -258,7 +207,15 @@ def fetch_dev_env_cluster!
end

def dev_environment
@dev_environment ||= DevService.dev_environment
DevService.dev_environment
end

def dev_cluster_already_deleted?(dev_cluster)
DevService.dev_environment_exist? && dev_cluster.blank?
end

def try_to_start_second_dev_env?(dev_cluster)
!DevService.dev_environment_exist? && dev_cluster.present?
end

def cluster_api_connection_params
Expand All @@ -280,5 +237,9 @@ def oidc_token
def server
@server ||= ConfigFile.read_option(:server)
end

def account_id
@account_id ||= ConfigFile.read_option(:account, :id)
end
end
end
7 changes: 7 additions & 0 deletions lib/uffizzi/clients/api/api_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,13 @@ def get_account_controller_settings(server, account_id)
build_response(response)
end

def get_account_user_project_clusters(server, account_id, project_slug, params = {})
uri = account_user_project_clusters_uri(server, account_id, project_slug, params)
response = http_client.make_get_request(uri)

build_response(response)
end

def create_account_controller_settings(server, account_id, params = {})
uri = account_controller_settings_uri(server, account_id)
response = http_client.make_post_request(uri, params)
Expand Down
21 changes: 21 additions & 0 deletions lib/uffizzi/clients/api/api_routes.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true

require 'uri'
require 'cgi'

module ApiRoutes
Expand Down Expand Up @@ -116,6 +117,12 @@ def cluster_uri(server, project_slug, cluster_name:, oidc_token:)
"#{server}/api/cli/v1/projects/#{project_slug}/clusters/#{cluster_name}?token=#{oidc_token}"
end

def account_user_project_clusters_uri(server, account_id, project_slug, params = {})
path = "/api/cli/v1/accounts/#{account_id}/user/projects/#{project_slug}/clusters"

build_uri(server, path, params)
end

def scale_up_cluster_uri(server, project_slug, cluster_name)
"#{server}/api/cli/v1/projects/#{project_slug}/clusters/#{cluster_name}/scale_up"
end
Expand Down Expand Up @@ -147,4 +154,18 @@ def account_controller_settings_uri(server, account_id)
def account_controller_setting_uri(server, account_id, id)
"#{server}/api/cli/v1/accounts/#{account_id}/controller_settings/#{id}"
end

private

def build_uri(server, path, params = {})
uri = URI.parse(server)
host = uri.scheme.nil? ? server : uri.host
query = URI.encode_www_form(params)

if uri.scheme == 'http'
URI::HTTP.build(host: host, path: path, query: query, port: uri.port).to_s
else
URI::HTTPS.build(host: host, path: path, query: query, port: uri.port).to_s
end
end
end
5 changes: 3 additions & 2 deletions lib/uffizzi/services/cluster/create_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

class ClusterCreateService
class << self
def save_kubeconfig(kubeconfig, kubeconfig_path, is_update_current_context)
def save_kubeconfig(kubeconfig, kubeconfig_path, update_current_context:)
kubeconfig_path = kubeconfig_path.nil? ? KubeconfigService.default_path : kubeconfig_path

KubeconfigService.save_to_filepath(kubeconfig_path, kubeconfig) do |kubeconfig_by_path|
merged_kubeconfig = KubeconfigService.merge(kubeconfig_by_path, kubeconfig)

if is_update_current_context
if update_current_context
new_current_context = KubeconfigService.get_current_context(kubeconfig)
new_kubeconfig = KubeconfigService.update_current_context(merged_kubeconfig, new_current_context)

Expand Down
29 changes: 27 additions & 2 deletions lib/uffizzi/services/cluster/delete_service.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# frozen_string_literal: true

require 'uffizzi/clients/api/api_client'
require 'uffizzi/response_helper'
require 'uffizzi/helpers/config_helper'
require 'uffizzi/services/kubeconfig_service'

class ClusterDeleteService
extend ApiClient

class << self
def exclude_kubeconfig(cluster_id, kubeconfig)
cluster_config = Uffizzi::ConfigHelper.cluster_config_by_id(cluster_id)
Expand All @@ -19,10 +23,31 @@ def exclude_kubeconfig(cluster_id, kubeconfig)
end

new_kubeconfig = KubeconfigService.exclude(kubeconfig_by_path, kubeconfig)
first_context = KubeconfigService.get_first_context(new_kubeconfig)
new_current_context = first_context.present? ? first_context['name'] : nil
new_current_context = find_previous_current_context(new_kubeconfig, kubeconfig_path)
KubeconfigService.update_current_context(new_kubeconfig, new_current_context)
end
end

def find_previous_current_context(kubeconfig, kubeconfig_path)
prev_current_context = Uffizzi::ConfigHelper.previous_current_context_by_path(kubeconfig_path)&.fetch(:current_context, nil)

if KubeconfigService.find_cluster_contexts_by_name(kubeconfig, prev_current_context).present?
prev_current_context
end
end

def delete(cluster_name, connection_params)
params = {
cluster_name: cluster_name,
oidc_token: connection_params[:oidc_token],
}
response = delete_cluster(connection_params[:server], connection_params[:project_slug], params)

if Uffizzi::ResponseHelper.no_content?(response)
Uffizzi.ui.say("Cluster #{cluster_name} deleted")
else
Uffizzi::ResponseHelper.handle_failed_response(response)
end
end
end
end
Loading

0 comments on commit 8bef3ba

Please sign in to comment.