Skip to content

Commit

Permalink
cmu: Add an option to disable Kubernetes support
Browse files Browse the repository at this point in the history
It might seem counter-intuitive to disable Kubernetes support
in a toolkit meant for managing Kubernetes clusters, but just
in case you only want to use cmu to run Ansible playbooks
and look at logs this option allows for removing the slowdown
during startup spent while trying to connect to the API-server.

Signed-off-by: David Weinehall <[email protected]>
  • Loading branch information
taotriad committed Jul 18, 2023
1 parent 89c53dd commit deeb9ae
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 24 deletions.
95 changes: 72 additions & 23 deletions cmu
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ initial_container = None
# Is cmu running in read only-mode?
read_only_mode = False

# Is Kubernetes support enabled
kubernetes_support = True

# Namespace
selected_namespace = ""

Expand All @@ -129,7 +132,9 @@ def init_kubernetes_client() -> None:
"""

global kh # pylint: disable=global-statement
kh = KubernetesHelper(about.PROGRAM_SUITE_NAME, about.PROGRAM_SUITE_VERSION, None)

if kubernetes_support:
kh = KubernetesHelper(about.PROGRAM_SUITE_NAME, about.PROGRAM_SUITE_VERSION, None)

override_tail_lines = None
default_tail_lines = 4000
Expand All @@ -139,6 +144,9 @@ def gather_cluster_info() -> None:
Gather information about the cluster necessary for running playbooks
"""

if not kubernetes_support:
return

ansithemeprint([ANSIThemeString("[Gathering cluster information]\n", "phase")])

