]> git.ipfire.org Git - pakfire.git/commitdiff
client: Rewrite of the client that interacts with the hub
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Dec 2016 23:46:38 +0000 (00:46 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 1 Dec 2016 23:46:38 +0000 (00:46 +0100)
This is a rewrite of the client that interacts with the Pakfire Hub
to upload scratch builds and retrieve the status of builds and jobs.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/pakfire/client.py

index e0eba2092e4bd5dee52ca99bf1869dfcce58eb1e..8bc5ba9062cc75c0017191d6baab4a023d8e4ae7 100644 (file)
 #                                                                             #
 ###############################################################################
 
-from . import transport
+import logging
 
-from pakfire.constants import *
-from pakfire.i18n import _
+from .ui.helpers import format_time
+
+from . import config
+from . import hub
+
+from .constants import *
+from .i18n import _
 
-import logging
 log = logging.getLogger("pakfire.client")
+log.propagate = 1
+
+class Client(object):
+       def __init__(self, config_file="client.conf"):
+               # Read configuration
+               self.config = config.Config(config_file)
+
+               # Create connection to the hub
+               self.hub = self.connect_to_hub()
+
+       def connect_to_hub(self):
+               huburl = self.config.get("client", "server", PAKFIRE_HUB)
 
-class PakfireClient(object):
-       def __init__(self, config):
-               self.config = config
+               # User Credentials
+               username = self.config.get("client", "username")
+               password = self.config.get("client", "password")
+
+               if not (username and password):
+                       raise RuntimeError("User credentials are not set")
 
                # Create connection to the hub.
-               self.transport = transport.PakfireHubTransport(self.config)
+               return hub.Hub(huburl, username, password)
+
+       def create_build(self, filename, **kwargs):
+               build_id = self.hub.create_build(filename, **kwargs)
+
+               return self.get_build(build_id)
+
+       def get_build(self, build_id):
+               return Build(self, build_id)
+
+
+class _ClientObject(object):
+       def __init__(self, client, id):
+               self.client = client
+
+               # UUID of the build
+               self.id = id
+
+               self._data = None
+               self._cache = {}
+
+       def __repr__(self):
+               return "<%s %s>" % (self.__class__.__name__, self.id)
+
+       def __eq__(self, other):
+               return self.id == other.id
+
+       @property
+       def data(self):
+               if self._data is None:
+                       self._data = self._load()
+
+               return self._data
+
+       def refresh(self):
+               self._data = self._load()
+
+       def _load(self):
+               """
+                       Loads information about this object from the hub
+               """
+               raise NotImplementedError
+
+
+class Build(_ClientObject):
+       def _load(self):
+               """
+                       Loads information about this build from the hub
+               """
+               return self.client.hub.get_build(self.id)
+
+       @property
+       def jobs(self):
+               jobs = []
+
+               for job in self.data.get("jobs"):
+                       try:
+                               j = self._cache[job]
+                       except KeyError:
+                               j = Job(self.client, job)
+
+                       jobs.append(j)
+
+               return sorted(jobs)
+
+       @property
+       def type(self):
+               """
+                       The type of this build (release or scratch)
+               """
+               return self.data.get("type")
+
+       @property
+       def _type_tag(self):
+               if self.type == "release":
+                       return "[R]"
+
+               elif self.type == "scratch":
+                       return "[S]"
+
+       @property
+       def name(self):
+               """
+                       The name of this build
+               """
+               return self.data.get("name")
+
+       @property
+       def priority(self):
+               """
+                       The priority of this build
+               """
+               return self.data.get("priority")
+
+       @property
+       def score(self):
+               """
+                       The score of this build
+               """
+               return self.data.get("score")
+
+       @property
+       def state(self):
+               """
+                       The state this build is in
+               """
+               return self.data.get("state")
+
+       def is_active(self):
+               return self.state == "building"
+
+       @property
+       def oneline(self):
+               s = [
+                       self.name,
+                       self._type_tag,
+                       "(%s)" % self.id,
+                       _("Score: %s") % self.score,
+                       _("Priority: %s") % self.priority,
+               ]
+
+               return " ".join(s)
+
+       def dump(self):
+               # Add a headline for the build
+               s = [
+                       self.oneline,
+               ]
+
+               # Add a short line for each job
+               for j in self.jobs:
+                       s.append("  %s" % j.oneline)
+
+               return "\n".join(s)
+
+
+class Job(_ClientObject):
+       def _load(self):
+               """
+                       Loads information about this job from the hub
+               """
+               return self.client.hub.get_job(self.id)
+
+       def __lt__(self, other):
+               return self.arch < other.arch
+
+       @property
+       def arch(self):
+               """
+                       The architecture of this job
+               """
+               return self.data.get("arch")
+
+       @property
+       def builder(self):
+               """
+                       The name of the builder that built this job
+               """
+               return self.data.get("builder")
+
+       @property
+       def duration(self):
+               """
+                       The duration the job took to build
+               """
+               return self.data.get("duration")
+
+       @property
+       def state(self):
+               """
+                       The state of this job
+               """
+               return self.data.get("state")
+
+       def is_active(self):
+               return self.state in ("dispatching", "running", "uploading")
+
+       def is_finished(self):
+               return self.state == "finished"
+
+       @property
+       def oneline(self):
+               s = [
+                       # Architecture
+                       "[%-8s]" % self.arch,
 
-       def build_create(self, *args, **kwargs):
-               return self.transport.build_create(*args, **kwargs)
+                       # State
+                       "[%12s]" % self.state,
+               ]
 
-       def build_get(self, *args, **kwargs):
-               return self.transport.build_get(*args, **kwargs)
+               if self.is_active():
+                       s.append(_("on %s") % self.builder)
 
-       def job_get(self, *args, **kwargs):
-               return self.transport.job_get(*args, **kwargs)
+               elif self.is_finished():
+                       s.append(_("in %s") % format_time(self.duration))
 
-       def package_get(self, *args, **kwargs):
-               return self.transport.package_get(*args, **kwargs)
+               return " ".join(s)