Skip to content

Commit

Permalink
fix: enable base_path for controller url (#654)
Browse files Browse the repository at this point in the history
A controller url like "https://awx-host/awx" is not supported trying the
connection against "https://awx-host/[AWX-SLUG]"

Fixes: #652
Jira: https://issues.redhat.com/browse/AAP-19726
  • Loading branch information
Alex-Izquierdo authored Jan 24, 2024
1 parent eff4dbb commit 73e0974
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- Generic print as well as printing of events use new banner style

### Fixed
- Support a base path for the controller url

## [1.0.4] - 2023-10-30

Expand Down
14 changes: 12 additions & 2 deletions ansible_rulebook/job_template_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import aiohttp
import dpath

from ansible_rulebook import util
from ansible_rulebook.exception import (
ControllerApiException,
JobTemplateNotFoundException,
Expand All @@ -34,8 +35,8 @@


class JobTemplateRunner:
UNIFIED_TEMPLATE_SLUG = "/api/v2/unified_job_templates/"
CONFIG_SLUG = "/api/v2/config/"
UNIFIED_TEMPLATE_SLUG = "api/v2/unified_job_templates/"
CONFIG_SLUG = "api/v2/config/"
JOB_COMPLETION_STATUSES = ["successful", "failed", "error", "canceled"]

def __init__(
Expand All @@ -47,6 +48,7 @@ def __init__(
verify_ssl: str = "yes",
):
self.token = token
self._host = ""
self.host = host
self.username = username
self.password = password
Expand All @@ -56,6 +58,14 @@ def __init__(
)
self._session = None

@property
def host(self):
return self._host

@host.setter
def host(self, value: str):
self._host = util.ensure_trailing_slash(value)

async def close_session(self):
if self._session and not self._session.closed:
await self._session.close()
Expand Down
6 changes: 6 additions & 0 deletions ansible_rulebook/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,9 @@ def process_controller_host_limit(
return ",".join(job_args["limit"])
return str(job_args["limit"])
return ",".join(parent_hosts)


def ensure_trailing_slash(url: str) -> str:
if not url.endswith("/"):
return url + "/"
return url
10 changes: 5 additions & 5 deletions tests/data/awx_test_data.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
UNIFIED_JOB_TEMPLATE_COUNT = 2
ORGANIZATION_NAME = "Default"
JOB_TEMPLATE_NAME_1 = "JT1"
JOB_TEMPLATE_1_LAUNCH_SLUG = "/api/v2/job_templates/255/launch/"
JOB_TEMPLATE_2_LAUNCH_SLUG = "/api/v2/workflow_job_templates/300/launch/"
JOB_TEMPLATE_1_LAUNCH_SLUG = "api/v2/job_templates/255/launch/"
JOB_TEMPLATE_2_LAUNCH_SLUG = "api/v2/workflow_job_templates/300/launch/"

JOB_TEMPLATE_1 = dict(
type="job_template",
Expand All @@ -24,10 +24,10 @@
)

UNIFIED_JOB_TEMPLATE_PAGE1_SLUG = (
f"/api/v2/unified_job_templates/?name={JOB_TEMPLATE_NAME_1}"
f"api/v2/unified_job_templates/?name={JOB_TEMPLATE_NAME_1}"
)
UNIFIED_JOB_TEMPLATE_PAGE2_SLUG = (
f"/api/v2/unified_job_templates/?name={JOB_TEMPLATE_NAME_1}&page=2"
f"api/v2/unified_job_templates/?name={JOB_TEMPLATE_NAME_1}&page=2"
)
UNIFIED_JOB_TEMPLATE_PAGE1_RESPONSE = dict(
count=UNIFIED_JOB_TEMPLATE_COUNT,
Expand Down Expand Up @@ -58,7 +58,7 @@
"barney": 90,
}
JOB_ID_1 = 909
JOB_1_SLUG = f"/api/v2/jobs/{JOB_ID_1}/"
JOB_1_SLUG = f"api/v2/jobs/{JOB_ID_1}/"
JOB_TEMPLATE_POST_RESPONSE = dict(
job=JOB_ID_1,
url=JOB_1_SLUG,
Expand Down
55 changes: 54 additions & 1 deletion tests/test_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from unittest.mock import AsyncMock, MagicMock, patch

import pytest
from aiohttp import ClientError
Expand Down Expand Up @@ -39,7 +40,17 @@
UNIFIED_JOB_TEMPLATE_PAGE2_SLUG,
)

CONFIG_SLUG = "/api/v2/config/"
CONFIG_SLUG = "api/v2/config/"


@pytest.fixture
def new_job_template_runner():
from ansible_rulebook.job_template_runner import JobTemplateRunner

return JobTemplateRunner(
host="https://example.com",
token="DUMMY",
)


@pytest.fixture
Expand Down Expand Up @@ -221,3 +232,45 @@ async def test_run_workflow_template_fail(mocked_job_template_runner):
ORGANIZATION_NAME,
{"a": 1, "limit": "all"},
)


@pytest.mark.parametrize(
("host", "expected"),
[
("https://example.com", "https://example.com/api/v2/config/"),
("https://example.com/", "https://example.com/api/v2/config/"),
(
"https://example.com/custom/awx",
"https://example.com/custom/awx/api/v2/config/",
),
(
"https://example.com/awx/",
"https://example.com/awx/api/v2/config/",
),
(
"https://example.com/custom/awx/",
"https://example.com/custom/awx/api/v2/config/",
),
],
)
@pytest.mark.asyncio
async def test_session_get_called_with_expected_url(
new_job_template_runner,
host,
expected,
):
with patch(
"ansible_rulebook.job_template_runner.aiohttp.ClientSession"
) as mock:
mocked_session = AsyncMock()
mocked_session.get = MagicMock()
mocked_session.get.return_value.__aenter__.return_value = MagicMock(
status=200,
text=AsyncMock(return_value=json.dumps({"a": 1})),
)
mock.return_value = mocked_session
new_job_template_runner.host = host
await new_job_template_runner.get_config()
calls = mocked_session.get.mock_calls[0]
args = calls[1]
assert args[0] == expected

0 comments on commit 73e0974

Please sign in to comment.