Skip to content

Commit 6d14add

Browse files
authored
Merge pull request #112 from abnamro/2332710-bug-fix-helm-deployment-command
2332710 bug fix in resc-helm-wizard
2 parents f9feaa3 + 23426b1 commit 6d14add

File tree

9 files changed

+117
-58
lines changed

9 files changed

+117
-58
lines changed
+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
exclude README.md
22
exclude MANIFEST.in
3-
include resources/*
4-
include images/*
3+
include config/*.yaml

deployment/resc-helm-wizard/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Helm Values YAML Wizard
1+
# Repository Scanner Helm Wizard (resc-helm-wizard)
22

33
<!-- TABLE OF CONTENTS -->
44
## Table of contents

deployment/resc-helm-wizard/setup.cfg

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[metadata]
22
name = resc_helm_wizard
33
description = Repository Scanner - Helm Wizard
4-
version = 1.0.2
4+
version = 1.0.3
55
author = ABN AMRO
66
author_email = resc@nl.abnamro.com
77
url = https://github.com/ABNAMRO/repository-scanner
@@ -11,7 +11,7 @@ long_description_content_type = text/markdown
1111

1212
[options]
1313
requires_python = >=3.9
14-
include_package_data = False
14+
include_package_data = True
1515
zip_safe = False
1616
package_dir = = src
1717
packages = find:
@@ -21,7 +21,7 @@ where = src
2121

2222
[options.package_data]
2323
resc_helm_wizard =
24-
static/*.ini
24+
static/*.ini, config/*.yaml
2525

2626
[options.entry_points]
2727
console_scripts =

deployment/resc-helm-wizard/src/resc_helm_wizard/common.py

+23-7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from urllib.parse import urlparse
88

99
# Third Party
10+
import pkg_resources
1011
import requests
1112
import yaml
1213

@@ -15,8 +16,9 @@
1516
from resc_helm_wizard.helm_utilities import (
1617
add_helm_repository,
1718
install_or_upgrade_helm_release,
18-
is_chart_version_already_installed,
19-
update_helm_repository
19+
is_chart_already_installed,
20+
update_helm_repository,
21+
validate_helm_deployment_status
2022
)
2123
from resc_helm_wizard.helm_value import HelmValue
2224
from resc_helm_wizard.kubernetes_utilities import create_namespace_if_not_exists
@@ -160,8 +162,7 @@ def create_helm_values_yaml(helm_values: HelmValue, input_values_yaml_file: str)
160162
"blob/main/deployment/kubernetes/README.md"
161163

162164
try:
163-
with open(input_values_yaml_file, "r", encoding="utf-8") as file_in:
164-
values_dict = yaml.safe_load(file_in)
165+
values_dict = read_yaml_file(input_values_yaml_file)
165166

166167
values_dict["resc-database"]["hostOS"] = helm_values.operating_system
167168
values_dict["resc-database"]["database"]["pvc_path"] = helm_values.db_storage_path
@@ -195,6 +196,19 @@ def create_helm_values_yaml(helm_values: HelmValue, input_values_yaml_file: str)
195196
return output_file_generated
196197

197198

199+
def read_yaml_file(file_path):
200+
"""
201+
Read content of yaml file
202+
:param file_path:
203+
path of yaml file
204+
:return: stream
205+
Returns yaml content
206+
"""
207+
with pkg_resources.resource_stream(__name__, file_path) as file_in:
208+
data = yaml.safe_load(file_in)
209+
return data
210+
211+
198212
def get_scheme_host_port_from_url(url: str):
199213
"""
200214
Get scheme, host, port from url
@@ -322,17 +336,19 @@ def run_deployment():
322336
if namespace_created:
323337
# Check if release is already installed
324338
output = subprocess.run(["helm", "list", "-n", constants.NAMESPACE], capture_output=True, text=True, check=True)
325-
# Check if same chart version is already installed
326-
version_installed = is_chart_version_already_installed()
327-
if constants.RELEASE_NAME in output.stdout and version_installed is True:
339+
# Check if deployment is already running
340+
chart_installed = is_chart_already_installed()
341+
if constants.RELEASE_NAME in output.stdout and chart_installed:
328342
run_upgrade_confirm_msg = f"Release {constants.RELEASE_NAME} is already installed in " \
329343
f"{constants.NAMESPACE} namespace. Do you want to upgrade the release?"
330344
run_upgrade_confirm = questions.ask_user_confirmation(msg=run_upgrade_confirm_msg)
331345
if run_upgrade_confirm is True:
332346
deployment_status = install_or_upgrade_helm_release(action="upgrade")
347+
validate_helm_deployment_status()
333348
else:
334349
logging.info("Skipping deployment...")
335350

336351
else:
337352
deployment_status = install_or_upgrade_helm_release(action="install")
353+
validate_helm_deployment_status()
338354
return deployment_status

deployment/resc-helm-wizard/src/resc_helm_wizard/helm_utilities.py

+30-16
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,30 @@ def install_or_upgrade_helm_release(action: str) -> bool:
3131
return False
3232

3333

34-
def is_chart_version_already_installed() -> bool:
34+
def get_deployment_status_from_installed_chart() -> str:
3535
"""
36-
Checks if chart installed or not
37-
:return: bool
38-
Returns true if chart already installed else returns false
39-
"""
40-
downloaded_version = get_version_from_downloaded_chart()
41-
installed_version = get_version_from_installed_chart()
42-
return downloaded_version == installed_version
43-
44-
45-
def get_version_from_installed_chart() -> str:
46-
"""
47-
Get version of the installed chart
36+
Get status of the installed chart
4837
:return: str
49-
Returns version of the installed chart
38+
Returns status of the installed chart
5039
"""
5140
cmd = f"helm list -f {constants.CHART_NAME} -n {constants.NAMESPACE} -o json"
5241
output = subprocess.check_output(cmd, shell=True)
5342
chart_info = json.loads(output.decode("utf-8"))
54-
if chart_info and "chart" in chart_info[0]:
55-
return chart_info[0]["chart"].split("-")[1]
43+
if chart_info and "status" in chart_info[0]:
44+
return chart_info[0]["status"]
5645
return None
5746

5847

48+
def is_chart_already_installed() -> bool:
49+
"""
50+
Checks if chart installed or not
51+
:return: bool
52+
Returns true if chart already installed else returns false
53+
"""
54+
status = get_deployment_status_from_installed_chart()
55+
return bool(status == "deployed")
56+
57+
5958
def get_version_from_downloaded_chart() -> str:
6059
"""
6160
Get version of the downloaded chart
@@ -93,3 +92,18 @@ def update_helm_repository():
9392
except subprocess.CalledProcessError:
9493
logging.error("An error occurred while updating the helm repository")
9594
sys.exit(1)
95+
96+
97+
def validate_helm_deployment_status():
98+
"""
99+
Validate the status of the helm deployment
100+
"""
101+
try:
102+
result = subprocess.run(['helm', 'status', constants.RELEASE_NAME, "-n", constants.NAMESPACE],
103+
capture_output=True, check=True, text=True)
104+
output = result.stdout.strip()
105+
if "STATUS: deployed" in output:
106+
logging.info("The deployment was successful. Visit http://127.0.0.1:30000 to get started with RESC!")
107+
except subprocess.CalledProcessError:
108+
logging.error("An error occurred during deployment.")
109+
sys.exit(1)

deployment/resc-helm-wizard/src/resc_helm_wizard/run_wizard.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def prompt_questions():
3737
)
3838

3939
common.create_helm_values_yaml(helm_values=helm_values,
40-
input_values_yaml_file="resources/example-values.yaml")
40+
input_values_yaml_file="config/example-values.yaml")
4141
common.run_deployment_as_per_user_confirmation()
4242
except KeyboardInterrupt:
4343
logging.error("Aborting the program! operation cancelled by user")

deployment/resc-helm-wizard/tests/test_common.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
# Third Party
99
import pytest
10+
import yaml
1011

1112
# First Party
1213
from resc_helm_wizard.common import (
@@ -251,9 +252,10 @@ def test_create_storage_for_db_and_rabbitmq_where_path_does_not_exist_and_dir_co
251252
assert excinfo.value.code == 1
252253

253254

255+
@patch("resc_helm_wizard.common.read_yaml_file")
254256
@patch("os.path.exists")
255257
def test_create_helm_values_yaml_success(
256-
mock_file_path_exists):
258+
mock_file_path_exists, mock_read_yaml_file):
257259
vcs_instance1 = VcsInstance(
258260
provider_type="GITHUB_PUBLIC",
259261
scheme="https",
@@ -272,8 +274,12 @@ def test_create_helm_values_yaml_success(
272274
rabbitmq_storage_path="/temp/rabbitmq",
273275
vcs_instances=vcs_instances
274276
)
277+
275278
mock_file_path_exists.return_type = True
276279
input_file_path = os.path.join(THIS_DIR.parent, "tests", "fixtures", "test-values.yaml")
280+
with open(input_file_path, "r", encoding="utf-8") as file_in:
281+
values_dict = yaml.safe_load(file_in)
282+
mock_read_yaml_file.return_value = values_dict
277283
generated_file_path = os.path.join(THIS_DIR.parent, "custom-values.yaml")
278284
output_file_generated = create_helm_values_yaml(helm_values=helm_values, input_values_yaml_file=input_file_path)
279285
assert output_file_generated is True
@@ -291,8 +297,9 @@ def test_create_helm_values_sys_exit_when_file_not_exists(mock_error_log):
291297
assert excinfo.value.code == 1
292298

293299

300+
@patch("resc_helm_wizard.common.read_yaml_file")
294301
@patch("logging.Logger.error")
295-
def test_create_helm_values_sys_exit_when_key_not_exists(mock_error_log):
302+
def test_create_helm_values_sys_exit_when_key_not_exists(mock_error_log, mock_read_yaml_file):
296303
helm_values = HelmValue(
297304
operating_system="linux",
298305
db_password="dummy_pass",
@@ -301,6 +308,9 @@ def test_create_helm_values_sys_exit_when_key_not_exists(mock_error_log):
301308
vcs_instances=[]
302309
)
303310
input_file_path = os.path.join(THIS_DIR.parent, "tests", "fixtures", "test-invalid-values.yaml")
311+
with open(input_file_path, "r", encoding="utf-8") as file_in:
312+
values_dict = yaml.safe_load(file_in)
313+
mock_read_yaml_file.return_value = values_dict
304314
expected_error_log = f"Aborting the program! 'resc-database' was missing in {input_file_path}"
305315
with pytest.raises(SystemExit) as excinfo:
306316
create_helm_values_yaml(helm_values=helm_values, input_values_yaml_file=input_file_path)

deployment/resc-helm-wizard/tests/test_helm_utilities.py

+46-26
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
from resc_helm_wizard import constants
99
from resc_helm_wizard.helm_utilities import (
1010
add_helm_repository,
11+
get_deployment_status_from_installed_chart,
1112
get_version_from_downloaded_chart,
12-
get_version_from_installed_chart,
1313
install_or_upgrade_helm_release,
14-
is_chart_version_already_installed,
15-
update_helm_repository
14+
is_chart_already_installed,
15+
update_helm_repository,
16+
validate_helm_deployment_status
1617
)
1718

1819
sys.path.insert(0, "src")
@@ -40,45 +41,37 @@ def test_install_or_upgrade_helm_release_failure(mock_error_log):
4041
mock_error_log.assert_called_with(expected_error_log)
4142

4243

43-
@patch("resc_helm_wizard.helm_utilities.get_version_from_downloaded_chart")
44-
@patch("resc_helm_wizard.helm_utilities.get_version_from_installed_chart")
45-
def test_is_chart_version_already_installed_is_true(get_version_from_installed_chart,
46-
get_version_from_downloaded_chart):
47-
get_version_from_installed_chart.return_value = "1.0.0"
48-
get_version_from_downloaded_chart.return_value = "1.0.0"
49-
already_installed = is_chart_version_already_installed()
50-
get_version_from_installed_chart.assert_called_once_with()
51-
get_version_from_downloaded_chart.assert_called_once_with()
44+
@patch("resc_helm_wizard.helm_utilities.get_deployment_status_from_installed_chart")
45+
def test_is_chart_already_installed_is_true(get_deployment_status_from_installed_chart):
46+
get_deployment_status_from_installed_chart.return_value = "deployed"
47+
already_installed = is_chart_already_installed()
48+
get_deployment_status_from_installed_chart.assert_called_once_with()
5249
assert already_installed is True
5350

5451

55-
@patch("resc_helm_wizard.helm_utilities.get_version_from_downloaded_chart")
56-
@patch("resc_helm_wizard.helm_utilities.get_version_from_installed_chart")
57-
def test_is_chart_version_already_installed_is_false(get_version_from_installed_chart,
58-
get_version_from_downloaded_chart):
59-
get_version_from_installed_chart.return_value = "1.0.0"
60-
get_version_from_downloaded_chart.return_value = "1.0.1"
61-
already_installed = is_chart_version_already_installed()
62-
get_version_from_installed_chart.assert_called_once_with()
63-
get_version_from_downloaded_chart.assert_called_once_with()
52+
@patch("resc_helm_wizard.helm_utilities.get_deployment_status_from_installed_chart")
53+
def test_is_chart_already_installed_is_false(get_deployment_status_from_installed_chart):
54+
get_deployment_status_from_installed_chart.return_value = None
55+
already_installed = is_chart_already_installed()
56+
get_deployment_status_from_installed_chart.assert_called_once_with()
6457
assert already_installed is False
6558

6659

6760
@patch("subprocess.check_output")
68-
def test_get_version_from_installed_chart_success(mock_check_output):
61+
def test_get_deployment_status_from_installed_chart_success(mock_check_output):
6962
expected_output = b'[{"name":"resc","namespace":"resc","revision":"1",' \
7063
b'"updated":"2023-03-30 10:16:56.211749 +0200 CEST","status":"deployed",' \
7164
b'"chart":"resc-1.1.0","app_version":"1.1.0"}]\n'
7265
mock_check_output.return_value = expected_output
73-
actual_output = get_version_from_installed_chart()
74-
assert actual_output == "1.1.0"
66+
actual_output = get_deployment_status_from_installed_chart()
67+
assert actual_output == "deployed"
7568

7669

7770
@patch("subprocess.check_output")
78-
def test_get_version_from_installed_chart_failure(mock_check_output):
71+
def test_get_deployment_status_from_installed_chart_failure(mock_check_output):
7972
expected_output = b'{}'
8073
mock_check_output.return_value = expected_output
81-
actual_output = get_version_from_installed_chart()
74+
actual_output = get_deployment_status_from_installed_chart()
8275
assert actual_output is None
8376

8477

@@ -141,3 +134,30 @@ def test_update_helm_repository_failure(mock_error_log):
141134
mock_error_log.assert_called_with(expected_error_log)
142135
mock_check_output.assert_called_once_with(cmd, check=True)
143136
mock_sys_exit.assert_called_once_with(1)
137+
138+
139+
@patch("subprocess.run")
140+
@patch("logging.Logger.info")
141+
def test_validate_helm_deployment_status_success(mock_info_log, mock_check_output):
142+
cmd = ['helm', 'status', constants.RELEASE_NAME, "-n", constants.NAMESPACE]
143+
expected_output = "RELEASE STATUS: deployed"
144+
expected_info_log = "The deployment was successful. Visit http://127.0.0.1:30000 to get started with RESC!"
145+
mock_check_output.return_value.stdout = expected_output
146+
validate_helm_deployment_status()
147+
assert mock_check_output.called
148+
mock_check_output.assert_called_once_with(cmd, capture_output=True, check=True, text=True)
149+
mock_info_log.assert_called_with(expected_info_log)
150+
151+
152+
@patch("logging.Logger.error")
153+
def test_validate_helm_deployment_status_failure(mock_error_log):
154+
cmd = ['helm', 'status', constants.RELEASE_NAME, "-n", constants.NAMESPACE]
155+
expected_error_log = "An error occurred during deployment."
156+
with mock.patch("subprocess.run") as mock_check_output, \
157+
mock.patch("sys.exit") as mock_sys_exit:
158+
mock_check_output.side_effect = subprocess.CalledProcessError(returncode=1, cmd=cmd)
159+
validate_helm_deployment_status()
160+
assert mock_check_output.called
161+
mock_error_log.assert_called_with(expected_error_log)
162+
mock_check_output.assert_called_once_with(cmd, capture_output=True, check=True, text=True)
163+
mock_sys_exit.assert_called_once_with(1)

0 commit comments

Comments
 (0)