Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
moklidia committed Oct 30, 2023
2 parents 1722724 + 74b0085 commit 7882d54
Show file tree
Hide file tree
Showing 26 changed files with 377 additions and 96 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
uffizzi-cli (2.2.2)
uffizzi-cli (2.3.0)
activesupport
awesome_print
faker
Expand Down
5 changes: 5 additions & 0 deletions lib/uffizzi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require 'active_support'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/object/blank'
require 'launchy'

require 'thor'
require 'uffizzi/error'
Expand Down Expand Up @@ -52,5 +53,9 @@ def thread
def at_exit(&block)
Kernel.at_exit(&block)
end

def launchy
Launchy
end
end
end
105 changes: 20 additions & 85 deletions lib/uffizzi/cli/cluster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
require 'uffizzi/helpers/config_helper'
require 'uffizzi/services/preview_service'
require 'uffizzi/services/cluster_service'
require 'uffizzi/services/cluster/common_service'
require 'uffizzi/services/cluster/create_service'
require 'uffizzi/services/cluster/delete_service'
require 'uffizzi/services/cluster/list_service'
require 'uffizzi/services/cluster/update_kubeconfig_service'
require 'uffizzi/services/kubeconfig_service'
require 'uffizzi/services/cluster/disconnect_service'

Expand Down Expand Up @@ -164,31 +169,11 @@ def handle_delete_command(command_args)

return handle_delete_cluster(cluster_name) unless is_delete_kubeconfig

cluster_data = ClusterService.fetch_cluster_data(cluster_name, **cluster_api_connection_params)
kubeconfig = parse_kubeconfig(cluster_data[: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)
exclude_kubeconfig(cluster_data[:id], kubeconfig) if kubeconfig.present?
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|
if kubeconfig_by_path.nil?
msg = "Warning: kubeconfig at path #{kubeconfig_path} does not exist"
return Uffizzi.ui.say(msg)
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
KubeconfigService.update_current_context(new_kubeconfig, new_current_context)
end
ClusterDeleteService.exclude_kubeconfig(cluster_data[:id], kubeconfig) if kubeconfig.present?
end

def handle_delete_cluster(cluster_name)
Expand All @@ -211,10 +196,10 @@ def handle_update_kubeconfig_command(command_args)
cluster_data = ClusterService.fetch_cluster_data(cluster_name, **cluster_api_connection_params)

unless cluster_data[:kubeconfig].present?
say_error_update_kubeconfig(cluster_data)
ClusterUpdateKubeconfigService.say_error_update_kubeconfig(cluster_data)
end

parsed_kubeconfig = parse_kubeconfig(cluster_data[:kubeconfig])
parsed_kubeconfig = ClusterCommonService.parse_kubeconfig(cluster_data[:kubeconfig])

return Uffizzi.ui.say(parsed_kubeconfig.to_yaml) if options[:print]

Expand All @@ -226,11 +211,11 @@ def handle_update_kubeconfig_command(command_args)
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)
ClusterCommonService.save_previous_current_context(kubeconfig_path, previous_current_context)
new_kubeconfig
end

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

return if options[:quiet]

Expand Down Expand Up @@ -287,10 +272,9 @@ def say_error_update_kubeconfig(cluster_data)
end

def cluster_creation_params(cluster_name)
manifest_content = load_manifest_file(options[:manifest])
creation_source = options[:"creation-source"] || ClusterService::MANUAL_CREATION_SOURCE
manifest_file_path = options[:manifest]
k8s_version = options[:"k8s-version"]
manifest_content = load_manifest_file(manifest_file_path)

{
cluster: {
Expand Down Expand Up @@ -327,32 +311,19 @@ def handle_succeed_list_response(response)
raise Uffizzi::Error.new('The project has no active clusters') if clusters.empty?

clusters_data = if Uffizzi.ui.output_format.nil?
render_plain_cluster_list(clusters)
ClusterListService.render_plain_clusters(clusters)
else
clusters.map { |c| c.slice(:name, :project) }
end

Uffizzi.ui.say(clusters_data)
end

def render_plain_cluster_list(clusters)
clusters.map do |cluster|
project_name = cluster.dig(:project, :name)

if project_name.present?
"- Cluster name: #{cluster[:name].strip} Project name: #{project_name.strip}"
else
"- #{cluster[:name]}"
end
end.join("\n")
end

def handle_succeed_create_response(cluster_data)
kubeconfig_path = options[:kubeconfig] || KubeconfigService.default_path
is_update_current_context = options[:'update-current-context']
parsed_kubeconfig = parse_kubeconfig(cluster_data[:kubeconfig])
rendered_cluster_data = render_cluster_data(cluster_data)
cluster_name = cluster_data[:name]
parsed_kubeconfig = ClusterCommonService.parse_kubeconfig(cluster_data[:kubeconfig])
rendered_cluster_data = build_render_cluster_data!(cluster_data)

Uffizzi.ui.enable_stdout
Uffizzi.ui.say("Cluster with name: #{rendered_cluster_data[:name]} was created.")
Expand All @@ -363,42 +334,13 @@ def handle_succeed_create_response(cluster_data)

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

save_kubeconfig(parsed_kubeconfig, kubeconfig_path)
update_clusters_config(cluster_data[:id], name: cluster_name, kubeconfig_path: kubeconfig_path)
ClusterCreateService.save_kubeconfig(parsed_kubeconfig, kubeconfig_path, 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

def save_kubeconfig(kubeconfig, kubeconfig_path)
is_update_current_context = options[:'update-current-context']

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

if is_update_current_context
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
else
merged_kubeconfig
end
end

Uffizzi.ui.say("Kubeconfig was updated by the path: #{kubeconfig_path}") if is_update_current_context
end

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

def render_cluster_data(cluster_data)
kubeconfig = parse_kubeconfig(cluster_data[:kubeconfig])
def build_render_cluster_data!(cluster_data)
kubeconfig = ClusterCommonService.parse_kubeconfig(cluster_data[:kubeconfig])
raise Uffizzi::Error.new('The kubeconfig data is empty') unless kubeconfig

new_cluster_data = cluster_data.slice(:name)
Expand All @@ -413,13 +355,6 @@ def parse_kubeconfig(kubeconfig)
Psych.safe_load(Base64.decode64(kubeconfig))
end

def save_previous_current_context(kubeconfig_path, current_context)
return if kubeconfig_path.nil? || ConfigHelper.previous_current_context_by_path(kubeconfig_path).present?

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 handle_missing_cluster_name_error
Uffizzi.ui.say("No kubeconfig found at #{KubeconfigService.default_path}")
Uffizzi.ui.say('Please update the current context or provide a cluster name.')
Expand Down
4 changes: 4 additions & 0 deletions lib/uffizzi/cli/dev.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ module Uffizzi
class Cli::Dev < Thor
include ApiClient

desc 'ingress', 'Show the compose dev environment ingress info'
require_relative 'dev/ingress'
subcommand 'ingress', Uffizzi::Cli::Dev::Ingress

desc 'start [CONFIG]', 'Start dev environment'
method_option :quiet, type: :boolean, aliases: :q
method_option :'default-repo', type: :string
Expand Down
42 changes: 42 additions & 0 deletions lib/uffizzi/cli/dev/ingress.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

require 'uffizzi'
require 'uffizzi/auth_helper'
require 'uffizzi/response_helper'

module Uffizzi
class Cli::Dev::Ingress < Thor
include ApiClient

desc 'open', 'Open dev environment hosts'
def open
Uffizzi::AuthHelper.check_login
DevService.check_running_process!

if DevService.startup?
Uffizzi.ui.say_error_and_exit('Dev environment not started yet')
end

dev_environment = DevService.dev_environment
cluster_name = dev_environment[:cluster_name]
params = { cluster_name: cluster_name }
response = get_cluster_ingresses(server, project_slug, params)

return ResponseHelper.handle_failed_response(response) unless ResponseHelper.ok?(response)

ingress_hosts = response.dig(:body, :ingresses)
urls = ingress_hosts.map { |host| "https://#{host}" }
urls.each { |url| Uffizzi.launchy.open(url) { Uffizzi.ui.say(url) } }
end

private

def server
@server ||= ConfigFile.read_option(:server)
end

def project_slug
@project_slug ||= ConfigFile.read_option(:project)
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 @@ -293,6 +293,13 @@ def get_cluster(server, project_slug, params)
build_response(response)
end

def get_cluster_ingresses(server, project_slug, params)
uri = project_cluster_ingresses_uri(server, project_slug, cluster_name: params[:cluster_name], oidc_token: params[:oidc_token])
response = http_client.make_get_request(uri)

build_response(response)
end

def get_access_token(server, code)
uri = access_token_url(server, code)
response = http_client.make_get_request(uri)
Expand Down
6 changes: 6 additions & 0 deletions lib/uffizzi/clients/api/api_routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ def project_clusters_uri(server, project_slug, oidc_token:)
"#{server}/api/cli/v1/projects/#{project_slug}/clusters?token=#{oidc_token}"
end

def project_cluster_ingresses_uri(server, project_slug, cluster_name:, oidc_token:)
url = "#{server}/api/cli/v1/projects/#{project_slug}/clusters/#{cluster_name}/ingresses"

oidc_token.nil? ? url : url + "?token=#{oidc_token}"
end

def cluster_uri(server, project_slug, cluster_name:, oidc_token:)
return "#{server}/api/cli/v1/projects/#{project_slug}/clusters/#{cluster_name}" if oidc_token.nil?

Expand Down
25 changes: 25 additions & 0 deletions lib/uffizzi/services/cluster/common_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

require 'uffizzi/helpers/config_helper'

class ClusterCommonService
class << self
def save_previous_current_context(kubeconfig_path, current_context)
return if kubeconfig_path.nil? || Uffizzi::ConfigHelper.previous_current_context_by_path(kubeconfig_path).present?

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

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

def parse_kubeconfig(kubeconfig)
return if kubeconfig.nil?

Psych.safe_load(Base64.decode64(kubeconfig))
end
end
end
29 changes: 29 additions & 0 deletions lib/uffizzi/services/cluster/create_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

require 'uffizzi/helpers/config_helper'
require 'uffizzi/services/cluster/common_service'
require 'uffizzi/services/kubeconfig_service'

class ClusterCreateService
class << self
def save_kubeconfig(kubeconfig, kubeconfig_path, is_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
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)
ClusterCommonService.save_previous_current_context(kubeconfig_path, previous_current_context)
new_kubeconfig
else
merged_kubeconfig
end
end
end
end
end
28 changes: 28 additions & 0 deletions lib/uffizzi/services/cluster/delete_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require 'uffizzi/helpers/config_helper'
require 'uffizzi/services/kubeconfig_service'

class ClusterDeleteService
class << self
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]
Uffizzi::ConfigFile.write_option(:clusters, Uffizzi::ConfigHelper.clusters_config_without(cluster_id))

KubeconfigService.save_to_filepath(kubeconfig_path, kubeconfig) do |kubeconfig_by_path|
if kubeconfig_by_path.nil?
msg = "Warning: kubeconfig at path #{kubeconfig_path} does not exist"
return Uffizzi.ui.say(msg)
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
KubeconfigService.update_current_context(new_kubeconfig, new_current_context)
end
end
end
end
20 changes: 20 additions & 0 deletions lib/uffizzi/services/cluster/list_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

class ClusterListService
class << self
# REFACTOR_ME:
# Uffizzi.ui.output_format = Uffizzi::UI::Shell::PRETTY_LIST
# Uffizzi.ui.say(data)
def render_plain_clusters(clusters)
clusters.map do |cluster|
project_name = cluster.dig(:project, :name)

if project_name.present?
"- Cluster name: #{cluster[:name].strip} Project name: #{project_name.strip}"
else
"- #{cluster[:name]}"
end
end.join("\n")
end
end
end
Loading

0 comments on commit 7882d54

Please sign in to comment.