API now connects to server lazily (#15632)

This should fix most issues with offline operation.

Fixes #14486
Fixes #13991

Alternate to #15363 and #15593
pull/15759/head
Brian Coca 9 years ago committed by Brian Coca
parent 5a9e826647
commit 74b4d7a2ae

@ -149,11 +149,7 @@ class GalaxyCLI(CLI):
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()
@ -97,7 +107,7 @@ class GalaxyAPI(object):
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.
@ -149,6 +161,7 @@ class GalaxyAPI(object):
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/?'
@ -242,6 +258,7 @@ class GalaxyAPI(object):
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…
Cancel
Save