diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000..fc47484 Binary files /dev/null and b/__pycache__/main.cpython-312.pyc differ diff --git a/main.py b/main.py index 74505aa..3ccb603 100644 --- a/main.py +++ b/main.py @@ -6,54 +6,62 @@ import subprocess # Environment Variables -CHART_NAME = os.getenv("PLUGIN_CHART_NAME") -CHART_VERSION = os.getenv("PLUGIN_CHART_VERSION", "1.0.0") -DOCKER_REGISTRY = os.getenv( - "PLUGIN_DOCKER_REGISTRY", 'registry.hub.docker.com') +def main_function(): -DOCKER_USERNAME = os.getenv( - "PLUGIN_DOCKER_USERNAME") -DOCKER_PASSWORD = os.getenv( - "PLUGIN_DOCKER_PASSWORD") + CHART_NAME = os.getenv("PLUGIN_CHART_NAME") + CHART_VERSION = os.getenv("PLUGIN_CHART_VERSION", "1.0.0") -CHART_PATH = os.getenv("PLUGIN_CHART_PATH") + DOCKER_REGISTRY = os.getenv( + "PLUGIN_DOCKER_REGISTRY", 'registry.hub.docker.com') -if (CHART_NAME is None): - print("Please provide a chart name") - exit(1) + DOCKER_USERNAME = os.getenv( + "PLUGIN_DOCKER_USERNAME") + DOCKER_PASSWORD = os.getenv( + "PLUGIN_DOCKER_PASSWORD") -if (DOCKER_USERNAME is None or DOCKER_PASSWORD is None): - print("Please provide a username and a password") - exit(1) + CHART_PATH = os.getenv("PLUGIN_CHART_PATH") + + if (CHART_NAME is None or CHART_NAME == ""): + print("Please provide a chart name") + exit(1) + + if (DOCKER_USERNAME is None or DOCKER_PASSWORD is None or DOCKER_USERNAME == "" or DOCKER_PASSWORD == ""): + print("Please provide a username and a password") + exit(1) + + if (CHART_PATH is not None): + os.chdir(CHART_PATH) + + try: + if (subprocess.run(["helm", "package", "--dependency-update", "."]).returncode != 0): + raise Exception("Failed to package chart!") + except: + print("Failed to package chart!") + exit(1) + + chart_filename = f"{CHART_NAME}-{CHART_VERSION}.tgz" + + try: + login_command = ['helm', 'registry', 'login', DOCKER_REGISTRY, + '-u', DOCKER_USERNAME, '-p', DOCKER_PASSWORD] + if (subprocess.run(login_command).returncode != 0): + raise Exception("Failed to login!") + except: + print("Failed to login!") + exit(1) + + try: + docker_push_command = ["helm", "push", chart_filename, + f"oci://{DOCKER_REGISTRY}/{DOCKER_USERNAME}"] + if (subprocess.run(docker_push_command).returncode != 0): + raise Exception("Failed to push chart!") + else: + print("Chart pushed successfully.") + except: + print("Failed to push chart!") + exit(1) -if (CHART_PATH is not None): - os.chdir(CHART_PATH) - -try: - if (subprocess.run(["helm", "package", "--dependency-update", "."]).returncode != 0): - raise Exception("Failed to package chart!") -except: - print("Failed to package chart!") - exit(1) - -chart_filename = f"{CHART_NAME}-{CHART_VERSION}.tgz" - -try: - login_command = ['helm', 'registry', 'login', DOCKER_REGISTRY, - '-u', DOCKER_USERNAME, '-p', DOCKER_PASSWORD] - if (subprocess.run(login_command).returncode != 0): - raise Exception("Failed to login!") -except: - print("Failed to login!") - exit(1) - -try: - docker_push_command = ["helm", "push", chart_filename, - f"oci://{DOCKER_REGISTRY}/{DOCKER_USERNAME}"] - if (subprocess.run(docker_push_command).returncode != 0): - raise Exception("Failed to push chart!") -except: - print("Failed to push chart!") - exit(1) \ No newline at end of file +if __name__ == "__main__": + main_function() diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..edf6939 --- /dev/null +++ b/tests.py @@ -0,0 +1,97 @@ +import unittest +from unittest.mock import patch +import os +from io import StringIO +from main import main_function + + +class TestPushOCIChartToRegistry(unittest.TestCase): + + def tearDown(self): + os.environ["PLUGIN_CHART_NAME"] = "" + os.environ["PLUGIN_CHART_VERSION"] = "" + os.environ["PLUGIN_DOCKER_REGISTRY"] = "" + os.environ["PLUGIN_DOCKER_USERNAME"] = "" + os.environ["PLUGIN_DOCKER_PASSWORD"] = "" + os.environ["PLUGIN_CHART_PATH"] = "" + + @patch("subprocess.run") + def test_successful_chart_push(self, mock_subprocess_run): + os.environ["PLUGIN_CHART_NAME"] = "mywebapp" + test_docker_username = os.environ["TEST_DOCKER_USERNAME"] + test_docker_password = os.environ["TEST_DOCKER_PASSWORD"] + os.environ["PLUGIN_DOCKER_USERNAME"] = test_docker_username + os.environ["PLUGIN_DOCKER_PASSWORD"] = test_docker_password + os.environ["PLUGIN_CHART_PATH"] = "chart" + os.environ["PLUGIN_CHART_VERSION"] = "5.0.0" + os.environ["PLUGIN_DOCKER_REGISTRY"] = "registry.hub.docker.com" + + mock_subprocess_run.return_value.returncode = 0 + + with patch("sys.stdout", new_callable=StringIO) as mock_stdout: + main_function() + + mock_subprocess_run.assert_called_with( + ["helm", "push", "mywebapp-5.0.0.tgz", f"oci://registry.hub.docker.com/{test_docker_username}"]) + + expected_output = 'Chart pushed successfully.' + self.assertEqual(mock_stdout.getvalue().strip(), expected_output) + + @patch("subprocess.run") + def test_failed_to_package_chart(self, mock_subprocess_run): + os.environ["PLUGIN_CHART_NAME"] = "mywebapp" + test_docker_username = os.environ["TEST_DOCKER_USERNAME"] + test_docker_password = os.environ["TEST_DOCKER_PASSWORD"] + os.environ["PLUGIN_DOCKER_USERNAME"] = test_docker_username + os.environ["PLUGIN_DOCKER_PASSWORD"] = test_docker_password + os.environ["PLUGIN_CHART_PATH"] = "chart" + + mock_subprocess_run.return_value.returncode = 1 + + with patch("sys.stdout", new_callable=StringIO) as mock_stdout: + with self.assertRaises(SystemExit) as context: + main_function() + + self.assertEqual(context.exception.code, 1) + + expected_output = 'Failed to package chart!' + self.assertEqual(mock_stdout.getvalue().strip(), expected_output) + + @patch("subprocess.run") + def test_chart_name_not_provided(self, mock_subprocess_run): + test_docker_username = os.environ["TEST_DOCKER_USERNAME"] + test_docker_password = os.environ["TEST_DOCKER_PASSWORD"] + os.environ["PLUGIN_DOCKER_USERNAME"] = test_docker_username + os.environ["PLUGIN_DOCKER_PASSWORD"] = test_docker_password + os.environ["PLUGIN_CHART_PATH"] = "chart" + + mock_subprocess_run.return_value.returncode = 0 + + with patch("sys.stdout", new_callable=StringIO) as mock_stdout: + with self.assertRaises(SystemExit) as context: + main_function() + + self.assertEqual(context.exception.code, 1) + + expected_output = 'Please provide a chart name' + self.assertEqual(mock_stdout.getvalue().strip(), expected_output) + + @patch("subprocess.run") + def test_username_and_password_not_provided(self, mock_subprocess_run): + os.environ["PLUGIN_CHART_NAME"] = "mywebapp" + os.environ["PLUGIN_CHART_PATH"] = "chart" + + mock_subprocess_run.return_value.returncode = 0 + + with patch("sys.stdout", new_callable=StringIO) as mock_stdout: + with self.assertRaises(SystemExit) as context: + main_function() + + self.assertEqual(context.exception.code, 1) + + expected_output = 'Please provide a username and a password' + self.assertEqual(mock_stdout.getvalue().strip(), expected_output) + + +if __name__ == '__main__': + unittest.main()