[copr] master: Fix the authentication using token ID (8264cf2)
by Pierre-YvesChibon
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 8264cf2b38971613a77fc552495c22991cd5b944
Author: Pierre-Yves Chibon <pingou(a)pingoured.fr>
Date: Sun Jan 20 23:22:49 2013 +0100
Fix the authentication using token ID
>---------------------------------------------------------------
coprs_frontend/coprs/views/misc.py | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/coprs_frontend/coprs/views/misc.py b/coprs_frontend/coprs/views/misc.py
index 78c9721..9640d8b 100644
--- a/coprs_frontend/coprs/views/misc.py
+++ b/coprs_frontend/coprs/views/misc.py
@@ -74,8 +74,8 @@ def logout():
def login_required(f):
@functools.wraps(f)
def decorated_function(*args, **kwargs):
- token = flask.request.form.get('token')
- username = flask.request.form.get('username')
+ token = flask.request.args.get('token')
+ username = flask.request.args.get('username')
token_auth = False
if token and username:
user = models.User.query.filter(
11 years, 4 months
Pierre-Yves Chibon Added to copr git commit
by Seth Vidal
Hi folks,
I added Pierre-Yves (pingou) to the copr git commit list. He's helping in
lots of things and it just made sense.
Let me know if that's not okay but I think it is.
-sv
11 years, 4 months
[copr] master: Merge branch 'master' of ssh://git.fedorahosted.org/git/copr (d6baf2b)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit d6baf2b77e6bdf2fa001b89e711d2e5dddb44389
Merge: 44e1d1d f6508e3
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:05:45 2013 +0100
Merge branch 'master' of ssh://git.fedorahosted.org/git/copr
>---------------------------------------------------------------
backend/dispatcher.py | 42 +++++++++----
backend/mockremote.py | 10 ++-
copr-be.py | 165 +++++++++++++++++++++++++++++++++----------------
3 files changed, 147 insertions(+), 70 deletions(-)
diff --git a/backend/dispatcher.py b/backend/dispatcher.py
index 92395ce..5fa6aa0 100644
--- a/backend/dispatcher.py
+++ b/backend/dispatcher.py
@@ -68,18 +68,16 @@ class WorkerCallback(object):
self.logfile = logfile
def log(self, msg):
- if not self.logfile:
- return
-
- now = time.strftime('%F %T')
- try:
- open(self.logfile, 'a').write(str(now) + ': ' + msg + '\n')
- except (IOError, OSError), e:
- print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.logfile, str(e))
+ if self.logfile:
+ now = time.strftime('%F %T')
+ try:
+ open(self.logfile, 'a').write(str(now) + ': ' + msg + '\n')
+ except (IOError, OSError), e:
+ print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.logfile, str(e))
class Worker(multiprocessing.Process):
- def __init__(self, opts, jobs, worker_num, ip=None, create=True, callback=None):
+ def __init__(self, opts, jobs, events, worker_num, ip=None, create=True, callback=None):
# base class initialization
multiprocessing.Process.__init__(self, name="worker-builder")
@@ -87,6 +85,7 @@ class Worker(multiprocessing.Process):
# job management stuff
self.jobs = jobs
+ self.events = events # event queue for communicating back to dispatcher
self.worker_num = worker_num
self.ip = ip
self.opts = opts
@@ -99,11 +98,23 @@ class Worker(multiprocessing.Process):
if ip:
self.callback.log('creating worker: %s' % ip)
+ self.event('creating worker: %s' % ip)
else:
self.callback.log('creating worker: dynamic ip')
+ self.event('creating worker: dynamic ip')
+
+ def event(self, what):
+ if self.ip:
+ who = 'worker-%s-%s' % (self.worker_num, self.ip)
+ else:
+ who = 'worker-%s' % (self.worker_num)
+
+ self.events.put({'when':time.time(), 'who':who, 'what':what})
def spawn_instance(self):
"""call the spawn playbook to startup/provision a building instance"""
+
+
self.callback.log('spawning instance begin')
start = time.time()
@@ -143,7 +154,7 @@ class Worker(multiprocessing.Process):
stats = callbacks.AggregateStats()
playbook_cb = SilentPlaybookCallbacks(verbose=False)
runner_cb = callbacks.DefaultRunnerCallbacks()
- play = ansible.playbook.PlayBook(host_list=[ip], stats=stats, playbook=self.opts.terminate_playbook,
+ play = ansible.playbook.PlayBook(host_list=ip +',', stats=stats, playbook=self.opts.terminate_playbook,
callbacks=playbook_cb, runner_callbacks=runner_cb,
remote_user='root')
@@ -167,6 +178,8 @@ class Worker(multiprocessing.Process):
jobdata.repos.append(jobdata.results)
jobdata.copr_id = build['copr']['id']
jobdata.user_id = build['user_id']
+ jobdata.user_name = build['copr']['owner']['name']
+ jobdata.copr_name = build['copr']['name']
return jobdata
# maybe we move this to the callback?
@@ -195,6 +208,7 @@ class Worker(multiprocessing.Process):
# maybe we move this to the callback?
def mark_started(self, job):
+
build = {'id':job.build_id,
'started_on': job.started_on,
'results': job.results,
@@ -206,8 +220,8 @@ class Worker(multiprocessing.Process):
# maybe we move this to the callback?
def return_results(self, job):
- self.callback.log('%s status %s. Took %s seconds' % (job.build_id, job.status, job.ended_on - job.started_on))
+ self.callback.log('%s status %s. Took %s seconds' % (job.build_id, job.status, job.ended_on - job.started_on))
build = {'id':job.build_id,
'ended_on': job.ended_on,
'status': job.status,
@@ -256,8 +270,10 @@ class Worker(multiprocessing.Process):
job.started_on = time.time()
self.mark_started(job)
- for chroot in job.chroots:
+ self.event('build start: user:%s copr:%s build:%s ip:%s pid:%s' % (job.user_name, job.copr_name, job.build_id, ip, self.pid))
+ for chroot in job.chroots:
+ self.event('chroot start: chroot:%s user:%s copr:%s build:%s ip:%s pid:%s' % (chroot, job.user_name, job.copr_name, job.build_id, ip, self.pid))
chroot_destdir = job.destdir + '/' + chroot
# setup our target dir locally
if not os.path.exists(chroot_destdir):
@@ -296,12 +312,12 @@ class Worker(multiprocessing.Process):
if mr.failed:
status = 0
self.callback.log('Finished build: id=%r builder=%r timeout=%r destdir=%r chroot=%r repos=%r' % (job.build_id, ip, job.timeout, job.destdir, chroot, str(job.repos)))
-
job.ended_on = time.time()
job.status = status
self.return_results(job)
self.callback.log('worker finished build: %s' % ip)
+ self.event('build end: user:%s copr:%s build:%s ip:%s pid:%s status:%s' % (job.user_name, job.copr_name, job.build_id, ip, self.pid, job.status))
# clean up the instance
if self.create:
self.terminate_instance(ip)
diff --git a/backend/mockremote.py b/backend/mockremote.py
index 7017a51..2e1e19f 100755
--- a/backend/mockremote.py
+++ b/backend/mockremote.py
@@ -96,7 +96,7 @@ def get_ans_results(results, hostname):
def _create_ans_conn(hostname, username, timeout):
ans_conn = ansible.runner.Runner(remote_user=username,
- host_list=[hostname], pattern=hostname, forks=1,
+ host_list=hostname + ',', pattern=hostname, forks=1,
timeout=timeout)
return ans_conn
@@ -203,7 +203,7 @@ class CliLogCallBack(DefaultCallBack):
try:
open(self.logfn, 'a').write(str(now) + ':' + msg + '\n')
except (IOError, OSError), e:
- print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.lf, str(e))
+ print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.logfn, str(e))
if not self.quiet:
print msg
@@ -299,6 +299,7 @@ class Builder(object):
#print ' Running %s on %s' % (buildcmd, hostname)
# run the mockchain command async
# this runs it sync - FIXME
+ self.mockremote.callback.log('executing: %r' % buildcmd)
self.conn.module_name="shell"
self.conn.module_args = str(buildcmd)
results = self.conn.run()
@@ -362,7 +363,8 @@ class Builder(object):
raise BuilderError('%s could not be resolved' % self.hostname)
# connect as user
- ans = ansible.runner.Runner(host_list=[self.hostname], pattern='*',
+
+ ans = ansible.runner.Runner(host_list=self.hostname + ',', pattern='*',
remote_user=self.username, forks=1, timeout=20)
ans.module_name = "shell"
ans.module_args = str("/bin/rpm -q mock rsync")
@@ -486,7 +488,7 @@ class MockRemote(object):
if not os.path.exists(self.destdir + '/' + self.chroot):
os.makedirs(self.destdir + '/' + self.chroot)
r_log = open(self.destdir + '/' + self.chroot + '/mockchain.log', 'a')
- r_log.write('%s\n' % pkg)
+ r_log.write('\n\n%s\n\n' % pkg)
r_log.write(b_out)
if b_err:
r_log.write('\nstderr\n')
diff --git a/copr-be.py b/copr-be.py
index 6631ac4..dfcd4c0 100644
--- a/copr-be.py
+++ b/copr-be.py
@@ -21,7 +21,102 @@ def _get_conf(cp, section, option, default):
return default
+
+class CoprJobGrab(multiprocessing.Process):
+ """Fetch jobs from the Frontend - submit them to the jobs queue for workers"""
+
+ def __init__(self, opts, events, jobs):
+ # base class initialization
+ multiprocessing.Process.__init__(self, name="jobgrab")
+
+ self.opts = opts
+ self.events = events
+ self.jobs = jobs
+ self.added_jobs = []
+
+ def event(self, what):
+ self.events.put({'when':time.time(), 'who':'jobgrab', 'what':what})
+
+ def fetch_jobs(self):
+ try:
+ r = requests.get('%s/waiting_builds/' % self.opts.frontend_url) # auth stuff here? maybe/maybenot
+ except requests.RequestException, e:
+ self.event('Error retrieving jobs from %s: %s' % (self.opts.frontend_url, e))
+ else:
+ try:
+ r_json = json.loads(r.content) # using old requests on el6 :(
+ except ValueError, e:
+ self.event('Error getting JSON build list from FE %s' % e)
+ return
+
+ if 'builds' in r_json and r_json['builds']:
+ self.event('%s jobs returned' % len(r_json['builds']))
+ count = 0
+ for b in r_json['builds']:
+ if 'id' in b:
+ jobfile = self.opts.jobsdir + '/%s.json' % b['id']
+ if not os.path.exists(jobfile) and b['id'] not in self.added_jobs:
+ count += 1
+ open(jobfile, 'w').write(json.dumps(b))
+ self.event('Wrote job: %s' % b['id'])
+ if count:
+ self.event('New jobs: %s' % count)
+
+ def run(self):
+ abort = False
+ while not abort:
+ self.fetch_jobs()
+ for f in sorted(glob.glob(self.opts.jobsdir + '/*.json')):
+ n = os.path.basename(f).replace('.json', '')
+ if n not in self.added_jobs:
+ self.jobs.put(f)
+ self.added_jobs.append(n)
+ self.event('adding to work queue id %s' % n)
+ time.sleep(self.opts.sleeptime)
+
+
+class CoprLog(multiprocessing.Process):
+ """log mechanism where items from the events queue get recorded"""
+ def __init__(self, opts, events):
+
+ # base class initialization
+ multiprocessing.Process.__init__(self, name="logger")
+
+ self.opts = opts
+ self.events = events
+
+ logdir = os.path.dirname(self.opts.logfile)
+ if not os.path.exists(logdir):
+ os.makedirs(logdir, mode=0750)
+
+ if not os.path.exists(self.opts.destdir):
+ os.makedirs(self.opts.destdir, mode=0755)
+
+ # setup a log file to write to
+ self.logfile = self.opts.logfile
+
+ def log(self, event):
+
+ when = time.strftime('%F %T', time.gmtime(event['when']))
+ msg = '%s : %s: %s' % (when, event['who'], event['what'].strip())
+
+ try:
+ open(self.logfile, 'a').write(msg + '\n')
+ except (IOError, OSError), e:
+ print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.logfile, str(e))
+
+
+ # event format is a dict {when:time, who:[worker|logger|job|main], what:str}
+ def run(self):
+ abort = False
+ while not abort:
+ e = self.events.get()
+ if 'when' in e and 'who' in e and 'what' in e:
+ self.log(e)
+
class CoprBackend(object):
+ """core process - starts/stops/initializes workers"""
+
def __init__(self, config_file=None, ext_opts=None):
# read in config file
# put all the config items into a single self.opts bunch
@@ -33,25 +128,28 @@ class CoprBackend(object):
self.ext_opts = ext_opts # to stow our cli options for read_conf()
self.opts = self.read_conf()
- logdir = os.path.dirname(self.opts.logfile)
- if not os.path.exists(logdir):
- os.makedirs(logdir, mode=0750)
+ self.jobs = multiprocessing.Queue() # job is a path to a jobfile on the localfs
+ self.events = multiprocessing.Queue()
+ # event format is a dict {when:time, who:[worker|logger|job|main], what:str}
- if not os.path.exists(self.opts.destdir):
- os.makedirs(self.opts.destdir, mode=0755)
- # setup a log file to write to
- self.logfile = self.opts.logfile
- self.log("Starting up new copr-be instance")
+ # create logger
+ self._logger = CoprLog(self.opts, self.events)
+ self._logger.start()
+ self.event('Starting up Job Grabber')
+ # create job grabber
+ self._jobgrab = CoprJobGrab(self.opts, self.events, self.jobs)
+ self._jobgrab.start()
if not os.path.exists(self.opts.worker_logdir):
os.makedirs(self.opts.worker_logdir, mode=0750)
- self.jobs = multiprocessing.Queue()
self.workers = []
self.added_jobs = []
+ def event(self, what):
+ self.events.put({'when':time.time(), 'who':'main', 'what':what})
def read_conf(self):
"read in config file - return Bunch of config data"
@@ -90,64 +188,25 @@ class CoprBackend(object):
return opts
- def log(self, msg):
- now = time.strftime('%F %T')
- output = str(now) + ': ' + msg
- if not self.opts.daemonize:
- print output
-
- try:
- open(self.logfile, 'a').write(output + '\n')
- except (IOError, OSError), e:
- print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.logfile, str(e))
-
-
- def fetch_jobs(self):
- self.log('fetching jobs')
- try:
- r = requests.get('%s/waiting_builds/' % self.opts.frontend_url) # auth stuff here? maybe/maybenot
- except requests.RequestException, e:
- self.log('Error retrieving jobs from %s: %s' % (self.opts.frontend_url, e))
- else:
- r_json = json.loads(r.content) # using old requests on el6 :(
- if 'builds' in r_json:
- self.log('%s jobs returned' % len(r_json['builds']))
- count = 0
- for b in r_json['builds']:
- if 'id' in b:
- jobfile = self.opts.jobsdir + '/%s.json' % b['id']
- if not os.path.exists(jobfile) and b['id'] not in self.added_jobs:
- count += 1
- open(jobfile, 'w').write(json.dumps(b))
- self.log('Wrote job: %s' % b['id'])
- self.log('New jobs: %s' % count)
def run(self):
abort = False
while not abort:
- self.fetch_jobs()
- for f in sorted(glob.glob(self.opts.jobsdir + '/*.json')):
- n = os.path.basename(f).replace('.json', '')
- if n not in self.added_jobs:
- self.jobs.put(f)
- self.added_jobs.append(n)
- self.log('adding to work queue id %s' % n)
-
# re-read config into opts
self.opts = self.read_conf()
if self.jobs.qsize():
- self.log("# jobs in queue: %s" % self.jobs.qsize())
+ self.event("# jobs in queue: %s" % self.jobs.qsize())
# this handles starting/growing the number of workers
if len(self.workers) < self.opts.num_workers:
- self.log("Spinning up more workers for jobs")
+ self.event("Spinning up more workers for jobs")
for i in range(self.opts.num_workers - len(self.workers)):
worker_num = len(self.workers) + 1
- w = Worker(self.opts, self.jobs, worker_num)
+ w = Worker(self.opts, self.jobs, self.events, worker_num)
self.workers.append(w)
w.start()
- self.log("Finished starting worker processes")
+ self.event("Finished starting worker processes")
# FIXME - prune out workers
#if len(self.workers) > self.opts.num_workers:
# killnum = len(self.workers) - self.opts.num_workers
@@ -158,7 +217,7 @@ class CoprBackend(object):
# check for dead workers and abort
for w in self.workers:
if not w.is_alive():
- self.log('Worker %d died unexpectedly' % w.worker_num)
+ self.event('Worker %d died unexpectedly' % w.worker_num)
if self.opts.exit_on_worker:
raise errors.CoprBackendError, "Worker died unexpectedly, exiting"
else:
11 years, 4 months
[copr] master: This was moved to templates/coprs/detail/_permissions_table.html (44e1d1d)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 44e1d1da72830626deae54589543585107d43327
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:04:45 2013 +0100
This was moved to templates/coprs/detail/_permissions_table.html
>---------------------------------------------------------------
.../coprs/templates/coprs/_permissions_table.html | 90 --------------------
1 files changed, 0 insertions(+), 90 deletions(-)
diff --git a/coprs_frontend/coprs/templates/coprs/_permissions_table.html b/coprs_frontend/coprs/templates/coprs/_permissions_table.html
deleted file mode 100644
index a8675ec..0000000
--- a/coprs_frontend/coprs/templates/coprs/_permissions_table.html
+++ /dev/null
@@ -1,90 +0,0 @@
-{% macro permissions_table(permissions, current_user_permissions, copr, permissions_applier_form, permissions_form) %}
- {% if permissions or g.user != copr.owner %} {# display the whole table if there are permissions or user can ask for them #}
- {% if permissions_applier_form and g.user %}
- <form action="{{ url_for('coprs_ns.copr_permissions_applier_change', username = copr.owner.name, coprname = copr.name)}}" method=post>
- {{ permissions_applier_form.csrf_token }}
- {% endif %}
- {% if permissions_form and g.user %}
- <form action="{{ url_for('coprs_ns.copr_update_permissions', username = copr.owner.name, coprname = copr.name)}}" method=post>
- {{ permissions_form.csrf_token }}
- {% endif %}
- <table class=permissions-table>
- <tr><th>Username</th><th>Is Builder</th><th>Is Admin</th></tr>
- {% for perm in permissions %}
- {% if perm.user_id != g.user.id %} {# if user is logged in, only display his form below, not a row #}
- {{ permissions_table_row_other_user(perm, permissions_applier_form, permissions_form) }}
- {% endif %}
- {% endfor %}
- {{ permissions_table_row_current_user(current_user_permissions, permissions_applier_form, permissions_form) }}
- </table>
- {% if g.user and (permissions_applier_form or permissions_form) %} {# TODO: when to display? #}
- <input type=submit value=Submit>
- </form>
- {% endif %}
- {% else %}
- No permissions for other users for this Copr.
- {% endif %}
-{% endmacro %}
-
-{% macro permissions_table_row_other_user(perm, permissions_applier_form, permissions_form) %}
- <tr>
- <td>{{ perm.user.name }}</td>
- <td>
- {% if permissions_form %}
- {% if perm.copr_builder != 0 %}
- {{ permissions_form['copr_builder_{0}'.format(perm.user.id)] }}
- {% endif %}
- {% else %}
- {{ perm.copr_builder|perm_type_from_num }}
- {% endif %}
- </td>
- <td>
- {% if permissions_form %}
- {% if perm.copr_admin != 0 %}
- {{ permissions_form['copr_admin_{0}'.format(perm.user.id)] }}
- {% endif %}
- {% else %}
- {{ perm.copr_admin|perm_type_from_num }}
- {% endif %}
- </td>
- </tr>
-{% endmacro %}
-
-{% macro permissions_table_row_current_user(current_user_permissions, permissions_applier_form, permissions_form) %}
- {# if user is logged in and permissions_applier_form is defined, display it #}
- {% if g.user and permissions_applier_form %}
- <tr>
- <td>{{ g.user.name }}</td>
- <td>
- {% if current_user_permissions %}
- {{ current_user_permissions.copr_builder|perm_type_from_num }}
- {% else %}
- Not requested
- {% endif %}
- <br>
- {{ permissions_applier_form.copr_builder|safe }}
- </td>
- <td>
- {% if current_user_permissions %}
- {{ current_user_permissions.copr_admin|perm_type_from_num }}
- {% else %}
- Not requested
- {% endif %}
- <br>
- {{ permissions_applier_form.copr_admin|safe }}
- </tr>
- {% endif %}
-
- {# if user is admin (means current_user_permissions is set), display his own permissions for changing #}
- {% if g.user and permissions_form and current_user_permissions %}
- <tr>
- <td>{{ g.user.name }}</td>
- <td>
- {{ permissions_form['copr_builder_{0}'.format(g.user.id)] }}
- </td>
- <td>
- {{ permissions_form['copr_admin_{0}'.format(g.user.id)] }}
- </td>
- </tr>
- {% endif %}
-{% endmacro %}
11 years, 4 months
[copr] master: Add the nice pink arrow image (dc2302e)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit dc2302ed326e69024f01d2b56e27760801ff1e02
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:04:00 2013 +0100
Add the nice pink arrow image
>---------------------------------------------------------------
coprs_frontend/coprs/static/pink_arrow.png | Bin 0 -> 382 bytes
1 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/coprs_frontend/coprs/static/pink_arrow.png b/coprs_frontend/coprs/static/pink_arrow.png
new file mode 100644
index 0000000..fec3cf7
Binary files /dev/null and b/coprs_frontend/coprs/static/pink_arrow.png differ
11 years, 4 months
[copr] master: Actually commit the templates :) (e98f165)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit e98f1658ce12b73c153f1b5d14de7146939a74ad
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:03:45 2013 +0100
Actually commit the templates :)
>---------------------------------------------------------------
.../coprs/detail/.builds.html.swp} | Bin 12288 -> 12288 bytes
.../coprs/templates/coprs/detail/_build_forms.html | 24 ++++++++++
.../coprs/{ => detail}/_permissions_table.html | 0
.../coprs/templates/coprs/detail/builds.html | 12 +++++
.../coprs/templates/coprs/detail/overview.html | 45 ++++++++++++++++++++
.../coprs/templates/coprs/detail/permissions.html | 9 ++++
6 files changed, 90 insertions(+), 0 deletions(-)
diff --git a/coprs_frontend/coprs/logic/.coprs_logic.py.swo b/coprs_frontend/coprs/templates/coprs/detail/.builds.html.swp
similarity index 67%
copy from coprs_frontend/coprs/logic/.coprs_logic.py.swo
copy to coprs_frontend/coprs/templates/coprs/detail/.builds.html.swp
index b244106..bfa2ee8 100644
Binary files a/coprs_frontend/coprs/logic/.coprs_logic.py.swo and b/coprs_frontend/coprs/templates/coprs/detail/.builds.html.swp differ
diff --git a/coprs_frontend/coprs/templates/coprs/detail/_build_forms.html b/coprs_frontend/coprs/templates/coprs/detail/_build_forms.html
new file mode 100644
index 0000000..a5d6c4e
--- /dev/null
+++ b/coprs_frontend/coprs/templates/coprs/detail/_build_forms.html
@@ -0,0 +1,24 @@
+{% macro copr_build_form(form, view, copr) %}
+ <form action="{{ url_for(view, username = copr.owner.name, coprname = copr.name) }}" method=post class=add-entry>
+ <dl>
+ {{ form.csrf_token }}
+ {{ render_field(form.pkgs, rows = 10, cols = 50) }}
+ {% if g.user.proven %}
+ {{ render_field(form.memory_reqs) }}
+ {{ render_field(form.timeout) }}
+ {% else %} {# once we pass the hidden attribute, the field will just be hidden, it seems #}
+ {{ render_field(form.memory_reqs, hidden = True) }}
+ {{ render_field(form.timeout, hidden = True) }}
+ {% endif %}
+ <dd><input type=submit value=Submit></dd>
+ </dl>
+ </form>
+{% endmacro %}
+
+{% macro copr_build_cancel_form(build) %}
+ {% if build.cancelable %}
+ <form action="{{ url_for('coprs_ns.copr_cancel_build', username = build.copr.owner.name, coprname = build.copr.name, build_id = build.id)}}" method=post>
+ <input type=submit value=Cancel>
+ </form>
+ {% endif %}
+{% endmacro %}
diff --git a/coprs_frontend/coprs/templates/coprs/_permissions_table.html b/coprs_frontend/coprs/templates/coprs/detail/_permissions_table.html
similarity index 100%
copy from coprs_frontend/coprs/templates/coprs/_permissions_table.html
copy to coprs_frontend/coprs/templates/coprs/detail/_permissions_table.html
diff --git a/coprs_frontend/coprs/templates/coprs/detail/builds.html b/coprs_frontend/coprs/templates/coprs/detail/builds.html
new file mode 100644
index 0000000..c2882b8
--- /dev/null
+++ b/coprs_frontend/coprs/templates/coprs/detail/builds.html
@@ -0,0 +1,12 @@
+{% extends "coprs/detail.html" %}
+{% from "coprs/_builds_table.html" import builds_table with context %}
+
+{% block detail_body %}
+ {% if copr.builds %}
+ <h3>Latest 10 in this repo</h3>
+ {{ builds_table(copr.builds) }}
+ <a href="{{ url_for('coprs_ns.copr_show_builds', username = copr.owner.name, coprname = copr.name) }}">Show all builds</a>
+ {% else %}
+ <h3>No builds so far</h3>
+ {% endif %}
+{% endblock %}
diff --git a/coprs_frontend/coprs/templates/coprs/detail/overview.html b/coprs_frontend/coprs/templates/coprs/detail/overview.html
new file mode 100644
index 0000000..82cb8d5
--- /dev/null
+++ b/coprs_frontend/coprs/templates/coprs/detail/overview.html
@@ -0,0 +1,45 @@
+{% extends "coprs/detail.html" %}
+{% block detail_body %}
+ <h2>Description</h2>
+ <div class="shift-right">This is a description...</div>
+ <h2>Installation Instructions</h2>
+ <div class="shift-right">These are installation instructions...</div>
+ <h2>Active Releases</h2>
+ <table class="releases">
+ <tr>
+ <th class="leftmost">Release</th>
+ <th class="rightmost">Architecture</th>
+ </tr>
+ {% for mock_chroot in copr.mock_chroots %}
+ {% if loop.index < copr.mock_chroots|length %}
+ {% if mock_chroot.os_release != copr.mock_chroots[loop.index].os_release or
+ mock_chroot.os_version != copr.mock_chroots[loop.index].os_version %}
+ {# next release is different => release-end #}
+ <tr class="release-end">
+ {% else %}
+ <tr>
+ {% endif %}
+ {% else %}{# last line => release-end for sure #}
+ <tr class="release-end">
+ {% endif %}
+ {% if mock_chroot.os_release != copr.mock_chroots[loop.index0 - 1].os_release or
+ mock_chroot.os_version != copr.mock_chroots[loop.index0 - 1].os_version %}
+ <td>{{ mock_chroot.os_release|capitalize }} {{ mock_chroot.os_version }}</td>
+ {% else %}
+ <td></td>
+ {% endif %}
+ <td>{{ mock_chroot.arch }}</td>
+ </tr>
+ {% else %}
+ <tr colspan="2"><td>No active releases</td></tr>
+ {% endfor %}
+ </table>
+ {% if copr.repos_list %}
+ <h2>Repository List</h2>
+ <ul class=repos-list>
+ {% for repo in copr.repos_list %}
+ <li><a href="{{ repo }}">{{ repo }}</a></li>
+ {% endfor %}
+ </ul>
+ {% endif %}
+{% endblock %}
diff --git a/coprs_frontend/coprs/templates/coprs/detail/permissions.html b/coprs_frontend/coprs/templates/coprs/detail/permissions.html
new file mode 100644
index 0000000..2b2ad6d
--- /dev/null
+++ b/coprs_frontend/coprs/templates/coprs/detail/permissions.html
@@ -0,0 +1,9 @@
+{% extends "coprs/detail.html" %}
+{% from "coprs/detail/_permissions_table.html" import permissions_table with context%}
+
+{% block detail_body %}
+ {% if (g.user and g.user != copr.owner) or permissions %}
+ {# the table is displayed only if there are some permissions or a non-owner is viewing the page (then display at least his applier form #}
+ {{ permissions_table(permissions, current_user_permissions, copr, permissions_applier_form, permissions_form) }}
+ {% endif %}
+{% endblock %}
11 years, 4 months
[copr] master: Refactor the views to match the new templates (48778a6)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 48778a655550b4df255bb90c877e9becaf8c4aa7
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:03:31 2013 +0100
Refactor the views to match the new templates
>---------------------------------------------------------------
.../coprs/views/coprs_ns/coprs_general.py | 39 ++++++++++++++------
1 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
index b408d30..027845b 100644
--- a/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
+++ b/coprs_frontend/coprs/views/coprs_ns/coprs_general.py
@@ -19,13 +19,13 @@ from coprs.logic import coprs_logic
@coprs_ns.route('/<int:page>/')
def coprs_show(page = 1):
if flask.g.user:
- query = coprs_logic.CoprsLogic.get_multiple(flask.g.user, user_relation = 'owned', username = flask.g.user.name)
+ query = coprs_logic.CoprsLogic.get_multiple(flask.g.user, user_relation='owned', username=flask.g.user.name)
else:
query = coprs_logic.CoprsLogic.get_multiple(flask.g.user)
paginator = helpers.Paginator(query, query.count(), page)
coprs = paginator.sliced_query
- return flask.render_template('coprs/show.html', coprs = coprs, paginator = paginator)
+ return flask.render_template('coprs/show.html', coprs=coprs, paginator=paginator)
@coprs_ns.route('/owned/<username>/', defaults = {'page': 1})
@@ -86,15 +86,21 @@ def copr_new():
else:
return flask.render_template('coprs/add.html', form = form)
-
@coprs_ns.route('/detail/<username>/<coprname>/')
-def copr_detail(username, coprname, build_form = None):
- if not build_form:
- build_form = forms.BuildForm()
- try: # query[0:10][0] will raise an index error, if Copr doesn't exist
- query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname, with_builds = True)
- copr = query[0:10][0]# we retrieved all builds, but we got one copr in a list...
- except IndexError:
+def copr_detail(username, coprname):
+ query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname)
+ copr = query.first()
+ if not copr:
+ return page_not_found('Copr with name {0} does not exist.'.format(coprname))
+
+ return flask.render_template('coprs/detail/overview.html',
+ copr=copr)
+
+(a)coprs_ns.route('/detail/<username>/<coprname>/permissions/')
+def copr_permissions(username, coprname):
+ query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname)
+ copr = query.first()
+ if not copr:
return page_not_found('Copr with name {0} does not exist.'.format(coprname))
permissions = coprs_logic.CoprsPermissionLogic.get_for_copr(flask.g.user, copr).all()
@@ -114,14 +120,23 @@ def copr_detail(username, coprname, build_form = None):
# https://github.com/ajford/flask-wtf/issues/58
permissions_applier_form = forms.PermissionsApplierFormFactory.create_form_cls(user_perm)(formdata=None)
- return flask.render_template('coprs/detail.html',
+ return flask.render_template('coprs/detail/permissions.html',
copr = copr,
- build_form = build_form,
permissions_form = permissions_form,
permissions_applier_form = permissions_applier_form,
permissions = permissions,
current_user_permissions = user_perm)
+(a)coprs_ns.route('/detail/<username>/<coprname>/builds/')
+def copr_builds(username, coprname, build_form = None):
+ try: # query[0:10][0] will raise an index error, if Copr doesn't exist
+ query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname, with_builds = True)
+ copr = query[0:10][0]# we retrieved all builds, but we got one copr in a list...
+ except IndexError:
+ return page_not_found('Copr with name {0} does not exist.'.format(coprname))
+
+ return flask.render_template('coprs/detail/builds.html',
+ copr = copr)
@coprs_ns.route('/detail/<username>/<coprname>/edit/')
@login_required
11 years, 4 months
[copr] master: Refactor the detail templates (3cc766d)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 3cc766d7ddd7d7328a872d13a9e503074bd9585c
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:02:46 2013 +0100
Refactor the detail templates
>---------------------------------------------------------------
.../coprs/templates/coprs/_coprs_forms.html | 25 --------------------
1 files changed, 0 insertions(+), 25 deletions(-)
diff --git a/coprs_frontend/coprs/templates/coprs/_coprs_forms.html b/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
index 4256bdc..4d6341a 100644
--- a/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
+++ b/coprs_frontend/coprs/templates/coprs/_coprs_forms.html
@@ -59,28 +59,3 @@
</form>
{% endif %}
{% endmacro %}
-
-{% macro copr_build_form(form, view, copr) %}
- <form action="{{ url_for(view, username = copr.owner.name, coprname = copr.name) }}" method=post class=add-entry>
- <dl>
- {{ form.csrf_token }}
- {{ render_field(form.pkgs, rows = 10, cols = 50) }}
- {% if g.user.proven %}
- {{ render_field(form.memory_reqs) }}
- {{ render_field(form.timeout) }}
- {% else %} {# once we pass the hidden attribute, the field will just be hidden, it seems #}
- {{ render_field(form.memory_reqs, hidden = True) }}
- {{ render_field(form.timeout, hidden = True) }}
- {% endif %}
- <dd><input type=submit value=Submit></dd>
- </dl>
- </form>
-{% endmacro %}
-
-{% macro copr_build_cancel_form(build) %}
- {% if build.cancelable %}
- <form action="{{ url_for('coprs_ns.copr_cancel_build', username = build.copr.owner.name, coprname = build.copr.name, build_id = build.id)}}" method=post>
- <input type=submit value=Cancel>
- </form>
- {% endif %}
-{% endmacro %}
11 years, 4 months
[copr] master: Add the menu to copr detail and split the detail into simpler subpages (952ad77)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 952ad7753afe494edeb4073ff4f3f3c12da8f85c
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 16:02:10 2013 +0100
Add the menu to copr detail and split the detail into simpler subpages
>---------------------------------------------------------------
coprs_frontend/coprs/static/style-new.css | 79 ++++++++++++++++++++++
coprs_frontend/coprs/templates/coprs/detail.html | 56 ++++++----------
2 files changed, 99 insertions(+), 36 deletions(-)
diff --git a/coprs_frontend/coprs/static/style-new.css b/coprs_frontend/coprs/static/style-new.css
index 9ed1715..cf69fd6 100644
--- a/coprs_frontend/coprs/static/style-new.css
+++ b/coprs_frontend/coprs/static/style-new.css
@@ -2,6 +2,7 @@ html, body {
font-family: Cantarell, "Droid Sans", Verdana, sans-serif;
font-size: 1em;
+ color: #666666;
margin: 0px;
padding: 0px;
}
@@ -11,6 +12,15 @@ a {
text-decoration: none;
}
+h1 {
+ font-weight: normal;
+ color: #3d69a8;
+}
+
+h2 {
+ font-size: 1.1em;
+}
+
#logo {
position: relative;
top: 8px;
@@ -130,9 +140,78 @@ div.add-copr a {
color: #666666;
}
+div.horizontal-menu {
+ background-color: #ededed;
+ padding: 0.5em;
+ height: 2em;
+
+ border-radius: 10px;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+}
+
+div.horizontal-menu a {
+ font-size: 1.1em;
+ font-weight: bold;
+ color: #4d4d4d;
+}
+
+div.horizontal-menu img {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+div.horizontal-menu div.selected a {
+ color: #db3279;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+div.horizontal-menu div.selected, div.horizontal-menu div.unselected {
+ margin-right: 1em;
+ display: inline;
+ float: left;
+}
+
+div.shift-right {
+ margin-left: 1em;
+}
+
input.rounded {
padding-left: 4px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
+
+table.releases {
+ width: 100%;
+ border-collapse:collapse;
+}
+
+table.releases th {
+ background-color: #f2f2f2;
+}
+
+table.releases th.leftmost {
+ border-top-left-radius: 10px;
+ -moz-border-radius-topleft: 10px;
+ -webkit-border-top-left-radius: 10px;
+ border-bottom-left-radius: 10px;
+ -moz-border-radius-bottomleft: 10px;
+ -webkit-border-bottom-left-radius: 10px;
+}
+
+table.releases th.rightmost {
+ border-top-right-radius: 10px;
+ -moz-border-radius-topright: 10px;
+ -webkit-border-top-right-radius: 10px;
+ border-bottom-right-radius: 10px;
+ -moz-border-radius-bottomright: 10px;
+ -webkit-border-bottom-right-radius: 10px;
+}
+
+table.releases tr.release-end {
+ border-bottom: 3px solid #f2f2f2;
+}
diff --git a/coprs_frontend/coprs/templates/coprs/detail.html b/coprs_frontend/coprs/templates/coprs/detail.html
index e895973..e12e5f1 100644
--- a/coprs_frontend/coprs/templates/coprs/detail.html
+++ b/coprs_frontend/coprs/templates/coprs/detail.html
@@ -1,43 +1,27 @@
{% extends "layout.html" %}
{% block title %}{{ copr.owner.name }}/{{ copr.name }} Copr{% endblock %}
{% block header %}Information for Copr {{ copr.owner.name }}/{{ copr.name }}{% endblock %}
-{% from "coprs/_builds_table.html" import builds_table with context %}
-{% from "coprs/_permissions_table.html" import permissions_table with context%}
-{% from "coprs/_coprs_forms.html" import copr_build_form,
+{% from "coprs/detail/_build_forms.html" import copr_build_form,
copr_build_cancel_form with context %}
{% block body %}
- <h3>chroots</h3>
- <ul class=chroots-list>
- {% for mock_chroot in copr.mock_chroots %}
- <li>{{ mock_chroot.chroot_name }}</li>
- {% endfor %}
- </ul>
- {% if copr.repos %}
- <h3>repos</h3>
- <ul class=repos-list>
- {% for repo in copr.repos_list %}
- <li><a href="{{ repo }}">{{ repo }}</a></li>
- {% endfor %}
- </ul>
- {% endif %}
- <h3>Permissions</h3>
- {% if (g.user and g.user != copr.owner) or permissions %}
- {# the table is displayed only if there are some permissions or a non-owner is viewing the page (then display at least his applier form #}
- {{ permissions_table(permissions, current_user_permissions, copr, permissions_applier_form, permissions_form) }}
- {% endif %}
- {% if g.user and g.user.can_build_in(copr) %}
- <h3>Build packages in this repo:</h3>
- {{ copr_build_form(build_form, 'coprs_ns.copr_add_build', copr) }}
- {% endif %}
- {% if g.user and g.user.can_edit(copr) %}
- <a href="{{ url_for('coprs_ns.copr_edit', username = copr.owner.name, coprname = copr.name) }}">Edit this Copr</a>
- {% endif %}
- {% if copr.builds %}
- <h3>Latest 10 in this repo</h3>
- {{ builds_table(copr.builds) }}
- <a href="{{ url_for('coprs_ns.copr_show_builds', username = copr.owner.name, coprname = copr.name) }}">Show all builds</a>
- {% else %}
- <h3>No builds so far</h3>
- {% endif %}
+ <h1>{{ copr.owner.name }} / <strong>{{ copr.name }}</strong></h1>
+ <div class="horizontal-menu">
+ <div class="selected">
+ <a href="{{ url_for('coprs_ns.copr_detail', username = copr.owner.name, coprname = copr.name) }}">Overview</a>
+ <img src="{{ url_for('static', filename='pink_arrow.png') }}">
+ </div>
+ <div class="unselected">
+ <a href="{{ url_for('coprs_ns.copr_permissions', username = copr.owner.name, coprname = copr.name) }}">Permissions</a>
+ </div>
+ <div class="unselected">
+ <a href="{{ url_for('coprs_ns.copr_builds', username = copr.owner.name, coprname = copr.name) }}">Builds</a>
+ </div>
+ {% if g.user and g.user.can_edit(copr) %}
+ <div class="unselected">
+ <a href="{{ url_for('coprs_ns.copr_edit', username = copr.owner.name, coprname = copr.name) }}">Edit</a>
+ </div>
+ {% endif %}
+ </div>
+ {% block detail_body %}{% endblock %}
{% endblock %}
11 years, 4 months
[copr] master: A small fix in getting copr repos list (59a18bb)
by bkabrda@fedoraproject.org
Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
>---------------------------------------------------------------
commit 59a18bb7097bf882897815edf7fbdada3c5da355
Author: Bohuslav Kabrda <bkabrda(a)redhat.com>
Date: Fri Jan 18 15:42:38 2013 +0100
A small fix in getting copr repos list
>---------------------------------------------------------------
coprs_frontend/coprs/models.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/coprs_frontend/coprs/models.py b/coprs_frontend/coprs/models.py
index c9888ca..573c472 100644
--- a/coprs_frontend/coprs/models.py
+++ b/coprs_frontend/coprs/models.py
@@ -117,7 +117,7 @@ class Copr(db.Model, Serializer):
@property
def repos_list(self):
- return self.repos.split(' ')
+ return self.repos.split()
@property
def mock_chroots(self):
11 years, 4 months