Anton Troyanov has proposed merging ~troyanov/maas:describe-maas-url into 
maas:master.

Commit message:
fix(cli): use profile.url to build absolute uri

When MAAS is behind a load-balancer or proxy
(e.g. HAProxy with `mode tcp`), CLI should use MAAS URL stored in profile
to build absolute URI of a resource, instead of relying on `uri` property
returned by `/describe`.

Resolves LP:2009186

Requested reviews:
  MAAS Lander (maas-lander)
  Igor Brovtsin (igor-brovtsin)
Related bugs:
  Bug #2009186 in MAAS: "CLI results in connection timed out when behind 
haproxy and 5240 is blocked"
  https://bugs.launchpad.net/maas/+bug/2009186

For more details, see:
https://code.launchpad.net/~troyanov/maas/+git/maas/+merge/438387

Consider the following deployment:

1. HAProxy (mode tcp) that listens on `10.37.215.16:80`
2. MAAS available on `10.81.242.188:5240 `

> cat haproxy.cfg
frontend maas
    bind    *:80
    retries 3
    option  redispatch
    option  http-server-close
    default_backend maas_tls

backend maas
    timeout server 900s
    balance source
    hash-type consistent
    server maas-api-0 10.81.242.188:5240 check

When we are making a call to `http://10.37.215.16/MAAS/api/2.0/describe/` it 
will return resources information with `uri` pointing to `10.81.242.188:5240` 
instead of `10.37.215.16`
{
  "doc": "Manage the collection of boot sources.",
  "name": "BootSourcesHandler",
  "params": [],
  "path": "/MAAS/api/2.0/boot-sources/",
  "uri": "http://10.81.242.188:5240/MAAS/api/2.0/boot-sources/";
}

Thats because current logic is to take MAAS URL from HTTP `Host` header, which 
is not set by HAProxy, but rather by nginx (which comes with MAAS), so there is 
no way for MAAS to know that it was accessed through another proxy from the 
Host header.

That leads to an issue with CLI, which is using `uri` to execute commands.

This fix will changes CLI behaviour. Now instead of blindly using value of 
`uri`, it will now build correct URI from profile["url"] and resource `path` 
property.

profile["url"] is MAAS URL used during `maas login` 
-- 
Your team MAAS Committers is subscribed to branch maas:master.
diff --git a/src/maascli/api.py b/src/maascli/api.py
index d121309..1b8ef6d 100644
--- a/src/maascli/api.py
+++ b/src/maascli/api.py
@@ -90,7 +90,10 @@ class Action(Command):
     # Override these in subclasses; see `register_actions`.
     profile = handler = action = None
 
-    uri = property(lambda self: self.handler["uri"])
+    maas_url = property(lambda self: urlparse(self.profile["url"]))
+    uri = property(
+        lambda self: f"{self.maas_url.scheme}://{self.maas_url.netloc}{self.handler['path']}"
+    )
     method = property(lambda self: self.action["method"])
     credentials = property(lambda self: self.profile["credentials"])
     op = property(lambda self: self.action["op"])
diff --git a/src/maascli/tests/test_api.py b/src/maascli/tests/test_api.py
index a767648..22515f8 100644
--- a/src/maascli/tests/test_api.py
+++ b/src/maascli/tests/test_api.py
@@ -304,7 +304,8 @@ class TestAction(MAASTestCase):
             "name": factory.make_name("handler"),
             "handler_name": factory.make_name("handler"),
             "params": [],
-            "uri": "http://example.com/api/2.0/";,
+            "path": "/MAAS/api/2.0",
+            "uri": "http://example.com/MAAS/api/2.0/";,
         }
         action = {"name": "action", "op": "test", "method": "GET"}
         action_name = safe_name(action["name"])
-- 
Mailing list: https://launchpad.net/~sts-sponsors
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~sts-sponsors
More help   : https://help.launchpad.net/ListHelp

Reply via email to