ansible / django-ansible-base

Apache License 2.0
18 stars 49 forks source link

Exit `resource_sync` command as a no-op if `RESOURCE_SERVER` undefined #607

Open AlanCoding opened 2 months ago

AlanCoding commented 2 months ago

We have a command:

https://github.com/ansible/django-ansible-base/blob/devel/ansible_base/resource_registry/management/commands/resource_sync.py

This will pull changes from the resource server to the local server. But what if there is no resource server??

Demo:

$ python manage.py resource_sync
2024-09-05 17:55:43,479 DEBUG    []  psycopg.pq couldn't import psycopg 'c' implementation: No module named 'psycopg_c'
2024-09-05 17:55:43,964 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.api_documentation.urls
2024-09-05 17:55:43,964 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.api_documentation.urls
2024-09-05 17:55:44,181 DEBUG    []  ansible_base.authentication.urls Loaded URLS from ansible_base.authentication.authenticator_plugins.saml
2024-09-05 17:55:44,181 DEBUG    []  ansible_base.authentication.urls Loaded URLS from ansible_base.authentication.authenticator_plugins.saml
2024-09-05 17:55:44,208 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.authentication.urls
2024-09-05 17:55:44,208 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.authentication.urls
2024-09-05 17:55:44,208 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Module ansible_base.rest_filters does not specify urls.py
2024-09-05 17:55:44,208 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Module ansible_base.rest_filters does not specify urls.py
2024-09-05 17:55:44,209 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.jwt_consumer.urls
2024-09-05 17:55:44,209 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.jwt_consumer.urls
2024-09-05 17:55:44,212 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.resource_registry.urls
2024-09-05 17:55:44,212 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.resource_registry.urls
2024-09-05 17:55:44,212 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Module ansible_base.rest_pagination does not specify urls.py
2024-09-05 17:55:44,212 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Module ansible_base.rest_pagination does not specify urls.py
2024-09-05 17:55:44,216 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.rbac.urls
2024-09-05 17:55:44,216 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.rbac.urls
2024-09-05 17:55:44,218 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.oauth2_provider.urls
2024-09-05 17:55:44,218 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.oauth2_provider.urls
2024-09-05 17:55:44,220 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.activitystream.urls
2024-09-05 17:55:44,220 DEBUG    []  ansible_base.lib.dynamic_config.dynamic_urls Including URLS from ansible_base.activitystream.urls
----- RESOURCE SYNC STARTED -----

>>> shared.authenticator
2024-09-05 17:55:44,341 INFO     []  ansible_base.resources_api.rest_client Making get request to http://localhost/api/gateway/v1/service-index/metadata/.
2024-09-05 17:55:44,341 INFO     []  ansible_base.resources_api.rest_client Making get request to http://localhost/api/gateway/v1/service-index/metadata/.
2024-09-05 17:55:44,553 DEBUG    []  urllib3.connectionpool Starting new HTTP connection (1): localhost:80
Traceback (most recent call last):
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connection.py", line 174, in _new_conn
    conn = connection.create_connection(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/util/connection.py", line 95, in create_connection
    raise err
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/util/connection.py", line 85, in create_connection
    sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connectionpool.py", line 715, in urlopen
    httplib_response = self._make_request(
                       ^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connectionpool.py", line 416, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connection.py", line 244, in request
    super(HTTPConnection, self).request(method, url, body=body, headers=headers)
  File "/usr/lib64/python3.12/http/client.py", line 1336, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/lib64/python3.12/http/client.py", line 1382, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.12/http/client.py", line 1331, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/lib64/python3.12/http/client.py", line 1091, in _send_output
    self.send(msg)
  File "/usr/lib64/python3.12/http/client.py", line 1035, in send
    self.connect()
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connection.py", line 205, in connect
    conn = self._new_conn()
           ^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connection.py", line 186, in _new_conn
    raise NewConnectionError(
urllib3.exceptions.NewConnectionError: <urllib3.connection.HTTPConnection object at 0x7fbf3209c9b0>: Failed to establish a new connection: [Errno 111] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/requests/adapters.py", line 486, in send
    resp = conn.urlopen(
           ^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/connectionpool.py", line 799, in urlopen
    retries = retries.increment(
              ^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/urllib3/util/retry.py", line 592, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /api/gateway/v1/service-index/metadata/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fbf3209c9b0>: Failed to establish a new connection: [Errno 111] Connection refused'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/arominge/repos/awx/django-ansible-base/manage.py", line 22, in <module>
    main()
  File "/home/arominge/repos/awx/django-ansible-base/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/django/core/management/__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/django/core/management/base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/django/core/management/base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/repos/awx/django-ansible-base/ansible_base/resource_registry/management/commands/resource_sync.py", line 80, in handle
    executor.run()
  File "/home/arominge/repos/awx/django-ansible-base/ansible_base/resource_registry/tasks/sync.py", line 373, in run
    manifest_list = fetch_manifest(resource_type_name, api_client=self.api_client)
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/repos/awx/django-ansible-base/ansible_base/resource_registry/tasks/sync.py", line 85, in fetch_manifest
    resp_metadata = api_client.get_service_metadata()
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/repos/awx/django-ansible-base/ansible_base/resource_registry/rest_client.py", line 127, in get_service_metadata
    return self._make_request("get", "metadata/")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/repos/awx/django-ansible-base/ansible_base/resource_registry/rest_client.py", line 106, in _make_request
    resp = requests.request(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/requests/api.py", line 59, in request
    return session.request(method=method, url=url, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/requests/sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/requests/sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/arominge/venv/awx/lib64/python3.12/site-packages/requests/adapters.py", line 519, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='localhost', port=80): Max retries exceeded with url: /api/gateway/v1/service-index/metadata/ (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fbf3209c9b0>: Failed to establish a new connection: [Errno 111] Connection refused'))

We have an emerging practice in other places where we check resource_server_defined() and do a silent exit if that returns False. This is because a resource server URL has not been configured, and there are many deployments we expect to run this way. The above traceback does not follow this practice, and it should.

Notably, AWX will run this every 15 minutes:

https://github.com/ansible/awx/blob/79684ab6033fb999ddfcf8e3ef7c2e4c7d806e39/awx/main/tasks/system.py#L979

And that would result in the above error. Still, even if it gives that error, no harm. But we would prefer a simple debug-level message and exit.