Skip to content

Commit 0c7f059

Browse files
authored
Merge pull request #49 from QualiSystemsLab/feature/dan_integration_tests_fixed
Feature/dan integration tests fixed
2 parents afc1071 + 6bc1d97 commit 0c7f059

7 files changed

Lines changed: 303 additions & 41 deletions

File tree

package/tests/integration_tests/int_test_downloader.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,24 @@ def setUp(self) -> None:
4747
default_tags
4848
)
4949

50-
def _test_download_terraform_module(self, url: str):
50+
def _test_download_terraform_module(self, url: str, branch: str):
5151
self.integration_data.context.resource.attributes[
5252
f"{SHELL_NAME}.Github Terraform Module URL"] = url
5353
self._driver_helper.tf_service.attributes[
5454
f"{SHELL_NAME}.Github Terraform Module URL"] = url
55+
self.integration_data.context.resource.attributes[
56+
f"{SHELL_NAME}.Branch"] = branch
57+
self._driver_helper.tf_service.attributes[
58+
f"{SHELL_NAME}.Branch"] = branch
5559

5660
downloader = Downloader(self._driver_helper)
5761
tf_workingdir = downloader.download_terraform_module()
5862
self.assertTrue(os.path.exists(os.path.join(tf_workingdir, TF_HELLO_FILE)))
5963

6064
def test_public_and_private_hello_dl(self):
61-
self._test_download_terraform_module(GITHUB_TF_PUBLIC_HELLO_URL_FILE)
62-
self._test_download_terraform_module(os.environ.get("GITHUB_TF_PRIVATE_HELLO_URL"))
63-
self._test_download_terraform_module(GITHUB_TF_PUBLIC_HELLO_URL_FOLDER)
65+
self._test_download_terraform_module(GITHUB_TF_PUBLIC_HELLO_URL_FILE, "")
66+
self._test_download_terraform_module(os.environ.get("GITHUB_TF_PRIVATE_HELLO_URL"), "")
67+
self._test_download_terraform_module(GITHUB_TF_PUBLIC_HELLO_URL_FOLDER, "")
6468

6569
def test_download_terraform_executable(self):
6670
downloader = Downloader(self._driver_helper)

shells/generic_terraform_service/tests/.env.template.env

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ CS_USERNAME = ""
77
CS_PASSWORD = ""
88

99
CLP_RESOURSE = ""
10+
CLP_ATTRIBUTES = ""
11+
12+
GITHUB_TOKEN_ENC = ""
13+
GITHUB_TOKEN_DEC = ""
1014

1115
TFEXEC_VERSION = ""
1216
RESERVATION_DOMAIN = ""
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,19 @@
11
SHELL_NAME = "Generic Terraform Service"
22
UUID_ATTRIBUTE = f"{SHELL_NAME}.UUID"
3+
4+
5+
class ATTRIBUTE_NAMES:
6+
TF_OUTPUTS = "Terraform Outputs"
7+
TF_SENSIITVE_OUTPUTS = "Terraform Sensitive Outputs"
8+
TF_INPUTS = "Terraform Inputs"
9+
CT_INPUTS = "Custom Tags"
10+
APPLY_TAGS = "Apply Tags"
11+
CUSTOM_TAGS = "Custom Tags"
12+
REMOTE_STATE_PROVIDER = "Remote State Provider"
13+
GITHUB_TERRAFORM_MODULE_URL = "Github Terraform Module URL"
14+
TERRAFORM_VERSION = "Terraform Version"
15+
GITHUB_TOKEN = "Github Token"
16+
GITHUB_URL = "Github Terraform Module URL"
17+
BRANCH = "Branch"
18+
CLOUD_PROVIDER = "Cloud Provider"
19+
UUID = "UUID"
Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,54 @@
11
from unittest import mock
2+
from unittest.mock import Mock
23

34
from cloudshell.api.cloudshell_api import CloudShellAPISession
5+
from cloudshell.iac.terraform import TerraformShell, TerraformShellConfig
46
from cloudshell.logging.qs_logger import get_qs_logger
57
from cloudshell.shell.core.driver_context import ResourceCommandContext
68

