Skip to content

Commit 94bc602

Browse files
committed
fixed regex bug for gitlab url. added logging and unit tests for http request module
1 parent 59581d7 commit 94bc602

8 files changed

Lines changed: 109 additions & 33 deletions

File tree

package/cloudshell/cm/ansible/domain/Helpers/gitlab_api_url_validator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@ def is_gitlab_rest_url(url):
1111
EXAMPLE = "http://<SERVER_IP>/api/4/projects/<PROJECT_ID>/repository/files/<PROJECT_PATH>/raw?ref=<GIT_BRANCH>"
1212

1313
# DETERMINE INTENT TO USE GITLAB
14-
initial_pattern_check = "api/v\d/projects/\d/repository/files"
14+
initial_pattern_check = "api/v\d/projects/\d+/repository/files"
1515
matching = re.search(initial_pattern_check, url)
1616
if not matching:
1717
return False
1818

1919
# VALIDATE ENTIRE GITLAB URL STRING
20-
gitlab_api_pattern = "https?://.+/api/v\d/projects/\d/repository/files/.+/raw\?ref=.+"
20+
gitlab_api_pattern = "https?://.+/api/v\d/projects/\d+/repository/files/.+/raw\?ref=.+"
2121
matching = re.match(gitlab_api_pattern, url)
2222
if not matching:
2323
raise Exception("Gitlab Rest API URL failed validation. Should be of form: {}".format(EXAMPLE))
@@ -26,6 +26,6 @@ def is_gitlab_rest_url(url):
2626

2727

2828
if __name__ == "__main__":
29-
input_url = "http://192.168.85.62/api/v4/projects/4/repository/files/hello_world.sh/raw?ref=master"
29+
input_url = "http://192.168.85.62/api/v4/projects/41/repository/files/hello_world.sh/raw?ref=master"
3030
is_gitlab = is_gitlab_rest_url(input_url)
3131
print(is_gitlab)

