From bb34bc05eb1a146487ae43e2f084b16e209ce191 Mon Sep 17 00:00:00 2001 From: Jose Angel Munoz <5019972+imjoseangel@users.noreply.github.com> Date: Sun, 12 Sep 2021 22:05:37 +0200 Subject: [PATCH] Feature/41 cpversion (#44) * feat(add-cluster-version): include version from client Signed-off-by: imjoseangel --- .github/workflows/covecov-analysis.yml | 3 ++ .github/workflows/python-package.yml | 3 ++ .pre-commit-config.yaml | 2 +- Makefile | 2 +- README.md | 7 +++++ powerline_k8sstatus/segments.py | 33 ++++++++++++++++----- tests/test_powerlinek8sstatus.py | 41 ++++++++++++++++++++++++-- 7 files changed, 78 insertions(+), 13 deletions(-) diff --git a/.github/workflows/covecov-analysis.yml b/.github/workflows/covecov-analysis.yml index c8c3c52..7e08150 100644 --- a/.github/workflows/covecov-analysis.yml +++ b/.github/workflows/covecov-analysis.yml @@ -16,6 +16,9 @@ jobs: PYTHON: '3.7' steps: - uses: actions/checkout@master + - name: start minikube + id: minikube + uses: medyagh/setup-minikube@master - name: Setup Python uses: actions/setup-python@master with: diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index bddbbe8..3ab232e 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -19,6 +19,9 @@ jobs: steps: - uses: actions/checkout@v2 + - name: start minikube + id: minikube + uses: medyagh/setup-minikube@master - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2b06aa1..09e15bb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,7 +61,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/commitizen-tools/commitizen - rev: v2.18.0 + rev: v2.18.1 hooks: - id: commitizen stages: [commit-msg] diff --git a/Makefile b/Makefile index 5c8d286..98f8e39 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ install: ## Install in editable mode uninstall: ## Uninstall package $(info Make: Uninstall package.) - pip uninstall powerline_k8sstatus + pip uninstall powerline-k8sstatus test: ## Run unit tests $(info Make: Run unit tests.) diff --git a/README.md b/README.md index fa5a4c8..e51ce70 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ It will show any or all of: * context name * namespace * username +* controlplane version You can also: @@ -67,6 +68,11 @@ for example in `.config/powerline/colorschemes/default.json`: "bg": "green", "attrs": [] }, + "k8sstatus_version": { + "fg": "white", + "bg": "mediumorange", + "attrs": [] + }, "k8sstatus:divider": { "fg": "white", "bg": "mediumorange", @@ -86,6 +92,7 @@ for example in `.config/powerline/themes/shell/default.json`: "args": { "show_namespace": true, "show_user": true, + "show_version": true, "context_alert": [ "minikube", "production" diff --git a/powerline_k8sstatus/segments.py b/powerline_k8sstatus/segments.py index 7a1032a..ac005ca 100644 --- a/powerline_k8sstatus/segments.py +++ b/powerline_k8sstatus/segments.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# pylint: disable=R1710 +# pylint: disable=R1710, R0914, E1121 from __future__ import (unicode_literals, division, absolute_import, print_function) @@ -8,6 +8,9 @@ from powerline.segments import Segment, with_docstring from powerline.theme import requires_segment_info, requires_filesystem_watcher from kubernetes import config +from kubernetes.config.config_exception import ConfigException +from kubernetes.client import VersionApi +from urllib3.exceptions import MaxRetryError @requires_filesystem_watcher @@ -16,7 +19,7 @@ class K8SStatusSegment(Segment): divider_highlight_group = None @staticmethod - def build_segments(context, namespace, user, contextalert, namespacealert): + def build_segments(context, namespace, user, version, contextalert, namespacealert): segments = [{'contents': ('\U00002388 {}').format( context), 'highlight_groups': [contextalert]}] @@ -34,10 +37,18 @@ def build_segments(context, namespace, user, contextalert, namespacealert): 'divider_highlight_group': 'k8sstatus:divider' }) + if version and version.lower(): + segments.append({ + 'contents': version, + 'highlight_groups': ['k8sstatus_version'], + 'divider_highlight_group': 'k8sstatus:divider' + }) + return segments def __call__(self, pl, segment_info, create_watcher=None, context_alert: list = None, - namespace_alert: list = None, show_namespace=False, show_user=False): + namespace_alert: list = None, show_namespace=False, show_user=False, + show_version=False): if context_alert is None: context_alert = [] @@ -55,8 +66,6 @@ def __call__(self, pl, segment_info, create_watcher=None, context_alert: list = contexts, active_context = config.list_kube_config_contexts() except TypeError: return - except config.config_exception.ConfigException: - return if not contexts: return @@ -80,12 +89,20 @@ def __call__(self, pl, segment_info, create_watcher=None, context_alert: list = else: namespace = 'default' + user = None if show_user: user = active_context['context']['user'] - else: - user = None - return self.build_segments(context, namespace, user, contextstatus, namespacestatus) + version = None + if show_version: + try: + version = VersionApi( + config.load_kube_config()).get_code().git_version + except (ConnectionRefusedError, MaxRetryError, ConfigException): + version = None + + return self.build_segments(context, namespace, user, version, + contextstatus, namespacestatus) k8sstatus = with_docstring( diff --git a/tests/test_powerlinek8sstatus.py b/tests/test_powerlinek8sstatus.py index cb806ee..83c20d8 100644 --- a/tests/test_powerlinek8sstatus.py +++ b/tests/test_powerlinek8sstatus.py @@ -6,11 +6,13 @@ from kubernetes import config import pytest import powerline_k8sstatus as powerlinek8s - +from kubernetes.config.config_exception import ConfigException +from urllib3.exceptions import MaxRetryError CONTEXT = 'minikube' NAMESPACE = 'tools' USER = 'minikube' +VERSION = 'v1.18.0' EXPECTED_NAMESPACE = { 'contents': NAMESPACE, @@ -30,6 +32,12 @@ 'divider_highlight_group': 'k8sstatus:divider' } +EXPECTED_VERSION = { + 'contents': VERSION, + 'highlight_groups': ['k8sstatus_version'], + 'divider_highlight_group': 'k8sstatus:divider' +} + def mockk8sreturn(): return ([{'context': {'cluster': 'minikube', 'namespace': NAMESPACE, 'user': USER}, 'name': CONTEXT}], {'context': {'cluster': 'minikube', 'namespace': NAMESPACE, 'user': USER}, 'name': CONTEXT}) @@ -49,7 +57,7 @@ def mockk8snonereturn(): @pytest.fixture def expected_symbol(request): - return {'contents': (u'\U00002388 {}').format( + return {'contents': ('\U00002388 {}').format( CONTEXT), 'highlight_groups': [request.param]} @@ -86,6 +94,7 @@ def setup_notnamespacemocked_context(monkeypatch): def setup_nonemocked_context(monkeypatch): monkeypatch.setattr( config, 'list_kube_config_contexts', mockk8snonereturn) + monkeypatch.setattr(config, 'load_kube_config', mockk8snonereturn) @pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) @@ -112,6 +121,14 @@ def test_context_user(pl, segment_info, expected_symbol): assert output == [expected_symbol, EXPECTED_USER] +@pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) +@pytest.mark.usefixtures('setup_namespacemocked_context', 'expected_symbol') +def test_context_version(pl, segment_info, expected_symbol): + output = powerlinek8s.k8sstatus( + pl=pl, segment_info=segment_info, show_version=True) + assert output == [expected_symbol, EXPECTED_VERSION] + + @pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) @pytest.mark.usefixtures('setup_namespacemocked_context', 'expected_symbol') def test_context_usernamespace(pl, segment_info, expected_symbol): @@ -120,6 +137,24 @@ def test_context_usernamespace(pl, segment_info, expected_symbol): assert output == [expected_symbol, EXPECTED_NAMESPACE, EXPECTED_USER] +@pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) +@pytest.mark.usefixtures('setup_namespacemocked_context', 'expected_symbol') +def test_context_versionnamespace(pl, segment_info, expected_symbol): + output = powerlinek8s.k8sstatus( + pl=pl, segment_info=segment_info, show_namespace=True, show_version=True) + assert output == [expected_symbol, EXPECTED_NAMESPACE, EXPECTED_VERSION] + + +@pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) +@pytest.mark.usefixtures('setup_namespacemocked_context', 'expected_symbol') +def test_context_versionusernamespace(pl, segment_info, expected_symbol): + output = powerlinek8s.k8sstatus( + pl=pl, segment_info=segment_info, show_namespace=True, show_user=True, + show_version=True) + assert output == [expected_symbol, EXPECTED_NAMESPACE, + EXPECTED_USER, EXPECTED_VERSION] + + @pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) @pytest.mark.usefixtures('setup_mocked_context', 'expected_symbol') def test_context_notnamespacedefault(pl, segment_info, expected_symbol): @@ -138,7 +173,7 @@ def test_context_notnamespacedefaulttrue(pl, segment_info, expected_symbol): @pytest.mark.parametrize('expected_symbol', ['k8sstatus'], indirect=True) @pytest.mark.usefixtures('setup_notnamespacemocked_context', 'expected_symbol') -def test_context_notnamespacdefined(pl, segment_info, expected_symbol): +def test_context_notnamespacedefined(pl, segment_info, expected_symbol): output = powerlinek8s.k8sstatus( pl=pl, segment_info=segment_info) assert output == [expected_symbol]