# Set global variables that need to be available when executing playbooks
Expand Down Expand Up @@ -4180,12 +4188,16 @@ def get_inventory_list(**kwargs: Dict) -> Tuple[List[Dict], int, Any, Callable,

control_plane_node, control_plane_name = get_control_plane()

node_vlist, status = kh.get_list_by_kind_namespace(("Node", ""), "")
for node in node_vlist:
roles = kh.get_node_roles(node)
if "control-plane" in roles:
continue
nodes.append(deep_get(node, DictPath("metadata#name")))
if kubernetes_support:
node_vlist, status = kh.get_list_by_kind_namespace(("Node", ""), "")
for node in node_vlist:
roles = kh.get_node_roles(node)
if "control-plane" in roles:
continue
nodes.append(deep_get(node, DictPath("metadata#name")))
else:
nodes = []
status = 200

if len(nodes) > 0:
ansible_add_hosts(ANSIBLE_INVENTORY, nodes, group = "nodes")
Expand Down Expand Up @@ -4375,6 +4387,9 @@ def get_node_info(vlist, extra_vars) -> List[Type]:

# To make the failure case easier, return both the ref and the name of the control plane
def get_control_plane() -> Tuple[Dict, str]:
if not kubernetes_support:
return None, ""

vlist, status = kh.get_list_by_kind_namespace(("Node", ""), "")
control_planes = []

Expand Down Expand Up @@ -11102,7 +11117,11 @@ def format_selection_list(uip: UIProps, refresh_apis = False):
# Repopulate the list of views, on the offhand chance that a view file has been added
populate_views(force_refresh = refresh_apis)
curses.doupdate()
available_api_families, _status, _modified = kh.get_available_kinds()

if kubernetes_support:
available_api_families, _status, _modified = kh.get_available_kinds()
else:
available_api_families = {}

items = []
order = []
Expand Down Expand Up @@ -11295,15 +11314,19 @@ listviewactions = {
infoviews = {} # type: ignore

# These functions are used to check whether an API is available
def is_kubernetes_supported() -> bool:
return kubernetes_support

def is_cluster_reachable() -> bool:
reachable = False

if kh is not None:
if kubernetes_support and kh is not None:
reachable = kh.is_cluster_reachable()
return reachable

availability_checker_allowlist = {
"is_cluster_reachable": is_cluster_reachable
"is_cluster_reachable": is_cluster_reachable,
"is_kubernetes_supported": is_kubernetes_supported,
}

# action calls acceptable for direct use in view files
Expand Down Expand Up @@ -11523,7 +11546,11 @@ def map_key(view_file: str, shortcut: str, activatedfun, key: str, modifier: str
def populate_views(force_refresh: bool = False) -> None:
global views # pylint: disable=global-statement

tmp_available_api_families, _status, _modified = kh.get_available_kinds(force_refresh = force_refresh)
if kubernetes_support:
tmp_available_api_families, _status, _modified = kh.get_available_kinds(force_refresh = force_refresh)
else:
tmp_available_api_families = {}

available_api_families = set()
for kind, kind_data in tmp_available_api_families.items():
if deep_get(kind_data, DictPath("available"), False) == True:
Expand Down Expand Up @@ -11560,17 +11587,14 @@ def populate_views(force_refresh: bool = False) -> None:
if not filename.endswith((".yaml", ".yml")):
continue

if len(available_api_families) > 0:
match_tmp = yaml_regex.match(filename)
tmp = match_tmp[1]
if "." in tmp:
kind, api_family = tmp.split(".", 1)
else:
kind = tmp
api_family = ""
if (kind, api_family) in available_api_families or kind.startswith("__"):
view_files.append(os.path.join(view_dir, filename))
match_tmp = yaml_regex.match(filename)
tmp = match_tmp[1]
if "." in tmp:
kind, api_family = tmp.split(".", 1)
else:
kind = tmp
api_family = ""
if (kind, api_family) in available_api_families or kind.startswith("__"):
view_files.append(os.path.join(view_dir, filename))

for view_file in view_files:
Expand Down Expand Up @@ -12037,7 +12061,9 @@ def populate_views(force_refresh: bool = False) -> None:
# Add the new view
infoviews[(kind, api_family)] = infoview_entry
has_infoview = True
kh_update_api_status((kind, api_family), listview = has_listview, infoview = has_infoview)

if kubernetes_support:
kh_update_api_status((kind, api_family), listview = has_listview, infoview = has_infoview)

def setupui(stdscr: curses.window) -> None:
# Hide the cursor
Expand All @@ -12057,6 +12083,15 @@ def setupui(stdscr: curses.window) -> None:
viewfunc = deep_get(views, DictPath(f"{defaultview}#viewfunc"))
if viewfunc is None:
viewfunc = genericlistloop
check_availability = deep_get(views, DictPath(f"{defaultview}#check_availability"))
if check_availability is not None and not check_availability():
curses.endwin()
ansithemeprint([ANSIThemeString("Error", "error"),
ANSIThemeString(": The requested view “", "default"),
ANSIThemeString(defaultview, "argument"),
ANSIThemeString("“ is not available; ", "default"),
ANSIThemeString("the cluster may be offline or the API disabled.", "default")], stderr = True)
sys.exit(errno.ENOTSUP)
viewfunc(stdscr, defaultview)
else:
curses.endwin()
Expand Down Expand Up @@ -12295,6 +12330,7 @@ def open_view(options: List[Tuple[str, str]], args: List[str]) -> None:
global read_only_mode # pylint: disable=global-statement
global selected_namespace # pylint: disable=global-statement
global defaultview # pylint: disable=global-statement
global kubernetes_support # pylint: disable=global-statement

tmpdefaultview = deep_get(cmtlib.cmtconfig, DictPath("Global#defaultview"), "")

Expand All @@ -12303,8 +12339,11 @@ def open_view(options: List[Tuple[str, str]], args: List[str]) -> None:
selected_namespace = optarg
elif opt == "--read-only":
read_only_mode = True
elif opt == "--disable-kubernetes":
kubernetes_support = False

init_kubernetes_client()

# Customises the list views
ansithemeprint([ANSIThemeString("Populating list of supported views...\n", "default")])

Expand Down Expand Up @@ -12357,7 +12396,8 @@ def open_view(options: List[Tuple[str, str]], args: List[str]) -> None:

init_kubernetes_client()
ansithemeprint([ANSIThemeString("Checking available Kubernetes APIs\n", "default")])
_available_api_families, _status, _modified = kh.get_available_kinds()
if kubernetes_support:
_available_api_families, _status, _modified = kh.get_available_kinds()

# Customises the list views if necessary
if len(infoviews) == 0:
Expand Down Expand Up @@ -12586,6 +12626,15 @@ COMMANDLINE = {
"--read-only": {
"description": [ANSIThemeString("disable all commands that modify state", "description")],
},
"--disable-kubernetes": {
"description": [ANSIThemeString("disable Kubernetes support", "description")],
"extended_description": [
[ANSIThemeString("This option disables Kubernetes support; ", "description")],
[ANSIThemeString("this is typically only useful if you use", "description")],
[ANSIThemeString(about.UI_PROGRAM_NAME, "programname"),
ANSIThemeString(" to manage an Ansible inventory", "description")],
],
},
"--namespace": {
"description": [ANSIThemeString("only show namespace ", "description"),
ANSIThemeString("NAMESPACE", "argument")],
Expand Down
3 changes: 2 additions & 1 deletion tests/schemas/views.json
Original file line number Diff line number Diff line change
Expand Up @@ -1133,7 +1133,8 @@
"check_availability": {
"description": "Function to use to check whether the API is available",
"enum": [
"is_cluster_reachable"
"is_cluster_reachable",
"is_kubernetes_supported"
]
},
"field_indexes": {
Expand Down
1 change: 1 addition & 0 deletions views/__Context.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ listview:
listgetter_args:
key: "server_address"
retrigger_timeout: 300
check_availability: "is_kubernetes_supported"
on_activation:
call: null
name: "Contexts"
Expand Down

0 comments on commit deeb9ae

Please sign in to comment.