package/cloudshell/cm/ansible/domain/ansible_command_executor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def execute_playbook(self, playbook_file, inventory_file, args, output_writer, l
2020
"""
2121
:type playbook_file: str
2222
:type inventory_file: str
23-
:type args: list[str]
23+
:type args: str
2424
:type logger: Logger
2525
:type output_writer: OutputWriter
2626
:type cancel_sampler: CancellationSampler

package/cloudshell/cm/ansible/domain/http_request_service.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
class HttpRequestService(object):
8-
def get_response(self, url, auth, logger=None):
8+
def get_response(self, url, auth, logger):
99
"""
1010
:param str url:
1111
:param HttpAuth auth:
@@ -14,37 +14,48 @@ def get_response(self, url, auth, logger=None):
1414
"""
1515
is_gitlab_url = is_gitlab_rest_url(url)
1616
if is_gitlab_url:
17+
logger.info("=== GITLAB Rest API request ===".format(url))
1718
response = self._get_gitlab_response(url, auth, logger)
1819
self._validate_response_status_code(response)
1920
self._invalidate_gitlab_login_page(response)
2021
else:
22+
# if auth:
23+
# if not auth.username:
24+
# raise Exception("Auth download missing 'User' attribute value.")
25+
2126
auth = (auth.username, auth.password) if auth else None
22-
response = requests.get(url, auth=auth, stream=True, verify=False)
27+
if auth:
28+
logger.info("Auth download flow.")
29+
response = requests.get(url, auth=auth, stream=True, verify=False)
30+
else:
31+
logger.info("No-auth download flow.")
32+
response = requests.get(url, stream=True, verify=False)
2333
self._validate_response_status_code(response)
2434
self._invalidate_html(response.content)
35+
36+
logger.info("Playbook download response: {}".format(response.status_code))
2537
return response
2638

2739
@staticmethod
28-
def _get_gitlab_response(url, auth, logger=None):
40+
def _get_gitlab_response(url, auth, logger):
2941
"""
3042
:param url:
3143
:param auth:
3244
:param logging.Logger logger:
3345
:return:
3446
"""
35-
# GITLAB REST API CALL - ADDING TOKEN HEADER
36-
if logger:
37-
logger.info("downloading script via Gitlab Rest API call: {}".format(url))
3847
if auth:
48+
logger.info("Gitlab download from private repo with token...")
3949
headers = {"PRIVATE-TOKEN": auth.password}
4050
return requests.get(url, stream=True, verify=False, headers=headers)
4151
else:
52+
logger.info("Gitlab no auth download...")
4253
return requests.get(url, stream=True, verify=False)
4354

4455
@staticmethod
4556
def _validate_response_status_code(response):
4657
if not response.ok:
47-
raise Exception('Failed to download script file: ' + str(response.status_code) + ' ' + response.reason +
58+
raise Exception('Failed to download script file: ' + str(response.status_code) + ' - ' + response.reason +
4859
'. Please make sure the URL is valid, and any required credentials are correct.')
4960

5061
@staticmethod
@@ -57,20 +68,8 @@ def _invalidate_html(self, content):
5768

5869
def _invalidate_gitlab_login_page(self, response):
5970
"""
60-
6171
:param Response response: requests response object
6272
:return:
6373
"""
6474
if self._is_content_html(response.content) and "users/sign_in" in response.url:
6575
raise Exception('Authentication failed. Reached Gitlab Login. Gitlab Access Token required.')
66-
67-
68-
if __name__ == "__main__":
69-
TEST_URL = "http://192.168.85.62/api/v4/projects/2/repository/files/my_playbook.yml/raw?ref=master"
70-
TEST_GITLAB_TOKEN = "UAAEwzj7qSZn3oHRjzbZ"
71-
# TEST_GITLAB_TOKEN = "UAAEwzj7qSZn3oHRjzbZBROKEN"
72-
auth = HttpAuth(username="", password=TEST_GITLAB_TOKEN)
73-
service = HttpRequestService()
74-
response = service.get_response(TEST_URL, auth)
75-
print(response.ok)
76-
pass

package/cloudshell/cm/ansible/domain/playbook_downloader.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@ def _download(self, url, auth, logger, cancel_sampler):
4949
:rtype [str,int]
5050
:return The downloaded file name
5151
"""
52-
logger.info('Downloading file from \'%s\' ...'%url)
52+
logger.info('Downloading file from \'%s\' ...' % url)
5353
response = self.http_request_service.get_response(url, auth, logger)
5454
file_name = self.filename_extractor.get_filename(response)
5555

56-
with self.file_system.create_file(file_name) as file:
56+
with self.file_system.create_file(file_name) as f:
5757
for chunk in response.iter_content(PlaybookDownloader.CHUNK_SIZE):
5858
if chunk:
59-
file.write(chunk)
59+
f.write(chunk)
6060
cancel_sampler.throw_if_canceled()
61-
file_size = file.tell()
61+
file_size = f.tell()
6262

6363
logger.info('Done (file: %s, size: %s bytes)).' % (file_name, file_size))
6464
return file_name, file_size
@@ -70,19 +70,21 @@ def _unzip(self, file_name, logger):
7070
:return: Playbook file name
7171
:rtype str
7272
"""
73-
logger.info('Zip file was found, extracting file: %s ...' % (file_name))
73+
logger.info('Zip file was found, extracting file: %s ...' % file_name)
7474
zip_files = self.zip_service.extract_all(file_name)
75-
logger.info('Done (extracted %s files).'%len(zip_files))
75+
logger.info('Done (extracted %s files).' % len(zip_files))
7676
logger.info('Files: ' + os.linesep + (os.linesep+'\t').join(zip_files))
7777

78-
yaml_files = [file_name for file_name in self.file_system.get_entries(self.file_system.get_working_dir()) if file_name.endswith(".yaml") or file_name.endswith(".yml")]
78+
yaml_files = [file_name for file_name in self.file_system.get_entries(self.file_system.get_working_dir())
79+
if file_name.endswith(".yaml") or file_name.endswith(".yml")]
7980
playbook_name = None
8081
if len(yaml_files) > 1:
81-
playbook_name = next((file_name for file_name in yaml_files if file_name == "site.yaml" or file_name == "site.yml"), None)
82+
playbook_name = next((file_name for file_name in yaml_files
83+
if file_name == "site.yaml" or file_name == "site.yml"), None)
8284
if len(yaml_files) == 1:
8385
playbook_name = yaml_files[0]
8486
if not playbook_name:
8587
raise Exception("Playbook file name was not found in zip file")
86-
logger.info('Found playbook: \'%s\' in zip file' % (playbook_name))
88+
logger.info('Found playbook: \'%s\' in zip file' % playbook_name)
8789

8890
return playbook_name

package/tests/mocks/file_system_service_mock.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ def get_entries(self, path):
6060
file_entries.append(file.path)
6161
return self.folders + file_entries
6262

63+
6364
class FileMock(object):
6465
def __init__(self, path, full_path):
6566
self.path = path
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from unittest import TestCase
2+
from cloudshell.cm.ansible.domain.http_request_service import HttpRequestService
3+
from models import HttpAuth
4+
from mock import Mock
5+
6+
# ADD CREDENTIALS HERE FOR TEST THEN REMOVE
7+
8+
GITHUB_USER_NAME = ""
9+
GITHUB_PASSWORD = ""
10+
GITHUB_PUBLIC_RAW_URL = ""
11+
GITHUB_PRIVATE_REPO_RAW_URL = ""
12+
13+
14+
GITLAB_PERSONAL_ACCESS_TOKEN = "UAAEwzj7qSZn3oHRjzbZ"
15+
GITLAB_PUBLIC_REPO_API_URL = "http://192.168.85.62/api/v4/projects/3/repository/files/my_playbook.yml/raw?ref=master"
16+
GITLAB_PRIVATE_REPO_API_URL = "http://192.168.85.62/api/v4/projects/2/repository/files/my_playbook.yml/raw?ref=master"
17+
GITLAB_PUBLIC_REPO_RAW_URL = "http://192.168.85.62/root/public_test/-/raw/master/my_playbook.yml"
18+
19+
20+
class TestHttpService(TestCase):
21+
def setUp(self):
22+
self.http_service = HttpRequestService()
23+
self.logger = Mock()
24+
25+
def test_gitlab_public_repo_raw_url(self):
26+
response = self.http_service.get_response(GITLAB_PUBLIC_REPO_RAW_URL, None, self.logger)
27+
self.assertTrue(response.ok)
28+
print(response.status_code)
29+
30+
def test_gitlab_private_repo_url_with_token(self):
31+
auth = HttpAuth(None, GITLAB_PERSONAL_ACCESS_TOKEN)
32+
response = self.http_service.get_response(GITLAB_PRIVATE_REPO_API_URL, auth, self.logger)
33+
self.assertTrue(response.ok)
34+
print(response.status_code)
35+
36+
def test_gitlab_private_repo_url_multi_digit_project_id(self):
37+
auth = HttpAuth(None, GITLAB_PERSONAL_ACCESS_TOKEN)
38+
response = self.http_service.get_response(GITLAB_PRIVATE_REPO_API_URL, auth, self.logger)
39+
self.assertTrue(response.ok)
40+
print(response.status_code)
41+
42+
def test_gitlab_private_repo_url_with_token_fails(self):
43+
auth = HttpAuth(None, None)
44+
with self.assertRaises(Exception):
45+
self.http_service.get_response(GITLAB_PRIVATE_REPO_API_URL, auth, self.logger)
46+
47+
def test_gitlab_public_repo_api_url_with_token(self):
48+
auth = HttpAuth(None, GITLAB_PERSONAL_ACCESS_TOKEN)
49+
response = self.http_service.get_response(GITLAB_PRIVATE_REPO_API_URL, auth, self.logger)
50+
self.assertTrue(response.ok)
51+
print(response.status_code)
52+
53+
def test_gitlab_public_repo_raw_url_with_token(self):
54+
auth = HttpAuth(None, GITLAB_PERSONAL_ACCESS_TOKEN)
55+
response = self.http_service.get_response(GITLAB_PUBLIC_REPO_RAW_URL, auth, self.logger)
56+
self.assertTrue(response.ok)
57+
print(response.status_code)
58+
59+
60+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import requests
2+
3+
TEST_URL = "http://192.168.85.62/api/v4/projects/2/repository/files/my_playbook.yml/raw?ref=master"
4+
TEST_GITLAB_TOKEN = "UAAEwzj7qSZn3oHRjzbZ"
5+
6+
7+
headers = {"PRIVATE-TOKEN": TEST_GITLAB_TOKEN}
8+
response = requests.get(TEST_URL, stream=True, verify=False, headers=headers)
9+
10+
if not response.ok:
11+
raise Exception("Failed request. Error code: {}. Reason: {}".format(response.status_code, response.reason))
12+
13+
print("=== Response Success ===")
14+
print(response.text)

package/version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.5.4
1+
1.5.5

0 commit comments

Comments
 (0)