7-
8-
# from src.data_model import GenericTerraformService
9-
# from shells.generic_terraform_service.src.data_model import GenericTerraformService
10-
11-
# from driver import GenericTerraformServiceDriver
12-
from src.driver import GenericTerraformServiceDriver
13-
14-
# from cloudshell.iac.terraform.models.shell_helper import ShellHelperObject
15-
# from cloudshell.iac.terraform.services.live_status_updater import LiveStatusUpdater
16-
# from cloudshell.iac.terraform.services.sandbox_messages import SandboxMessagesService
179
from tests.integration_tests.helper_objects.env_vars import EnvVars
10+
from tests.integration_tests.helper_services.service_attributes_factory import ServiceAttributesFactory
1811

1912

2013
class IntegrationData(object):
21-
def __init__(self, service_name: str):
14+
def __init__(self, service_name: str, is_api_real: bool = True, mock_api: Mock = None):
2215
self._env_vars = EnvVars(service_name)
23-
self.real_api = CloudShellAPISession(
24-
self._env_vars.cs_server,
25-
self._env_vars.cs_user,
26-
self._env_vars.cs_pass,
27-
self._env_vars.cs_domain
28-
)
29-
self._set_context()
30-
self._logger = get_qs_logger(log_group=self.context.resource.name)
3116

32-
self._create_driver()
17+
if is_api_real:
18+
self.api = CloudShellAPISession(
19+
self._env_vars.cs_server,
20+
self._env_vars.cs_user,
21+
self._env_vars.cs_pass,
22+
self._env_vars.cs_domain
23+
)
3324

34-
def _set_context(self):
25+
else:
26+
self.api = mock_api
27+
self.api.authentication.xmlrpc_token = Mock()
28+
self._set_context(is_api_real)
29+
self._logger = get_qs_logger(log_group=self.context.resource.name)
30+
self.create_tf_shell()
31+
32+
def _set_context(self, is_api_real: bool):
3533
self.context = mock.create_autospec(ResourceCommandContext)
3634
self.context.connectivity = mock.MagicMock()
3735
self.context.connectivity.server_address = self._env_vars.cs_server
38-
self.context.connectivity.admin_auth_token = self.real_api.authentication.xmlrpc_token
36+
self.context.connectivity.admin_auth_token = self.api.authentication.xmlrpc_token
3937

4038
self.context.resource = mock.MagicMock()
4139
self.context.resource.attributes = dict()
4240
self.context.resource.name = self._env_vars.sb_service_alias
4341
self.context.resource.model = 'Generic Terraform Service'
44-
self.set_context_resource_attributes()
45-
42+
if is_api_real:
43+
self.set_context_resource_attributes_from_cs()
44+
else:
45+
self.context.resource.attributes = ServiceAttributesFactory.create_empty_attributes()
4646
self.context.reservation = mock.MagicMock()
4747
self.context.reservation.reservation_id = self._env_vars.cs_res_id
4848
self.context.reservation.domain = self._env_vars.cs_domain
4949

50-
def set_context_resource_attributes(self, the_only_attribute_to_update=""):
51-
services = self.real_api.GetReservationDetails(self._env_vars.cs_res_id, disableCache=True)\
50+
def set_context_resource_attributes_from_cs(self, the_only_attribute_to_update: str = ""):
51+
services = self.api.GetReservationDetails(self._env_vars.cs_res_id, disableCache=True) \
5252
.ReservationDescription.Services
5353
for service in services:
5454
if service.Alias == self._env_vars.sb_service_alias:
@@ -59,6 +59,6 @@ def set_context_resource_attributes(self, the_only_attribute_to_update=""):
5959
elif not the_only_attribute_to_update:
6060
self.context.resource.attributes[attribute.Name] = attribute.Value
6161

62-
def _create_driver(self):
63-
self.driver = GenericTerraformServiceDriver()
64-
self.driver.initialize(self.context)
62+
def create_tf_shell(self):
63+
self._config = TerraformShellConfig(write_sandbox_messages=True, update_live_status=True)
64+
self.tf_shell = TerraformShell(self.context, self._logger, self._config)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from cloudshell.api.cloudshell_api import NameValuePair
2+
3+
from tests.integration_tests.constants import SHELL_NAME, ATTRIBUTE_NAMES
4+
5+
6+
class ServiceAttributesFactory:
7+
@staticmethod
8+
def create_empty_attributes() -> list[dict]:
9+
attributes = [
10+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.REMOTE_STATE_PROVIDER}", Value=""),
11+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.BRANCH}", Value=""),
12+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.CUSTOM_TAGS}", Value=""),
13+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.APPLY_TAGS}", Value=""),
14+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.GITHUB_TERRAFORM_MODULE_URL}", Value=""),
15+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.TERRAFORM_VERSION}", Value=""),
16+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.GITHUB_TOKEN}", Value=""),
17+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.CLOUD_PROVIDER}", Value=""),
18+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.UUID}", Value=""),
19+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.TF_OUTPUTS}", Value=""),
20+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.TF_SENSIITVE_OUTPUTS}", Value=""),
21+
NameValuePair(Name=f"{SHELL_NAME}.{ATTRIBUTE_NAMES.TF_INPUTS}", Value="")
22+
]
23+
return attributes
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
from unittest.mock import patch, Mock
2+
3+
from cloudshell.api.cloudshell_api import NameValuePair
4+
from dotenv import load_dotenv
5+
from tests.integration_tests.constants import SHELL_NAME, ATTRIBUTE_NAMES
6+
from typing import Callable
7+
8+
from tests.integration_tests.helper_objects.integration_context import IntegrationData
9+
10+
import os
11+
from unittest import TestCase, mock
12+
13+
from tests.integration_tests.helper_services.service_attributes_factory import ServiceAttributesFactory
14+
15+
16+
class TestMockTerraformExecuteDestroy(TestCase):
17+
@patch('cloudshell.iac.terraform.services.object_factory.CloudShellSessionContext')
18+
def setUp(self, patched_api) -> None:
19+
load_dotenv()
20+
21+
self._prepare_mock_api()
22+
patched_api.return_value.get_api.return_value = self.mock_api
23+
24+
self._mocked_tf_working_dir = ''
25+
self._prepare_mock_services()
26+
self._prepare_integration_data()
27+
28+
self.mock_api.GetReservationDetails.return_value.ReservationDescription.Services = [self._service1,
29+
self._service2]
30+
31+
def _prepare_integration_data(self):
32+
self.integration_data1 = IntegrationData(self._service1.Alias, False, self.mock_api)
33+
self.integration_data2 = IntegrationData(self._service2.Alias, False, self.mock_api)
34+
35+
def _prepare_mock_services(self):
36+
self._service1 = Mock()
37+
self._service1.Alias = os.environ.get("SB_SERVICE_ALIAS1")
38+
self._service1.Attributes = ServiceAttributesFactory.create_empty_attributes()
39+
self._service2 = Mock()
40+
self._service2.Alias = os.environ.get("SB_SERVICE_ALIAS2")
41+
self._service2.Attributes = ServiceAttributesFactory.create_empty_attributes()
42+
43+
def _prepare_mock_api(self):
44+
self.mock_api = Mock()
45+
self.mock_api.DecryptPassword = _decrypt_password
46+
self.mock_api.GetResourceDetails.return_value.ResourceFamilyName = 'Cloud Provider'
47+
self.mock_api.GetResourceDetails.return_value.ResourceModelName = 'Microsoft Azure'
48+
self.mock_api.GetResourceDetails.return_value.ResourceAttributes = [
49+
NameValuePair(Name="Azure Subscription ID", Value=os.environ.get("AZURE_SUBSCRIPTION_ID")),
50+
NameValuePair(Name="Azure Tenant ID", Value=os.environ.get("AZURE_TENANT_ID")),
51+
NameValuePair(Name="Azure Application ID", Value=os.environ.get("AZURE_APPLICATION_ID")),
52+
NameValuePair(Name="Azure Application Key", Value=os.environ.get("AZURE_APPLICATION_KEY_DEC"))
53+
]
54+
55+
'''------------------------------ Generic Execute/Destroy functions ---------------------------------'''
56+
57+
def run_execute(self, pre_exec_function: Callable, integration_data: IntegrationData):
58+
self.pre_exec_prep(pre_exec_function, integration_data)
59+
integration_data.tf_shell.execute_terraform()
60+
61+
def run_destroy(self, pre_destroy_function: Callable, integration_data: IntegrationData):
62+
self.pre_destroy_prep(pre_destroy_function, integration_data)
63+
integration_data.tf_shell.destroy_terraform()
64+
65+
'''------------------------------ Test Cases ---------------------------------'''
66+
67+
@patch('cloudshell.iac.terraform.services.tf_proc_exec.TfProcExec.can_destroy_run')
68+
@patch('cloudshell.iac.terraform.terraform_shell.SandboxDataHandler')
69+
@patch('cloudshell.iac.terraform.services.object_factory.CloudShellSessionContext')
70+
def test_execute_and_destroy_azure_vault(self, patch_api, patched_sbdata_handler, can_destroy_run):
71+
can_destroy_run.return_value = True
72+
patch_api.return_value.get_api.return_value = self.mock_api
73+
mock_sbdata_handler = Mock()
74+
mock_sbdata_handler.get_tf_working_dir = self._get_mocked_tf_working_dir
75+
mock_sbdata_handler.set_tf_working_dir = self._set_mocked_tf_working_dir
76+
patched_sbdata_handler.return_value = mock_sbdata_handler
77+
self.run_execute_and_destroy(
78+
pre_exec_function=self.pre_exec_azure_vault,
79+
pre_destroy_function=self.pre_destroy,
80+
integration_data=self.integration_data1
81+
)
82+
83+
'''------------------------------ Functions : general _pre prep functions ---------------------------------'''
84+
85+
def pre_exec_prep(self, pre_exec_function: Callable, integration_data: IntegrationData):
86+
pre_exec_function(integration_data)
87+
88+
def pre_destroy_prep(self, pre_destroy_function: Callable, integration_data: IntegrationData):
89+
pre_destroy_function(integration_data)
90+
91+
def clear_sb_data(self):
92+
self.integration_data1.api.ClearSandboxData(self.integration_data1.context.reservation.reservation_id)
93+
94+
'''------------------------------ Functions : prep before exec -------------------------------------------'''
95+
96+
def pre_exec(self, integration_data: IntegrationData):
97+
pass
98+
99+
def pre_exec_azure_vault(self, integration_data: IntegrationData):
100+
self._set_attribute_on_mock_service(
101+
f"{SHELL_NAME}.Terraform Inputs",
102+
os.environ.get("AZUREAPP_TF_INPUTS"),
103+
integration_data
104+
)
105+
self._set_attribute_on_mock_service(
106+
f"{SHELL_NAME}.Github Terraform Module URL",
107+
os.environ.get("GITHUB_TF_PRIVATE_AZUREAPP_URL"),
108+
integration_data
109+
)
110+
self._set_attribute_on_mock_service(
111+
f"{SHELL_NAME}.{ATTRIBUTE_NAMES.GITHUB_TOKEN}",
112+
os.environ.get("GITHUB_TOKEN_DEC"),
113+
integration_data
114+
)
115+
self._set_attribute_on_mock_service(
116+
f"{SHELL_NAME}.{ATTRIBUTE_NAMES.TERRAFORM_VERSION}",
117+
os.environ.get("0.15.1"),
118+
integration_data
119+
)
120+
self._set_attribute_on_mock_service(
121+
f"{SHELL_NAME}.{ATTRIBUTE_NAMES.CLOUD_PROVIDER}",
122+
os.environ.get("CLP_RESOURSE"),
123+
integration_data
124+
)
125+
service1 = Mock()
126+
service1.Alias = integration_data.context.resource.name
127+
service1.Attributes = integration_data.context.resource.attributes
128+
self.mock_api.GetReservationDetails.return_value.ReservationDescription.Services = [service1]
129+
integration_data.create_tf_shell()
130+
131+
def pre_exec_azure_mssql(self, integration_data: IntegrationData):
132+
self._set_attribute_on_mock_service(
133+
f"{SHELL_NAME}.Terraform Inputs",
134+
os.environ.get("AZUREMSSQL_TF_INPUTS"),
135+
integration_data
136+
)
137+
self._set_attribute_on_mock_service(
138+
f"{SHELL_NAME}.Github Terraform Module URL",
139+
os.environ.get("GITHUB_TF_PRIVATE_AZUREMSSQL_URL"),
140+
integration_data
141+
)
142+
self._set_attribute_on_mock_service(
143+
f"{SHELL_NAME}.UUID",
144+
os.environ.get(""),
145+
integration_data
146+
)
147+
148+
def pre_exec_azure_vault_with_remote_access_key_based(self, integration_data: IntegrationData):
149+
self.pre_exec_azure_vault(integration_data)
150+
self._set_attribute_on_mock_service(
151+
f"{SHELL_NAME}.Remote State Provider",
152+
os.environ.get("REMOTE_STATE_PROVIDER_ACCESS_KEY"),
153+
integration_data
154+
)
155+
156+
def pre_exec_azure_vault_with_remote_cloud_cred_based(self, integration_data: IntegrationData):
157+
self.pre_exec_azure_vault(integration_data)
158+
self._set_attribute_on_mock_service(
159+
f"{SHELL_NAME}.Remote State Provider",
160+
os.environ.get("REMOTE_STATE_PROVIDER_CLOUD_CRED"),
161+
integration_data
162+
)
163+
164+
def pre_exec_azure_vault_with_remote_invalid_nonexistent(self, integration_data: IntegrationData):
165+
self.pre_exec_azure_vault(integration_data)
166+
self._set_attribute_on_mock_service(
167+
f"{SHELL_NAME}.Remote State Provider",
168+
os.environ.get("REMOTE_STATE_PROVIDER_INVALID_NO_RESOURCE"),
169+
integration_data
170+
)
171+
172+
def pre_exec_azure_vault_with_remote_invalid_wrong(self, integration_data: IntegrationData):
173+
self.pre_exec_azure_vault(integration_data)
174+
self._set_attribute_on_mock_service(
175+
f"{SHELL_NAME}.Remote State Provider",
176+
os.environ.get("REMOTE_STATE_PROVIDER_INVALID_WRONG_RESOURCE"),
177+
integration_data
178+
)
179+
180+
def pre_exec_azure_vault_without_remote(self, integration_data: IntegrationData):
181+
self.pre_exec_azure_vault(integration_data)
182+
self._set_attribute_on_mock_service(
183+
f"{SHELL_NAME}.Remote State Provider",
184+
os.environ.get(""),
185+
integration_data
186+
)
187+
188+
'''------------------------------ Functions : prep before destroy -----------------------------------------'''
189+
190+
def pre_destroy(self, integration_data: IntegrationData):
191+
# As UUID has been created and SB data now contains UUID and Status we must update context so destroy can run
192+
for attribute in integration_data.context.resource.attributes:
193+
if attribute.Name == f"{SHELL_NAME}.UUID":
194+
attribute.Value = integration_data.tf_shell._tf_service.attributes[f"{SHELL_NAME}.UUID"]
195+
196+
'''------------------------------ Helper Functions ---------------------------------------------------------'''
197+
@staticmethod
198+
def _set_attribute_on_mock_service(attr_name: str, attr_value: str, integration_data: IntegrationData):
199+
for attribute in integration_data.context.resource.attributes:
200+
if attribute.Name == attr_name:
201+
attribute.Value = attr_value
202+
return
203+
204+
def _get_mocked_tf_working_dir(self):
205+
return self._mocked_tf_working_dir
206+
207+
def _set_mocked_tf_working_dir(self, tf_working_dir: str):
208+
self._mocked_tf_working_dir = tf_working_dir
209+
210+
211+
def _decrypt_password(x):
212+
result = mock.MagicMock()
213+
result.Value = x
214+
return result

0 commit comments

Comments
 (0)