mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-27 15:11:23 -07:00
API now connects to server lazily (#15632)
This should fix most issues with offline operation. Fixes #14486 Fixes #13991 Alternate to #15363 and #15593
This commit is contained in:
parent
c6a14567b6
commit
941564b366
2 changed files with 43 additions and 27 deletions
|
@ -51,7 +51,7 @@ class GalaxyCLI(CLI):
|
||||||
|
|
||||||
SKIP_INFO_KEYS = ("name", "description", "readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url" )
|
SKIP_INFO_KEYS = ("name", "description", "readme_html", "related", "summary_fields", "average_aw_composite", "average_aw_score", "url" )
|
||||||
VALID_ACTIONS = ("delete", "import", "info", "init", "install", "list", "login", "remove", "search", "setup")
|
VALID_ACTIONS = ("delete", "import", "info", "init", "install", "list", "login", "remove", "search", "setup")
|
||||||
|
|
||||||
def __init__(self, args):
|
def __init__(self, args):
|
||||||
self.api = None
|
self.api = None
|
||||||
self.galaxy = None
|
self.galaxy = None
|
||||||
|
@ -146,14 +146,10 @@ class GalaxyCLI(CLI):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
super(GalaxyCLI, self).run()
|
super(GalaxyCLI, self).run()
|
||||||
|
|
||||||
# if not offline, get connect to galaxy api
|
self.api = GalaxyAPI(self.galaxy)
|
||||||
if self.action in ("import","info","install","search","login","setup","delete") or \
|
|
||||||
(self.action == 'init' and not self.options.offline):
|
|
||||||
self.api = GalaxyAPI(self.galaxy)
|
|
||||||
|
|
||||||
self.execute()
|
self.execute()
|
||||||
|
|
||||||
def exit_without_ignore(self, rc=1):
|
def exit_without_ignore(self, rc=1):
|
||||||
|
@ -242,7 +238,7 @@ class GalaxyCLI(CLI):
|
||||||
# platforms included (but commented out), the galaxy_tags
|
# platforms included (but commented out), the galaxy_tags
|
||||||
# list, and the dependencies section
|
# list, and the dependencies section
|
||||||
platforms = []
|
platforms = []
|
||||||
if not offline and self.api:
|
if not offline:
|
||||||
platforms = self.api.get_list("platforms") or []
|
platforms = self.api.get_list("platforms") or []
|
||||||
|
|
||||||
# group the list of platforms from the api based
|
# group the list of platforms from the api based
|
||||||
|
@ -315,7 +311,7 @@ class GalaxyCLI(CLI):
|
||||||
role_info.update(install_info)
|
role_info.update(install_info)
|
||||||
|
|
||||||
remote_data = False
|
remote_data = False
|
||||||
if self.api:
|
if not self.options.offline:
|
||||||
remote_data = self.api.lookup_role_by_name(role, False)
|
remote_data = self.api.lookup_role_by_name(role, False)
|
||||||
|
|
||||||
if remote_data:
|
if remote_data:
|
||||||
|
|
|
@ -28,7 +28,6 @@ import json
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
from urllib2 import quote as urlquote, HTTPError
|
from urllib2 import quote as urlquote, HTTPError
|
||||||
from urlparse import urlparse
|
|
||||||
|
|
||||||
import ansible.constants as C
|
import ansible.constants as C
|
||||||
from ansible.errors import AnsibleError
|
from ansible.errors import AnsibleError
|
||||||
|
@ -41,6 +40,21 @@ except ImportError:
|
||||||
from ansible.utils.display import Display
|
from ansible.utils.display import Display
|
||||||
display = Display()
|
display = Display()
|
||||||
|
|
||||||
|
def g_connect(method):
|
||||||
|
''' wrapper to lazily initialize connection info to galaxy '''
|
||||||
|
def wrapped(self, *args, **kwargs):
|
||||||
|
if not self.initialized:
|
||||||
|
display.vvvv("Initial connection to galaxy_server: %s" % self._api_server)
|
||||||
|
server_version = self._get_server_api_version()
|
||||||
|
if not server_version in self.SUPPORTED_VERSIONS:
|
||||||
|
raise AnsibleError("Unsupported Galaxy server API version: %s" % server_version)
|
||||||
|
|
||||||
|
self.baseurl = '%s/api/%s' % (self._api_server, server_version)
|
||||||
|
self.version = server_version # for future use
|
||||||
|
display.vvvv("Base API: %s" % self.baseurl)
|
||||||
|
self.initialized = True
|
||||||
|
return method(self, *args, **kwargs)
|
||||||
|
return wrapped
|
||||||
|
|
||||||
class GalaxyAPI(object):
|
class GalaxyAPI(object):
|
||||||
''' This class is meant to be used as a API client for an Ansible Galaxy server '''
|
''' This class is meant to be used as a API client for an Ansible Galaxy server '''
|
||||||
|
@ -52,6 +66,9 @@ class GalaxyAPI(object):
|
||||||
self.token = GalaxyToken()
|
self.token = GalaxyToken()
|
||||||
self._api_server = C.GALAXY_SERVER
|
self._api_server = C.GALAXY_SERVER
|
||||||
self._validate_certs = not C.GALAXY_IGNORE_CERTS
|
self._validate_certs = not C.GALAXY_IGNORE_CERTS
|
||||||
|
self.baseurl = None
|
||||||
|
self.version = None
|
||||||
|
self.initialized = False
|
||||||
|
|
||||||
# set validate_certs
|
# set validate_certs
|
||||||
if galaxy.options.ignore_certs:
|
if galaxy.options.ignore_certs:
|
||||||
|
@ -61,15 +78,7 @@ class GalaxyAPI(object):
|
||||||
# set the API server
|
# set the API server
|
||||||
if galaxy.options.api_server != C.GALAXY_SERVER:
|
if galaxy.options.api_server != C.GALAXY_SERVER:
|
||||||
self._api_server = galaxy.options.api_server
|
self._api_server = galaxy.options.api_server
|
||||||
display.vvv("Connecting to galaxy_server: %s" % self._api_server)
|
|
||||||
|
|
||||||
server_version = self.get_server_api_version()
|
|
||||||
if not server_version in self.SUPPORTED_VERSIONS:
|
|
||||||
raise AnsibleError("Unsupported Galaxy server API version: %s" % server_version)
|
|
||||||
|
|
||||||
self.baseurl = '%s/api/%s' % (self._api_server, server_version)
|
|
||||||
self.version = server_version # for future use
|
|
||||||
display.vvv("Base API: %s" % self.baseurl)
|
|
||||||
|
|
||||||
def __auth_header(self):
|
def __auth_header(self):
|
||||||
token = self.token.get()
|
token = self.token.get()
|
||||||
|
@ -77,6 +86,7 @@ class GalaxyAPI(object):
|
||||||
raise AnsibleError("No access token. You must first use login to authenticate and obtain an access token.")
|
raise AnsibleError("No access token. You must first use login to authenticate and obtain an access token.")
|
||||||
return {'Authorization': 'Token ' + token}
|
return {'Authorization': 'Token ' + token}
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def __call_galaxy(self, url, args=None, headers=None, method=None):
|
def __call_galaxy(self, url, args=None, headers=None, method=None):
|
||||||
if args and not headers:
|
if args and not headers:
|
||||||
headers = self.__auth_header()
|
headers = self.__auth_header()
|
||||||
|
@ -91,13 +101,13 @@ class GalaxyAPI(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_server(self):
|
def api_server(self):
|
||||||
return self._api_server
|
return self._api_server
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def validate_certs(self):
|
def validate_certs(self):
|
||||||
return self._validate_certs
|
return self._validate_certs
|
||||||
|
|
||||||
def get_server_api_version(self):
|
def _get_server_api_version(self):
|
||||||
"""
|
"""
|
||||||
Fetches the Galaxy API current version to ensure
|
Fetches the Galaxy API current version to ensure
|
||||||
the API server is up and reachable.
|
the API server is up and reachable.
|
||||||
|
@ -107,8 +117,9 @@ class GalaxyAPI(object):
|
||||||
data = json.load(open_url(url, validate_certs=self._validate_certs))
|
data = json.load(open_url(url, validate_certs=self._validate_certs))
|
||||||
return data['current_version']
|
return data['current_version']
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise AnsibleError("The API server (%s) is not responding, please try again later." % url)
|
raise AnsibleError("The API server (%s) is not responding, please try again later" % url)
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def authenticate(self, github_token):
|
def authenticate(self, github_token):
|
||||||
"""
|
"""
|
||||||
Retrieve an authentication token
|
Retrieve an authentication token
|
||||||
|
@ -134,6 +145,7 @@ class GalaxyAPI(object):
|
||||||
return data['results']
|
return data['results']
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def get_import_task(self, task_id=None, github_user=None, github_repo=None):
|
def get_import_task(self, task_id=None, github_user=None, github_repo=None):
|
||||||
"""
|
"""
|
||||||
Check the status of an import task.
|
Check the status of an import task.
|
||||||
|
@ -145,10 +157,11 @@ class GalaxyAPI(object):
|
||||||
url = "%s?github_user=%s&github_repo=%s" % (url,github_user,github_repo)
|
url = "%s?github_user=%s&github_repo=%s" % (url,github_user,github_repo)
|
||||||
else:
|
else:
|
||||||
raise AnsibleError("Expected task_id or github_user and github_repo")
|
raise AnsibleError("Expected task_id or github_user and github_repo")
|
||||||
|
|
||||||
data = self.__call_galaxy(url)
|
data = self.__call_galaxy(url)
|
||||||
return data['results']
|
return data['results']
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def lookup_role_by_name(self, role_name, notify=True):
|
def lookup_role_by_name(self, role_name, notify=True):
|
||||||
"""
|
"""
|
||||||
Find a role by name.
|
Find a role by name.
|
||||||
|
@ -170,6 +183,7 @@ class GalaxyAPI(object):
|
||||||
return data["results"][0]
|
return data["results"][0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def fetch_role_related(self, related, role_id):
|
def fetch_role_related(self, related, role_id):
|
||||||
"""
|
"""
|
||||||
Fetch the list of related items for the given role.
|
Fetch the list of related items for the given role.
|
||||||
|
@ -190,6 +204,7 @@ class GalaxyAPI(object):
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def get_list(self, what):
|
def get_list(self, what):
|
||||||
"""
|
"""
|
||||||
Fetch the list of items specified.
|
Fetch the list of items specified.
|
||||||
|
@ -213,6 +228,7 @@ class GalaxyAPI(object):
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
raise AnsibleError("Failed to download the %s list: %s" % (what, str(error)))
|
raise AnsibleError("Failed to download the %s list: %s" % (what, str(error)))
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def search_roles(self, search, **kwargs):
|
def search_roles(self, search, **kwargs):
|
||||||
|
|
||||||
search_url = self.baseurl + '/search/roles/?'
|
search_url = self.baseurl + '/search/roles/?'
|
||||||
|
@ -228,7 +244,7 @@ class GalaxyAPI(object):
|
||||||
if tags and isinstance(tags, basestring):
|
if tags and isinstance(tags, basestring):
|
||||||
tags = tags.split(',')
|
tags = tags.split(',')
|
||||||
search_url += '&tags_autocomplete=' + '+'.join(tags)
|
search_url += '&tags_autocomplete=' + '+'.join(tags)
|
||||||
|
|
||||||
if platforms and isinstance(platforms, basestring):
|
if platforms and isinstance(platforms, basestring):
|
||||||
platforms = platforms.split(',')
|
platforms = platforms.split(',')
|
||||||
search_url += '&platforms_autocomplete=' + '+'.join(platforms)
|
search_url += '&platforms_autocomplete=' + '+'.join(platforms)
|
||||||
|
@ -238,10 +254,11 @@ class GalaxyAPI(object):
|
||||||
|
|
||||||
if author:
|
if author:
|
||||||
search_url += '&username_autocomplete=%s' % author
|
search_url += '&username_autocomplete=%s' % author
|
||||||
|
|
||||||
data = self.__call_galaxy(search_url)
|
data = self.__call_galaxy(search_url)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def add_secret(self, source, github_user, github_repo, secret):
|
def add_secret(self, source, github_user, github_repo, secret):
|
||||||
url = "%s/notification_secrets/" % self.baseurl
|
url = "%s/notification_secrets/" % self.baseurl
|
||||||
args = urllib.urlencode({
|
args = urllib.urlencode({
|
||||||
|
@ -253,16 +270,19 @@ class GalaxyAPI(object):
|
||||||
data = self.__call_galaxy(url, args=args)
|
data = self.__call_galaxy(url, args=args)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def list_secrets(self):
|
def list_secrets(self):
|
||||||
url = "%s/notification_secrets" % self.baseurl
|
url = "%s/notification_secrets" % self.baseurl
|
||||||
data = self.__call_galaxy(url, headers=self.__auth_header())
|
data = self.__call_galaxy(url, headers=self.__auth_header())
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def remove_secret(self, secret_id):
|
def remove_secret(self, secret_id):
|
||||||
url = "%s/notification_secrets/%s/" % (self.baseurl, secret_id)
|
url = "%s/notification_secrets/%s/" % (self.baseurl, secret_id)
|
||||||
data = self.__call_galaxy(url, headers=self.__auth_header(), method='DELETE')
|
data = self.__call_galaxy(url, headers=self.__auth_header(), method='DELETE')
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@g_connect
|
||||||
def delete_role(self, github_user, github_repo):
|
def delete_role(self, github_user, github_repo):
|
||||||
url = "%s/removerole/?github_user=%s&github_repo=%s" % (self.baseurl,github_user,github_repo)
|
url = "%s/removerole/?github_user=%s&github_repo=%s" % (self.baseurl,github_user,github_repo)
|
||||||
data = self.__call_galaxy(url, headers=self.__auth_header(), method='DELETE')
|
data = self.__call_galaxy(url, headers=self.__auth_header(), method='DELETE')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue