Skip to content

Commit 26f533a

Browse files
troyanovr00ta
andauthored
fix: use MAAS URL to build absolute uri (#287)
When MAAS is behind a load-balancer or proxy (e.g. HAProxy with `mode tcp`), we should use MAAS URL stored in profile to build absolute URI of a resource, instead of relying on `uri` property returned by `/describe`. Co-authored-by: Jacopo Rota <jacopo.rota@canonical.com>
1 parent 7f5bffa commit 26f533a

2 files changed

Lines changed: 23 additions & 14 deletions

File tree

maas/client/bones/__init__.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ async def fromURL(cls, url, *, credentials=None, insecure=False):
3838
# For now just re-raise as SessionError.
3939
raise SessionError(str(error))
4040
else:
41-
session = cls(description, credentials)
41+
session = cls(url, description, credentials)
4242
session.scheme = urlparse(url).scheme
4343
session.insecure = insecure
4444
return session
@@ -49,7 +49,7 @@ def fromProfile(cls, profile):
4949
5050
:see: `ProfileStore`.
5151
"""
52-
session = cls(profile.description, profile.credentials)
52+
session = cls(profile.url, profile.description, profile.credentials)
5353
session.scheme = urlparse(profile.url).scheme
5454
session.insecure = profile.other.get("insecure", False)
5555
return session
@@ -75,7 +75,7 @@ async def login(cls, url, *, username=None, password=None, insecure=False):
7575
profile = await helpers.login(
7676
url=url, username=username, password=password, insecure=insecure
7777
)
78-
session = cls(profile.description, profile.credentials)
78+
session = cls(url, profile.description, profile.credentials)
7979
session.scheme = urlparse(url).scheme
8080
session.insecure = insecure
8181
return profile, session
@@ -90,7 +90,7 @@ async def connect(cls, url, *, apikey=None, insecure=False):
9090
instance made using the profile.
9191
"""
9292
profile = await helpers.connect(url=url, apikey=apikey, insecure=insecure)
93-
session = cls(profile.description, profile.credentials)
93+
session = cls(url, profile.description, profile.credentials)
9494
session.scheme = urlparse(url).scheme
9595
session.insecure = insecure
9696
return profile, session
@@ -100,13 +100,15 @@ async def connect(cls, url, *, apikey=None, insecure=False):
100100
insecure = False
101101
debug = False
102102

103-
def __init__(self, description, credentials=None):
103+
def __init__(self, url, description, credentials=None):
104104
"""Construct a `SessionAPI`.
105105
106+
:param url: MAAS URL
106107
:param description: The description of the remote API. See `fromURL`.
107108
:param credentials: Credentials for the remote system. Optional.
108109
"""
109110
super(SessionAPI, self).__init__()
111+
self.__url = url
110112
self.__description = description
111113
self.__credentials = credentials
112114
self.__populate()
@@ -116,15 +118,15 @@ def __populate(self):
116118
if self.__credentials is None:
117119
for resource in resources:
118120
if resource["anon"] is not None:
119-
handler = HandlerAPI(resource["anon"], resource, self)
121+
handler = HandlerAPI(self.__url, resource["anon"], resource, self)
120122
setattr(self, handler.name, handler)
121123
else:
122124
for resource in resources:
123125
if resource["auth"] is not None:
124-
handler = HandlerAPI(resource["auth"], resource, self)
126+
handler = HandlerAPI(self.__url, resource["auth"], resource, self)
125127
setattr(self, handler.name, handler)
126128
elif resource["anon"] is not None:
127-
handler = HandlerAPI(resource["anon"], resource, self)
129+
handler = HandlerAPI(self.__url, resource["anon"], resource, self)
128130
setattr(self, handler.name, handler)
129131

130132
@property
@@ -154,16 +156,18 @@ class HandlerAPI:
154156
operations.
155157
"""
156158

157-
def __init__(self, handler, resource, session):
159+
def __init__(self, url, handler, resource, session):
158160
"""Construct a `HandlerAPI`.
159161
162+
:param url: MAAS URL
160163
:param handler: The handler description from the overall API
161164
description document. See `SessionAPI`.
162165
:param resource: The parent of `handler` in the API description
163166
document. XXX: This does not appear to be needed.
164167
:param session: The `SessionAPI`.
165168
"""
166169
super(HandlerAPI, self).__init__()
170+
self.__url = url
167171
self.__handler = handler
168172
self.__resource = resource
169173
self.__session = session
@@ -187,7 +191,8 @@ def uri(self):
187191
This will typically contain replacement patterns; these are
188192
interpolated in `CallAPI`.
189193
"""
190-
return self.__handler["uri"]
194+
url = urlparse(self.__url)
195+
return f"{url.scheme}://{url.netloc}{self.__handler['path']}"
191196

192197
@property
193198
def params(self):

maas/client/bones/tests/test.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,10 @@ class TestActionAPI_APIVersions(TestCase):
7272
for name, version, description in testing.api_descriptions
7373
)
7474

75+
url = "http://127.0.0.1:8080/MAAS/api/2.0/"
76+
7577
def test__Version_read(self):
76-
session = bones.SessionAPI(self.description)
78+
session = bones.SessionAPI(self.url, self.description)
7779
action = session.Version.read
7880
self.assertThat(
7981
action,
@@ -91,7 +93,7 @@ def test__Machines_deployment_status(self):
9193
if self.version > (2, 0):
9294
self.skipTest("Machines.deployment_status only in <= 2.0")
9395

94-
session = bones.SessionAPI(self.description, ("a", "b", "c"))
96+
session = bones.SessionAPI(self.url, self.description, ("a", "b", "c"))
9597
action = session.Machines.deployment_status
9698
self.assertThat(
9799
action,
@@ -106,7 +108,7 @@ def test__Machines_deployment_status(self):
106108
)
107109

108110
def test__Machines_power_parameters(self):
109-
session = bones.SessionAPI(self.description, ("a", "b", "c"))
111+
session = bones.SessionAPI(self.url, self.description, ("a", "b", "c"))
110112
action = session.Machines.power_parameters
111113
self.assertThat(
112114
action,
@@ -129,9 +131,11 @@ class TestCallAPI_APIVersions(TestCase):
129131
for name, version, description in testing.api_descriptions
130132
)
131133

134+
url = "http://127.0.0.1:8080/MAAS/api/2.0/"
135+
132136
def test__marshals_lists_into_query_as_repeat_parameters(self):
133137
system_ids = list(str(uuid1()) for _ in range(3))
134-
session = bones.SessionAPI(self.description, ("a", "b", "c"))
138+
session = bones.SessionAPI(self.url, self.description, ("a", "b", "c"))
135139
call = session.Machines.power_parameters.bind()
136140
call.dispatch = Mock()
137141

0 commit comments

Comments
 (0)