Merge branch 'master' of /git/ansible

This commit is contained in:
Stephen Smoogen 2014-05-13 22:41:48 +00:00
commit bd09bf39fe
28 changed files with 12050 additions and 24 deletions

View file

@ -0,0 +1,6 @@
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.5.126.23 infrastructure.fedoraproject.org
10.5.126.23 puppet.fedoraproject.org puppet infrastructure.fedoraproject.org
10.5.126.52 admin.fedoraproject.org
10.5.125.36 kojipkgs.fedoraproject.org kojipkgs

View file

@ -29,15 +29,6 @@ buildvm-26.phx2.fedoraproject.org
buildvm-27.phx2.fedoraproject.org
[buildvmhost]
buildvmhost-01.phx2.fedoraproject.org
buildvmhost-02.phx2.fedoraproject.org
buildvmhost-03.phx2.fedoraproject.org
buildvmhost-04.phx2.fedoraproject.org
buildvmhost-05.phx2.fedoraproject.org
buildvmhost-06.phx2.fedoraproject.org
buildvmhost-07.phx2.fedoraproject.org
buildvmhost-08.phx2.fedoraproject.org
buildvmhost-09.phx2.fedoraproject.org
buildvmhost-10.phx2.fedoraproject.org
buildvmhost-11.phx2.fedoraproject.org
buildvmhost-12.phx2.fedoraproject.org
@ -46,6 +37,16 @@ buildvmhost-12.phx2.fedoraproject.org
[buildhw]
buildhw-01.phx2.fedoraproject.org
buildhw-02.phx2.fedoraproject.org
buildhw-03.phx2.fedoraproject.org
buildhw-04.phx2.fedoraproject.org
buildhw-05.phx2.fedoraproject.org
buildhw-06.phx2.fedoraproject.org
buildhw-07.phx2.fedoraproject.org
buildhw-08.phx2.fedoraproject.org
buildhw-09.phx2.fedoraproject.org
buildhw-10.phx2.fedoraproject.org
buildhw-11.phx2.fedoraproject.org
buildhw-12.phx2.fedoraproject.org
[buildppc]
buildppc-01.phx2.fedoraproject.org

View file

@ -1,5 +1,2 @@
---
freezes: true

View file

@ -99,8 +99,6 @@ bodhi01.stg.phx2.fedoraproject.org
[bvirthost]
bvirthost01.phx2.fedoraproject.org
bvirthost02.phx2.fedoraproject.org
bvirthost03.phx2.fedoraproject.org
bvirthost04.phx2.fedoraproject.org
bvirthost05.phx2.fedoraproject.org
bvirthost06.phx2.fedoraproject.org
@ -352,10 +350,9 @@ paste02.phx2.fedoraproject.org
[paste-stg]
paste01.stg.phx2.fedoraproject.org
# Not yet spun up
#[pkgdb]
#pkgdb01.phx2.fedoraproject.org
#pkgdb02.phx2.fedoraproject.org
[pkgdb]
pkgdb01.phx2.fedoraproject.org
pkgdb02.phx2.fedoraproject.org
[pkgdb-stg]
pkgdb01.stg.phx2.fedoraproject.org
@ -467,7 +464,6 @@ virthost07.phx2.fedoraproject.org
virthost08.phx2.fedoraproject.org
virthost09.phx2.fedoraproject.org
virthost10.phx2.fedoraproject.org
virthost11.phx2.fedoraproject.org
virthost12.phx2.fedoraproject.org
virthost14.phx2.fedoraproject.org
virthost15.phx2.fedoraproject.org

View file

@ -2,6 +2,7 @@
hosts: docs-backend
user: root
gather_facts: False
accelerate: True
vars_files:
- /srv/web/infra/ansible/vars/global.yml
@ -18,6 +19,7 @@
hosts: docs-backend
user: root
gather_facts: True
accelerate: True
vars_files:
- /srv/web/infra/ansible/vars/global.yml
@ -40,6 +42,25 @@
- include: "{{ tasks }}/2fa_client.yml"
- include: "{{ tasks }}/motd.yml"
- include: "{{ tasks }}/sudo.yml"
# we want httpd for now, to examine the product directly
- include: "{{ tasks }}/apache.yml"
handlers:
- include: "{{ handlers }}/restart_services.yml"
- name: setup publican web
hosts: docs-backend
user: root
gather_facts: True
accelerate: True
vars_files:
- /srv/web/infra/ansible/vars/global.yml
- "{{ private }}/vars.yml"
- /srv/web/infra/ansible/vars/{{ ansible_distribution }}.yml
roles:
- { role: publican_webhost, kojitag: "el6-docs", publican_brand: "fedora", site_title: "Fedora Documentation", site_host: "http://docs.fedoraproject.org" }
handlers:
- include: "{{ handlers }}/restart_services.yml"

View file

@ -42,6 +42,10 @@
- geoip-city-wsgi
- role: koji_reminder
when: master_sundries_node
- role: easyfix
when: master_sundries_node
- role: fedora_owner_change
when: master_sundries_node
tasks:
- include: "{{ tasks }}/hosts.yml"

View file

@ -0,0 +1,6 @@
# Sends the reminder about coming meetings
#
# The frequency set here should be consistent with the one set in the
# configuration file.
#
*/30 * * * * apache cd /srv/web/gather-easyfix && /usr/bin/python /usr/local/bin/gather_easyfix.py

View file

@ -0,0 +1,266 @@
#!/usr/bin/python -tt
#-*- coding: utf-8 -*-
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
The idea of this program is to gather tickets from different project
which are marked as 'easyfix' (or any other keyword for that matter).
This version is a simple proof of concept, eventually it should be
converted to an html page and this script run by a cron job of some sort.
The different project to suscribe by email or a git repo or a page on
the wiki. To be sorted out...
"""
import datetime
import json
import logging
import os
import re
import urllib2
import xmlrpclib
from bugzilla.rhbugzilla import RHBugzilla
import fedora.client
from kitchen.text.converters import to_bytes
# Let's import template stuff
from jinja2 import Template
__version__ = '0.1.1'
bzclient = RHBugzilla(url='https://bugzilla.redhat.com/xmlrpc.cgi',
cookiefile=None)
# So the bugzilla module has some way to complain
logging.basicConfig()
logger = logging.getLogger('bugzilla')
#logger.setLevel(logging.DEBUG)
RETRIES = 2
class MediaWikiException(Exception):
""" MediaWikiException class.
Exception class generated when something has gone wrong while
querying the MediaWiki instance of the project.
"""
pass
class MediaWiki(fedora.client.Wiki):
""" Mediawiki class.
Handles interaction with the Mediawiki.
Code stollen from cnucnu:
http://fedorapeople.org/gitweb?p=till/public_git/cnucnu.git;a=summary
"""
def __init__(self, base_url='https://fedoraproject.org/w/', *args,
**kwargs):
""" Instanciate a Mediawiki client.
:arg base_url: base url of the mediawiki to query.
"""
super(MediaWiki, self).__init__(base_url, *args, **kwargs)
def json_request(self, method="api.php", req_params=None,
auth=False, **kwargs):
""" Perform a json request to retrieve the content of a page.
"""
if req_params:
req_params["format"] = "json"
data = None
for i in range(0, RETRIES+1):
try:
data = self.send_request(method, req_params, auth, **kwargs)
except fedora.client.ServerError, ex:
if i >= RETRIES:
raise MediaWikiException(
'Could not contact the wiki -- error: %s' % ex)
else:
break
if 'error' in data:
raise MediaWikiException(data['error']['info'])
return data
def get_pagesource(self, titles):
""" Retrieve the content of a given page from Mediawiki.
:arg titles, the title of the page to return
"""
data = self.json_request(req_params={
'action': 'query',
'titles': titles,
'prop': 'revisions',
'rvprop': 'content'
}
)
return data['query']['pages'].popitem()[1]['revisions'][0]['*']
class Project(object):
""" Simple object representation of a project. """
def __init__(self):
self.name = ""
self.url = ""
self.site = ""
self.owner = ""
self.tag = ""
self.tickets = []
class Ticket(object):
""" Simple object representation of a ticket. """
def __init__(self):
self.id = ""
self.url = ""
self.title = ""
self.status = ""
self.type = ""
self.component = ""
def gather_bugzilla_easyfix():
""" From the Red Hat bugzilla, retrieve all new tickets flagged as
easyfix.
"""
bugbz = bzclient.query(
{'f1': 'keywords',
'o1': 'allwords',
'v1': 'easyfix',
'query_format': 'advanced',
'bug_status': ['NEW'],
'classification': 'Fedora'})
#print " {0} easyfix bugs retrieve from the BZ ".format(len(bugbz))
return bugbz
def gather_project():
""" Retrieve all the projects which have subscribed to this idea.
"""
wiki = MediaWiki(base_url='https://fedoraproject.org/w/')
page = wiki.get_pagesource("Easyfix")
projects = []
for row in page.split('\n'):
regex = re.search(' \* ([^ ]*) ([^ ]*)( [^ ]*)?', row)
if regex:
project = Project()
project.name = regex.group(1)
project.tag = regex.group(2)
project.owner = regex.group(3)
projects.append(project)
return projects
def get_open_tickets_for_keyword(project, keyword):
""" For a given project return the tickets ID which have the given
keyword attached.
:arg project, name of the project on fedorahosted.org
:arg keyword, search the trac for open tickets having this keyword
in the keywords field.
"""
tickets = []
try:
server = xmlrpclib.ServerProxy(
'https://fedorahosted.org/%s/rpc' % project)
query = 'status=assigned&status=new&status=reopened&' \
'keywords=~%s' % keyword
for ticket in server.ticket.query(query):
tickets.append(server.ticket.get(ticket))
except xmlrpclib.Error, err:
print ' Could not retrieve information for project: %s' % project
print ' Error: %s' % err
return tickets
def main():
""" For each projects which have suscribed in the correct place
(fedoraproject wiki page), gather all the tickets containing the
provided keyword.
"""
template = '/etc/fedora-gather-easyfix/template.html'
if not os.path.exists(template):
template = './template.html'
if not os.path.exists(template):
print 'No template found'
return 1
try:
projects = gather_project()
except MediaWikiException, ex:
print ex
return
ticket_num = 0
for project in projects:
#print 'Project: %s' % project.name
tickets = []
if project.name.startswith('github:'):
project.name = project.name.split('github:')[1]
project.url = 'http://github.com/%s/' % (project.name)
project.site = 'github'
url = 'https://api.github.com/repos/%s/issues' \
'?labels=%s&state=open' % (project.name, project.tag)
stream = urllib2.urlopen(url)
output = stream.read()
jsonobj = json.loads(output)
if jsonobj:
for ticket in jsonobj:
ticket_num = ticket_num + 1
ticketobj = Ticket()
ticketobj.id = ticket['number']
ticketobj.title = ticket['title']
ticketobj.url = ticket['html_url']
ticketobj.status = ticket['state']
tickets.append(ticketobj)
else:
project.url = 'http://fedorahosted.org/%s/' % (project.name)
project.site = 'trac'
for ticket in get_open_tickets_for_keyword(project.name,
project.tag):
ticket_num = ticket_num + 1
ticketobj = Ticket()
ticketobj.id = ticket[0]
ticketobj.title = ticket[3]['summary']
ticketobj.url = 'http://fedorahosted.org/%s/ticket/%s' %(
project, ticket[0])
ticketobj.status = ticket[3]['status']
ticketobj.type = ticket[3]['type']
ticketobj.component = ticket[3]['component']
tickets.append(ticketobj)
project.tickets = tickets
bzbugs = gather_bugzilla_easyfix()
try:
# Read in template
stream = open(template, 'r')
tplfile = stream.read()
stream.close()
# Fill the template
mytemplate = Template(tplfile)
html = mytemplate.render(projects=projects, bzbugs = bzbugs,
ticket_num=ticket_num, bzbugs_num=len(bzbugs),
date=datetime.datetime.now().strftime("%a %b %d %Y %H:%M"))
# Write down the page
stream = open('index.html', 'w')
stream.write(to_bytes(html))
stream.close()
except IOError, err:
print 'ERROR: %s' % err
if __name__ == '__main__':
main()

9266
roles/easyfix/files/jquery-1.7.1.js vendored Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,304 @@
/*
* jQuery UI CSS Framework 1.8.17
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*
* jQuery UI CSS Framework 1.8.17
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
.ui-widget-content { /*border: 1px solid #aaaaaa;*/ background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
/*.ui-widget-content a { color: #222222; }*/
.ui-widget-header { /*border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;*/ color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*
* jQuery UI Tabs 1.8.17
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Tabs#theming
*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }

314
roles/easyfix/files/jquery.ui.core.js vendored Normal file
View file

@ -0,0 +1,314 @@
/*!
* jQuery UI 1.8.17
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI
*/
(function( $, undefined ) {
// prevent duplicate loading
// this is only a problem because we proxy existing functions
// and we don't want to double proxy them
$.ui = $.ui || {};
if ( $.ui.version ) {
return;
}
$.extend( $.ui, {
version: "1.8.17",
keyCode: {
ALT: 18,
BACKSPACE: 8,
CAPS_LOCK: 20,
COMMA: 188,
COMMAND: 91,
COMMAND_LEFT: 91, // COMMAND
COMMAND_RIGHT: 93,
CONTROL: 17,
DELETE: 46,
DOWN: 40,
END: 35,
ENTER: 13,
ESCAPE: 27,
HOME: 36,
INSERT: 45,
LEFT: 37,
MENU: 93, // COMMAND_RIGHT
NUMPAD_ADD: 107,
NUMPAD_DECIMAL: 110,
NUMPAD_DIVIDE: 111,
NUMPAD_ENTER: 108,
NUMPAD_MULTIPLY: 106,
NUMPAD_SUBTRACT: 109,
PAGE_DOWN: 34,
PAGE_UP: 33,
PERIOD: 190,
RIGHT: 39,
SHIFT: 16,
SPACE: 32,
TAB: 9,
UP: 38,
WINDOWS: 91 // COMMAND
}
});
// plugins
$.fn.extend({
propAttr: $.fn.prop || $.fn.attr,
_focus: $.fn.focus,
focus: function( delay, fn ) {
return typeof delay === "number" ?
this.each(function() {
var elem = this;
setTimeout(function() {
$( elem ).focus();
if ( fn ) {
fn.call( elem );
}
}, delay );
}) :
this._focus.apply( this, arguments );
},
scrollParent: function() {
var scrollParent;
if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
scrollParent = this.parents().filter(function() {
return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0);
} else {
scrollParent = this.parents().filter(function() {
return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
}).eq(0);
}
return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
},
zIndex: function( zIndex ) {
if ( zIndex !== undefined ) {
return this.css( "zIndex", zIndex );
}
if ( this.length ) {
var elem = $( this[ 0 ] ), position, value;
while ( elem.length && elem[ 0 ] !== document ) {
// Ignore z-index if position is set to a value where z-index is ignored by the browser
// This makes behavior of this function consistent across browsers
// WebKit always returns auto if the element is positioned
position = elem.css( "position" );
if ( position === "absolute" || position === "relative" || position === "fixed" ) {
// IE returns 0 when zIndex is not specified
// other browsers return a string
// we ignore the case of nested elements with an explicit value of 0
// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
value = parseInt( elem.css( "zIndex" ), 10 );
if ( !isNaN( value ) && value !== 0 ) {
return value;
}
}
elem = elem.parent();
}
}
return 0;
},
disableSelection: function() {
return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
".ui-disableSelection", function( event ) {
event.preventDefault();
});
},
enableSelection: function() {
return this.unbind( ".ui-disableSelection" );
}
});
$.each( [ "Width", "Height" ], function( i, name ) {
var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
type = name.toLowerCase(),
orig = {
innerWidth: $.fn.innerWidth,
innerHeight: $.fn.innerHeight,
outerWidth: $.fn.outerWidth,
outerHeight: $.fn.outerHeight
};
function reduce( elem, size, border, margin ) {
$.each( side, function() {
size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
if ( border ) {
size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
}
if ( margin ) {
size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
}
});
return size;
}
$.fn[ "inner" + name ] = function( size ) {
if ( size === undefined ) {
return orig[ "inner" + name ].call( this );
}
return this.each(function() {
$( this ).css( type, reduce( this, size ) + "px" );
});
};
$.fn[ "outer" + name] = function( size, margin ) {
if ( typeof size !== "number" ) {
return orig[ "outer" + name ].call( this, size );
}
return this.each(function() {
$( this).css( type, reduce( this, size, true, margin ) + "px" );
});
};
});
// selectors
function focusable( element, isTabIndexNotNaN ) {
var nodeName = element.nodeName.toLowerCase();
if ( "area" === nodeName ) {
var map = element.parentNode,
mapName = map.name,
img;
if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
return false;
}
img = $( "img[usemap=#" + mapName + "]" )[0];
return !!img && visible( img );
}
return ( /input|select|textarea|button|object/.test( nodeName )
? !element.disabled
: "a" == nodeName
? element.href || isTabIndexNotNaN
: isTabIndexNotNaN)
// the element and all of its ancestors must be visible
&& visible( element );
}
function visible( element ) {
return !$( element ).parents().andSelf().filter(function() {
return $.curCSS( this, "visibility" ) === "hidden" ||
$.expr.filters.hidden( this );
}).length;
}
$.extend( $.expr[ ":" ], {
data: function( elem, i, match ) {
return !!$.data( elem, match[ 3 ] );
},
focusable: function( element ) {
return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
},
tabbable: function( element ) {
var tabIndex = $.attr( element, "tabindex" ),
isTabIndexNaN = isNaN( tabIndex );
return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
}
});
// support
$(function() {
var body = document.body,
div = body.appendChild( div = document.createElement( "div" ) );
$.extend( div.style, {
minHeight: "100px",
height: "auto",
padding: 0,
borderWidth: 0
});
$.support.minHeight = div.offsetHeight === 100;
$.support.selectstart = "onselectstart" in div;
// set display to none to avoid a layout bug in IE
// http://dev.jquery.com/ticket/4014
body.removeChild( div ).style.display = "none";
});
// deprecated
$.extend( $.ui, {
// $.ui.plugin is deprecated. Use the proxy pattern instead.
plugin: {
add: function( module, option, set ) {
var proto = $.ui[ module ].prototype;
for ( var i in set ) {
proto.plugins[ i ] = proto.plugins[ i ] || [];
proto.plugins[ i ].push( [ option, set[ i ] ] );
}
},
call: function( instance, name, args ) {
var set = instance.plugins[ name ];
if ( !set || !instance.element[ 0 ].parentNode ) {
return;
}
for ( var i = 0; i < set.length; i++ ) {
if ( instance.options[ set[ i ][ 0 ] ] ) {
set[ i ][ 1 ].apply( instance.element, args );
}
}
}
},
// will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
contains: function( a, b ) {
return document.compareDocumentPosition ?
a.compareDocumentPosition( b ) & 16 :
a !== b && a.contains( b );
},
// only used by resizable
hasScroll: function( el, a ) {
//If overflow is hidden, the element might have extra content, but the user wants to hide it
if ( $( el ).css( "overflow" ) === "hidden") {
return false;
}
var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
has = false;
if ( el[ scroll ] > 0 ) {
return true;
}
// TODO: determine which cases actually cause this to happen
// if the element doesn't have the scroll set, see if it's possible to
// set the scroll
el[ scroll ] = 1;
has = ( el[ scroll ] > 0 );
el[ scroll ] = 0;
return has;
},
// these are odd functions, fix the API or move into individual plugins
isOverAxis: function( x, reference, size ) {
//Determines when x coordinate is over "b" element axis
return ( x > reference ) && ( x < ( reference + size ) );
},
isOver: function( y, x, top, left, height, width ) {
//Determines when x, y coordinates is over "b" element
return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
}
});
})( jQuery );

758
roles/easyfix/files/jquery.ui.tabs.js vendored Normal file
View file

@ -0,0 +1,758 @@
/*
* jQuery UI Tabs 1.8.17
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Tabs
*
* Depends:
* jquery.ui.core.js
* jquery.ui.widget.js
*/
(function( $, undefined ) {
var tabId = 0,
listId = 0;
function getNextTabId() {
return ++tabId;
}
function getNextListId() {
return ++listId;
}
$.widget( "ui.tabs", {
options: {
add: null,
ajaxOptions: null,
cache: false,
cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
collapsible: false,
disable: null,
disabled: [],
enable: null,
event: "click",
fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
idPrefix: "ui-tabs-",
load: null,
panelTemplate: "<div></div>",
remove: null,
select: null,
show: null,
spinner: "<em>Loading&#8230;</em>",
tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
},
_create: function() {
this._tabify( true );
},
_setOption: function( key, value ) {
if ( key == "selected" ) {
if (this.options.collapsible && value == this.options.selected ) {
return;
}
this.select( value );
} else {
this.options[ key ] = value;
this._tabify();
}
},
_tabId: function( a ) {
return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
this.options.idPrefix + getNextTabId();
},
_sanitizeSelector: function( hash ) {
// we need this because an id may contain a ":"
return hash.replace( /:/g, "\\:" );
},
_cookie: function() {
var cookie = this.cookie ||
( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
},
_ui: function( tab, panel ) {
return {
tab: tab,
panel: panel,
index: this.anchors.index( tab )
};
},
_cleanup: function() {
// restore all former loading tabs labels
this.lis.filter( ".ui-state-processing" )
.removeClass( "ui-state-processing" )
.find( "span:data(label.tabs)" )
.each(function() {
var el = $( this );
el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
});
},
_tabify: function( init ) {
var self = this,
o = this.options,
fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
this.list = this.element.find( "ol,ul" ).eq( 0 );
this.lis = $( " > li:has(a[href])", this.list );
this.anchors = this.lis.map(function() {
return $( "a", this )[ 0 ];
});
this.panels = $( [] );
this.anchors.each(function( i, a ) {
var href = $( a ).attr( "href" );
// For dynamically created HTML that contains a hash as href IE < 8 expands
// such href to the full page url with hash and then misinterprets tab as ajax.
// Same consideration applies for an added tab with a fragment identifier
// since a[href=#fragment-identifier] does unexpectedly not match.
// Thus normalize href attribute...
var hrefBase = href.split( "#" )[ 0 ],
baseEl;
if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
href = a.hash;
a.href = href;
}
// inline tab
if ( fragmentId.test( href ) ) {
self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
// remote tab
// prevent loading the page itself if href is just "#"
} else if ( href && href !== "#" ) {
// required for restore on destroy
$.data( a, "href.tabs", href );
// TODO until #3808 is fixed strip fragment identifier from url
// (IE fails to load from such url)
$.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
var id = self._tabId( a );
a.href = "#" + id;
var $panel = self.element.find( "#" + id );
if ( !$panel.length ) {
$panel = $( o.panelTemplate )
.attr( "id", id )
.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
.insertAfter( self.panels[ i - 1 ] || self.list );
$panel.data( "destroy.tabs", true );
}
self.panels = self.panels.add( $panel );
// invalid tab href
} else {
o.disabled.push( i );
}
});
// initialization from scratch
if ( init ) {
// attach necessary classes for styling
this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
this.lis.addClass( "ui-state-default ui-corner-top" );
this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
// Selected tab
// use "selected" option or try to retrieve:
// 1. from fragment identifier in url
// 2. from cookie
// 3. from selected class attribute on <li>
if ( o.selected === undefined ) {
if ( location.hash ) {
this.anchors.each(function( i, a ) {
if ( a.hash == location.hash ) {
o.selected = i;
return false;
}
});
}
if ( typeof o.selected !== "number" && o.cookie ) {
o.selected = parseInt( self._cookie(), 10 );
}
if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
}
o.selected = o.selected || ( this.lis.length ? 0 : -1 );
} else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
o.selected = -1;
}
// sanity check - default to first tab...
o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
? o.selected
: 0;
// Take disabling tabs via class attribute from HTML
// into account and update option properly.
// A selected tab cannot become disabled.
o.disabled = $.unique( o.disabled.concat(
$.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
return self.lis.index( n );
})
) ).sort();
if ( $.inArray( o.selected, o.disabled ) != -1 ) {
o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
}
// highlight selected tab
this.panels.addClass( "ui-tabs-hide" );
this.lis.removeClass( "ui-tabs-selected ui-state-active" );
// check for length avoids error when initializing empty list
if ( o.selected >= 0 && this.anchors.length ) {
self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
// seems to be expected behavior that the show callback is fired
self.element.queue( "tabs", function() {
self._trigger( "show", null,
self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
});
this.load( o.selected );
}
// clean up to avoid memory leaks in certain versions of IE 6
// TODO: namespace this event
$( window ).bind( "unload", function() {
self.lis.add( self.anchors ).unbind( ".tabs" );
self.lis = self.anchors = self.panels = null;
});
// update selected after add/remove
} else {
o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
}
// update collapsible
// TODO: use .toggleClass()
this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
// set or update cookie after init and add/remove respectively
if ( o.cookie ) {
this._cookie( o.selected, o.cookie );
}
// disable tabs
for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
$( li )[ $.inArray( i, o.disabled ) != -1 &&
// TODO: use .toggleClass()
!$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
}
// reset cache if switching from cached to not cached
if ( o.cache === false ) {
this.anchors.removeData( "cache.tabs" );
}
// remove all handlers before, tabify may run on existing tabs after add or option change
this.lis.add( this.anchors ).unbind( ".tabs" );
if ( o.event !== "mouseover" ) {
var addState = function( state, el ) {
if ( el.is( ":not(.ui-state-disabled)" ) ) {
el.addClass( "ui-state-" + state );
}
};
var removeState = function( state, el ) {
el.removeClass( "ui-state-" + state );
};
this.lis.bind( "mouseover.tabs" , function() {
addState( "hover", $( this ) );
});
this.lis.bind( "mouseout.tabs", function() {
removeState( "hover", $( this ) );
});
this.anchors.bind( "focus.tabs", function() {
addState( "focus", $( this ).closest( "li" ) );
});
this.anchors.bind( "blur.tabs", function() {
removeState( "focus", $( this ).closest( "li" ) );
});
}
// set up animations
var hideFx, showFx;
if ( o.fx ) {
if ( $.isArray( o.fx ) ) {
hideFx = o.fx[ 0 ];
showFx = o.fx[ 1 ];
} else {
hideFx = showFx = o.fx;
}
}
// Reset certain styles left over from animation
// and prevent IE's ClearType bug...
function resetStyle( $el, fx ) {
$el.css( "display", "" );
if ( !$.support.opacity && fx.opacity ) {
$el[ 0 ].style.removeAttribute( "filter" );
}
}
// Show a tab...
var showTab = showFx
? function( clicked, $show ) {
$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
$show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
.animate( showFx, showFx.duration || "normal", function() {
resetStyle( $show, showFx );
self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
});
}
: function( clicked, $show ) {
$( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
$show.removeClass( "ui-tabs-hide" );
self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
};
// Hide a tab, $show is optional...
var hideTab = hideFx
? function( clicked, $hide ) {
$hide.animate( hideFx, hideFx.duration || "normal", function() {
self.lis.removeClass( "ui-tabs-selected ui-state-active" );
$hide.addClass( "ui-tabs-hide" );
resetStyle( $hide, hideFx );
self.element.dequeue( "tabs" );
});
}
: function( clicked, $hide, $show ) {
self.lis.removeClass( "ui-tabs-selected ui-state-active" );
$hide.addClass( "ui-tabs-hide" );
self.element.dequeue( "tabs" );
};
// attach tab event handler, unbind to avoid duplicates from former tabifying...
this.anchors.bind( o.event + ".tabs", function() {
var el = this,
$li = $(el).closest( "li" ),
$hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
$show = self.element.find( self._sanitizeSelector( el.hash ) );
// If tab is already selected and not collapsible or tab disabled or
// or is already loading or click callback returns false stop here.
// Check if click handler returns false last so that it is not executed
// for a disabled or loading tab!
if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
$li.hasClass( "ui-state-disabled" ) ||
$li.hasClass( "ui-state-processing" ) ||
self.panels.filter( ":animated" ).length ||
self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
this.blur();
return false;
}
o.selected = self.anchors.index( this );
self.abort();
// if tab may be closed
if ( o.collapsible ) {
if ( $li.hasClass( "ui-tabs-selected" ) ) {
o.selected = -1;
if ( o.cookie ) {
self._cookie( o.selected, o.cookie );
}
self.element.queue( "tabs", function() {
hideTab( el, $hide );
}).dequeue( "tabs" );
this.blur();
return false;
} else if ( !$hide.length ) {
if ( o.cookie ) {
self._cookie( o.selected, o.cookie );
}
self.element.queue( "tabs", function() {
showTab( el, $show );
});
// TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
self.load( self.anchors.index( this ) );
this.blur();
return false;
}
}
if ( o.cookie ) {
self._cookie( o.selected, o.cookie );
}
// show new tab
if ( $show.length ) {
if ( $hide.length ) {
self.element.queue( "tabs", function() {
hideTab( el, $hide );
});
}
self.element.queue( "tabs", function() {
showTab( el, $show );
});
self.load( self.anchors.index( this ) );
} else {
throw "jQuery UI Tabs: Mismatching fragment identifier.";
}
// Prevent IE from keeping other link focussed when using the back button
// and remove dotted border from clicked link. This is controlled via CSS
// in modern browsers; blur() removes focus from address bar in Firefox
// which can become a usability and annoying problem with tabs('rotate').
if ( $.browser.msie ) {
this.blur();
}
});
// disable click in any case
this.anchors.bind( "click.tabs", function(){
return false;
});
},
_getIndex: function( index ) {
// meta-function to give users option to provide a href string instead of a numerical index.
// also sanitizes numerical indexes to valid values.
if ( typeof index == "string" ) {
index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
}
return index;
},
destroy: function() {
var o = this.options;
this.abort();
this.element
.unbind( ".tabs" )
.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
.removeData( "tabs" );
this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
this.anchors.each(function() {
var href = $.data( this, "href.tabs" );
if ( href ) {
this.href = href;
}
var $this = $( this ).unbind( ".tabs" );
$.each( [ "href", "load", "cache" ], function( i, prefix ) {
$this.removeData( prefix + ".tabs" );
});
});
this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
if ( $.data( this, "destroy.tabs" ) ) {
$( this ).remove();
} else {
$( this ).removeClass([
"ui-state-default",
"ui-corner-top",
"ui-tabs-selected",
"ui-state-active",
"ui-state-hover",
"ui-state-focus",
"ui-state-disabled",
"ui-tabs-panel",
"ui-widget-content",
"ui-corner-bottom",
"ui-tabs-hide"
].join( " " ) );
}
});
if ( o.cookie ) {
this._cookie( null, o.cookie );
}
return this;
},
add: function( url, label, index ) {
if ( index === undefined ) {
index = this.anchors.length;
}
var self = this,
o = this.options,
$li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
$li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
// try to find an existing element before creating a new one
var $panel = self.element.find( "#" + id );
if ( !$panel.length ) {
$panel = $( o.panelTemplate )
.attr( "id", id )
.data( "destroy.tabs", true );
}
$panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
if ( index >= this.lis.length ) {
$li.appendTo( this.list );
$panel.appendTo( this.list[ 0 ].parentNode );
} else {
$li.insertBefore( this.lis[ index ] );
$panel.insertBefore( this.panels[ index ] );
}
o.disabled = $.map( o.disabled, function( n, i ) {
return n >= index ? ++n : n;
});
this._tabify();
if ( this.anchors.length == 1 ) {
o.selected = 0;
$li.addClass( "ui-tabs-selected ui-state-active" );
$panel.removeClass( "ui-tabs-hide" );
this.element.queue( "tabs", function() {
self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
});
this.load( 0 );
}
this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
return this;
},
remove: function( index ) {
index = this._getIndex( index );
var o = this.options,
$li = this.lis.eq( index ).remove(),
$panel = this.panels.eq( index ).remove();
// If selected tab was removed focus tab to the right or
// in case the last tab was removed the tab to the left.
if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
}
o.disabled = $.map(
$.grep( o.disabled, function(n, i) {
return n != index;
}),
function( n, i ) {
return n >= index ? --n : n;
});
this._tabify();
this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
return this;
},
enable: function( index ) {
index = this._getIndex( index );
var o = this.options;
if ( $.inArray( index, o.disabled ) == -1 ) {
return;
}
this.lis.eq( index ).removeClass( "ui-state-disabled" );
o.disabled = $.grep( o.disabled, function( n, i ) {
return n != index;
});
this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
return this;
},
disable: function( index ) {
index = this._getIndex( index );
var self = this, o = this.options;
// cannot disable already selected tab
if ( index != o.selected ) {
this.lis.eq( index ).addClass( "ui-state-disabled" );
o.disabled.push( index );
o.disabled.sort();
this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
}
return this;
},
select: function( index ) {
index = this._getIndex( index );
if ( index == -1 ) {
if ( this.options.collapsible && this.options.selected != -1 ) {
index = this.options.selected;
} else {
return this;
}
}
this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
return this;
},
load: function( index ) {
index = this._getIndex( index );
var self = this,
o = this.options,
a = this.anchors.eq( index )[ 0 ],
url = $.data( a, "load.tabs" );
this.abort();
// not remote or from cache
if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
this.element.dequeue( "tabs" );
return;
}
// load remote from here on
this.lis.eq( index ).addClass( "ui-state-processing" );
if ( o.spinner ) {
var span = $( "span", a );
span.data( "label.tabs", span.html() ).html( o.spinner );
}
this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
url: url,
success: function( r, s ) {
self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
// take care of tab labels
self._cleanup();
if ( o.cache ) {
$.data( a, "cache.tabs", true );
}
self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
try {
o.ajaxOptions.success( r, s );
}
catch ( e ) {}
},
error: function( xhr, s, e ) {
// take care of tab labels
self._cleanup();
self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
try {
// Passing index avoid a race condition when this method is
// called after the user has selected another tab.
// Pass the anchor that initiated this request allows
// loadError to manipulate the tab content panel via $(a.hash)
o.ajaxOptions.error( xhr, s, index, a );
}
catch ( e ) {}
}
} ) );
// last, so that load event is fired before show...
self.element.dequeue( "tabs" );
return this;
},
abort: function() {
// stop possibly running animations
this.element.queue( [] );
this.panels.stop( false, true );
// "tabs" queue must not contain more than two elements,
// which are the callbacks for the latest clicked tab...
this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
// terminate pending requests from other tabs
if ( this.xhr ) {
this.xhr.abort();
delete this.xhr;
}
// take care of tab labels
this._cleanup();
return this;
},
url: function( index, url ) {
this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
return this;
},
length: function() {
return this.anchors.length;
}
});
$.extend( $.ui.tabs, {
version: "1.8.17"
});
/*
* Tabs Extensions
*/
/*
* Rotate
*/
$.extend( $.ui.tabs.prototype, {
rotation: null,
rotate: function( ms, continuing ) {
var self = this,
o = this.options;
var rotate = self._rotate || ( self._rotate = function( e ) {
clearTimeout( self.rotation );
self.rotation = setTimeout(function() {
var t = o.selected;
self.select( ++t < self.anchors.length ? t : 0 );
}, ms );
if ( e ) {
e.stopPropagation();
}
});
var stop = self._unrotate || ( self._unrotate = !continuing
? function(e) {
if (e.clientX) { // in case of a true click
self.rotate(null);
}
}
: function( e ) {
t = o.selected;
rotate();
});
// start rotation
if ( ms ) {
this.element.bind( "tabsshow", rotate );
this.anchors.bind( o.event + ".tabs", stop );
rotate();
// stop rotation
} else {
clearTimeout( self.rotation );
this.element.unbind( "tabsshow", rotate );
this.anchors.unbind( o.event + ".tabs", stop );
delete this._rotate;
delete this._unrotate;
}
return this;
}
});
})( jQuery );

272
roles/easyfix/files/jquery.ui.widget.js vendored Normal file
View file

@ -0,0 +1,272 @@
/*!
* jQuery UI Widget 1.8.17
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Widget
*/
(function( $, undefined ) {
// jQuery 1.4+
if ( $.cleanData ) {
var _cleanData = $.cleanData;
$.cleanData = function( elems ) {
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
try {
$( elem ).triggerHandler( "remove" );
// http://bugs.jquery.com/ticket/8235
} catch( e ) {}
}
_cleanData( elems );
};
} else {
var _remove = $.fn.remove;
$.fn.remove = function( selector, keepData ) {
return this.each(function() {
if ( !keepData ) {
if ( !selector || $.filter( selector, [ this ] ).length ) {
$( "*", this ).add( [ this ] ).each(function() {
try {
$( this ).triggerHandler( "remove" );
// http://bugs.jquery.com/ticket/8235
} catch( e ) {}
});
}
}
return _remove.call( $(this), selector, keepData );
});
};
}
$.widget = function( name, base, prototype ) {
var namespace = name.split( "." )[ 0 ],
fullName;
name = name.split( "." )[ 1 ];
fullName = namespace + "-" + name;
if ( !prototype ) {
prototype = base;
base = $.Widget;
}
// create selector for plugin
$.expr[ ":" ][ fullName ] = function( elem ) {
return !!$.data( elem, name );
};
$[ namespace ] = $[ namespace ] || {};
$[ namespace ][ name ] = function( options, element ) {
// allow instantiation without initializing for simple inheritance
if ( arguments.length ) {
this._createWidget( options, element );
}
};
var basePrototype = new base();
// we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're
// inheriting from
// $.each( basePrototype, function( key, val ) {
// if ( $.isPlainObject(val) ) {
// basePrototype[ key ] = $.extend( {}, val );
// }
// });
basePrototype.options = $.extend( true, {}, basePrototype.options );
$[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
namespace: namespace,
widgetName: name,
widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
widgetBaseClass: fullName
}, prototype );
$.widget.bridge( name, $[ namespace ][ name ] );
};
$.widget.bridge = function( name, object ) {
$.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string",
args = Array.prototype.slice.call( arguments, 1 ),
returnValue = this;
// allow multiple hashes to be passed on init
options = !isMethodCall && args.length ?
$.extend.apply( null, [ true, options ].concat(args) ) :
options;
// prevent calls to internal methods
if ( isMethodCall && options.charAt( 0 ) === "_" ) {
return returnValue;
}
if ( isMethodCall ) {
this.each(function() {
var instance = $.data( this, name ),
methodValue = instance && $.isFunction( instance[options] ) ?
instance[ options ].apply( instance, args ) :
instance;
// TODO: add this back in 1.9 and use $.error() (see #5972)
// if ( !instance ) {
// throw "cannot call methods on " + name + " prior to initialization; " +
// "attempted to call method '" + options + "'";
// }
// if ( !$.isFunction( instance[options] ) ) {
// throw "no such method '" + options + "' for " + name + " widget instance";
// }
// var methodValue = instance[ options ].apply( instance, args );
if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue;
return false;
}
});
} else {
this.each(function() {
var instance = $.data( this, name );
if ( instance ) {
instance.option( options || {} )._init();
} else {
$.data( this, name, new object( options, this ) );
}
});
}
return returnValue;
};
};
$.Widget = function( options, element ) {
// allow instantiation without initializing for simple inheritance
if ( arguments.length ) {
this._createWidget( options, element );
}
};
$.Widget.prototype = {
widgetName: "widget",
widgetEventPrefix: "",
options: {
disabled: false
},
_createWidget: function( options, element ) {
// $.widget.bridge stores the plugin instance, but we do it anyway
// so that it's stored even before the _create function runs
$.data( element, this.widgetName, this );
this.element = $( element );
this.options = $.extend( true, {},
this.options,
this._getCreateOptions(),
options );
var self = this;
this.element.bind( "remove." + this.widgetName, function() {
self.destroy();
});
this._create();
this._trigger( "create" );
this._init();
},
_getCreateOptions: function() {
return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
},
_create: function() {},
_init: function() {},
destroy: function() {
this.element
.unbind( "." + this.widgetName )
.removeData( this.widgetName );
this.widget()
.unbind( "." + this.widgetName )
.removeAttr( "aria-disabled" )
.removeClass(
this.widgetBaseClass + "-disabled " +
"ui-state-disabled" );
},
widget: function() {
return this.element;
},
option: function( key, value ) {
var options = key;
if ( arguments.length === 0 ) {
// don't return a reference to the internal hash
return $.extend( {}, this.options );
}
if (typeof key === "string" ) {
if ( value === undefined ) {
return this.options[ key ];
}
options = {};
options[ key ] = value;
}
this._setOptions( options );
return this;
},
_setOptions: function( options ) {
var self = this;
$.each( options, function( key, value ) {
self._setOption( key, value );
});
return this;
},
_setOption: function( key, value ) {
this.options[ key ] = value;
if ( key === "disabled" ) {
this.widget()
[ value ? "addClass" : "removeClass"](
this.widgetBaseClass + "-disabled" + " " +
"ui-state-disabled" )
.attr( "aria-disabled", value );
}
return this;
},
enable: function() {
return this._setOption( "disabled", false );
},
disable: function() {
return this._setOption( "disabled", true );
},
_trigger: function( type, event, data ) {
var prop, orig,
callback = this.options[ type ];
data = data || {};
event = $.Event( event );
event.type = ( type === this.widgetEventPrefix ?
type :
this.widgetEventPrefix + type ).toLowerCase();
// the original event may come from any element
// so we need to reset the target on the new event
event.target = this.element[ 0 ];
// copy original event properties over to the new event
orig = event.originalEvent;
if ( orig ) {
for ( prop in orig ) {
if ( !( prop in event ) ) {
event[ prop ] = orig[ prop ];
}
}
}
this.element.trigger( event, data );
return !( $.isFunction(callback) &&
callback.call( this.element[0], event, data ) === false ||
event.isDefaultPrevented() );
}
};
})( jQuery );

View file

@ -0,0 +1,262 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" type="text/css" href="https://fedoraproject.org/static/css/reset.css" media="screen" />
<link rel="stylesheet" type="text/css" href="https://fedoraproject.org/static/css/text.css" media="screen" />
<link rel="stylesheet" type="text/css" href="https://fedoraproject.org/static/css/960.css" media="screen" />
<link rel="stylesheet" type="text/css" href="https://fedoraproject.org/static/css/fedora960.css" media="screen" />
<link rel="stylesheet" type="text/css" href="https://fedoraproject.org/static/css/fedora960-lang.css" media="screen" />
<!-- legacy -->
<link rel="shortcut icon" href="https://fedoraproject.org/static/images/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="stylesheet" type="text/css" media="print" href="https://fedoraproject.org/static/css/print.css" />
<!--[if IE 7]>
<link rel="stylesheet" type="text/css" href="https://fedoraproject.org/static/css/ie7.css" media="screen">
<style type="text/css">
#wrapper
{
height: 100%;
overflow: visible!important;
}
.downloadsidebar a {
backgroundimage: none!important;
}
</style>
<![endif]-->
<link rel="stylesheet" type="text/css" href="jquery-ui-1.8.17.custom.css" />
<script type="text/javascript" src="jquery-1.7.1.min.js" ></script>
<script type="text/javascript" src="jquery.ui.widget.js" ></script>
<script type="text/javascript" src="jquery.ui.tabs.js" ></script>
<script type="text/javascript">
$(function() {
$( "#tabs" ).tabs();
});
</script>
<title>Fedora Project easyfix</title>
</head>
<body id="fedoraproject-org" class="lang-en">
<!-- header -->
<div id="header">
<div class="container_16">
<div class="grid_6 prefix_10">
</div>
<div class="clear"></div>
<div class="grid_9" id="site-heading">
<h1><a href="/"><span id="logo">Fedora Project</span></a></h1>
<h2>Freedom. Friends. Features. First.</h2>
</div>
<div class="grid_1"> <!-- search filler --></div>
<div class="grid_6" id="site-heading-rh">
<a href="http://redhat.com">A Red Hat-Sponsored Community Project
<img id="rh-community" src="https://fedoraproject.org/static/images/sponsors/redhat-community.png"
alt="Red Hat Logo" /></a>
</div>
<div class="clear"></div>
</div>
</div>
<div id="main-nav">
<div class="container_16">
<ul id="nav-menu">
<li><a href="/en/">Home</a></li>
<li><a href="/en/features/">Features &amp; Screenshots</a></li>
<li><a href="/en/get-fedora">Download</a></li>
<li><a href="/en/join-fedora">Community</a></li>
<li><a href="/en/using/">Using Fedora</a></li>
<li><a href="/en/get-help">Help</a></li>
<li><a href="/wiki" id="nav-special">Contributors</a></li>
</ul>
</div>
</div>
<!-- /header -->
<!-- site-content -->
<div id="site-content">
<div class="container_16">
<div class="grid_16">
</div>
</div>
<div class="clear">
</div>
<div class="container_16">
<div class="grid_12 alpha">
<div id="web-quotes">
<p> There are a number of projects within Fedora which are looking
for help. Below are listed tasks which have been evaluated as easy
entrance point for people who are looking to start contributing and
do not know where to start.
</p>
<p>
If you are a project owner, see the <a href="https://fedoraproject.org/wiki/Easyfix">
wiki</a> for more information.
</p>
</div>
<div id="tabs">
<ul>
<li><a href="#tabs-1">Fedora hosted projects</a></li>
<li><a href="#tabs-2">Bugzilla</a></li>
</ul>
<div class="clear"></div>
<div id="tabs-1">
{% for project in projects %}
{% if project.tickets %}
<div class="main-page-section">
<h2><a name="{{ project.name }}">{{ project.name }}</a></h2>
<p>
To get started contact <a
href="mailto:{{ project.owner }}@fedoraproject.org">
{{ project.owner }}</a>
</p>
{% for ticket in project.tickets%}
<p>
<a href="{{ ticket.url }}"> #{{ ticket.id }}</a>
{{ ticket.title }} <br />
Status : {{ ticket.status }} - Type : {{ ticket.type }} -
Component : {{ ticket.component }}
</p>
{% endfor %}
</div>
{% endif %}
{% endfor %}
<p> Total: {{ticket_num}} tickets found </p>
</div>
<div id="tabs-2">
<ul>
{% for bug in bzbugs | sort %}
<li>
<a href="http://bugzilla.redhat.com/{{bug.bug_id}}">#{{bug.bug_id}}</a>
(<a href="https://apps.fedoraproject.org/packages/{{bug.component}}">
{{bug.component}}</a>) - {{bug.short_desc}} <br />
{% if '@' in bug.assigned_to %}
Contact: <a href="mailto:{{bug.assigned_to}}">{{bug.assigned_to.split('@')[0]}}</a>
{% else %}
Contact: {{bug.assigned_to}}
{% endif %}
</li>
{% endfor %}
</ul>
<p> Total: {{bzbugs_num}} bugs found </p>
</div>
</div>
<div class="clear"></div>
</div>
<!-- start sidebar -->
<div class="grid_4 omega" id="left-sidebar">
<h4>Project list </h4>
<ul class="checkmark-list">
{% for project in projects %}
<li>
<a href="#{{ project.name }}">{{ project.name }}</a>
(<a href="{{ project.url }}" target="_blank">{{ project.site }}</a>)
</li>
{% endfor %}
</ul>
</div>
<!-- /start sidebar -->
<div class="clear"></div>
<p>Last update: {{date}}</p>
</div>
</div>
<div id="bottom">
<div class="container_12">
<div class="grid_2 sitelinks">
<dl>
<dt>Fedora</dt>
<dd><a href="https://fedoraproject.org/en/about-fedora">About Fedora</a></dd>
<dd><a href="http://planet.fedoraproject.org/">Planet Fedora</a></dd>
<dd><a href="https://fedoraproject.org/wiki/FWN/LatestIssue">Fedora Weekly News</a></dd>
<dd><a href="http://docs.fedoraproject.org/">Documentation</a></dd>
<dd><a href="https://fedoraproject.org/wiki/">Fedora Wiki</a></dd>
<dd><a href="https://fedoraproject.org/wiki/FedoraEvents">Events</a></dd>
</dl>
</div>
<div class="grid_2 sitelinks">
<dl>
<dt>Download</dt>
<dd><a href="https://fedoraproject.org/en/get-fedora">Get Fedora</a></dd>
<dd><a href="https://fedoraproject.org/en/get-fedora-options">Full Download List</a></dd>
</dl>
</div>
<div class="grid_2 sitelinks">
<dl>
<dt>Support</dt>
<dd><a href="https://fedoraproject.org/en/get-help">Get Help</a></dd>
<dd><a href="irc://irc.freenode.org/#fedora">IRC Help</a></dd>
<dd><a href="https://admin.fedoraproject.org/mailman/listinfo/users">Mailing List Help</a></dd>
<dd><a href="http://www.fedoraforum.org/">Forums</a></dd>
<dd><a href="http://docs.fedoraproject.org/">Documentation</a></dd>
</dl>
</div>
<div class="grid_2 sitelinks">
<dl>
<dt>Join</dt>
<dd><a href="https://fedoraproject.org/en/join-fedora">Join Fedora</a></dd>
<dd><a href="https://fedoraproject.org/wiki/SIGs">Fedora SIGs</a></dd>
<dd><a href="https://admin.fedoraproject.org/accounts/">Fedora Account System</a></dd>
<dd><a href="https://admin.fedoraproject.org/community/">Fedora Community</a></dd>
</dl>
</div>
<div class="grid_2 sitelinks">
<dl>
<dt>Subprojects</dt>
<dd><a href="https://fedoraproject.org/wiki/DocsProject">Documentation</a></dd>
<dd><a href="https://fedoraproject.org/wiki/L10N">Translation</a></dd>
<dd><a href="https://fedoraproject.org/wiki/Marketing">Marketing</a></dd>
<dd><a href="https://fedoraproject.org/wiki/Ambassadors">Ambassadors</a></dd>
<dd><a href="https://fedoraproject.org/wiki/Design">Design</a></dd>
<dd><a href="https://fedoraproject.org/wiki/Infrastructure">Infrastructure</a></dd>
</dl>
</div>
<div class="grid_2 sitelinks">
<dl>
<dt> </dt>
<dd><a href="https://fedoraproject.org/wiki/Websites">Websites</a></dd>
<dd><a href="https://fedoraproject.org/wiki/I18N">Internationalization</a></dd>
<dd><a href="https://fedoraproject.org/wiki/NewsProject">News</a></dd>
<dd><a href="https://fedoraproject.org/wiki/Distribution/Project">Distribution</a></dd>
<dd><a href="https://fedoraproject.org/wiki/SIGs">Special Interest Groups (SIGs)</a></dd>
</dl>
</div>
<div class="clear"></div>
<div id="footer" class="grid_12">
<a href="http://www.redhat.com/"><img class="rh-logo"
src="https://fedoraproject.org/static/images/sponsors/sidebar/redhat.png" alt="Red Hat Logo" /></a>
<p class="sponsor">Fedora is sponsored by Red Hat.</p>
<p class="sponsor"><a href="http://www.redhat.com/rhel/fedora/">Learn more about the relationship between Red Hat and Fedora &gt;</a></p>
<p class="copy">(C) 2011 Red Hat, Inc. and others.</p>
<ul>
<li class="first"><a href="/en/contact">Contact</a></li>
<li><a href="https://fedoraproject.org/sponsors">Sponsors</a></li>
<li><a href="https://fedoraproject.org/wiki/Legal:Main">Legal</a></li>
<li class="last"><a href="https://fedoraproject.org/wiki/Legal:Trademark_guidelines">Trademark Guidelines</a></li>
</ul>
<p class="disclaimer">The Fedora Project is maintained and driven by the community. This is a community maintained site. Red Hat is not responsible for content.</p>
</div>
<div class="clear"> </div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,61 @@
---
# Configuration for the easyfix web page
## Create all the folder used/needed
- name: Create the easyfix folder
action: file state=directory
path=/srv/web/easyfix
owner=root group=root mode=0755
- name: Create the easyfix configuration folder
action: file state=directory
path=/etc/fedora-gather-easyfix/
owner=root group=root mode=0755
## Install packages
- name: Install needed packages
yum: pkg={{ item }} state=installed
with_items:
- python-fedora
- python-jinja2
- python-kitchen
tags:
- packages
## Install all files
- name: Install the easyfix js/css files
copy: >
src={{ item }} dest=/srv/web/easyfix/{{ item }}
owner=root group=root mode=0644
with_items:
- jquery-1.7.1.min.js
- jquery-ui-1.8.17.custom.css
- jquery.ui.tabs.js
- jquery.ui.widget.js
tags:
- files
- name: Install the easyfix template
copy: >
src=template.html dest=/etc/fedora-gather-easyfix/template.html
owner=root group=root mode=0644
tags:
- files
- name: Install the easyfix script
copy: >
src=gather_easyfix.py dest=/usr/local/bin/gather_easyfix.py
owner=root group=root mode=0755
tags:
- files
## Install the cron job
- name: Install the easyfix cronjob
copy: >
src=easyfix.cron dest=/etc/cron.d/easyfix.cron
owner=root group=root mode=0755
tags:
- files

View file

@ -0,0 +1 @@
0 10 * * 3 root /usr/bin/python /usr/local/bin/fedora-owner-change.py

View file

@ -0,0 +1,344 @@
#!/usr/bin/python -tt
#-*- coding: utf-8 -*-
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
"""
This program checks and reports the packages owner change in pkgdb using
its messages catched by datanommer and available via datagrepper.
Dependencies:
* python-requests
* python-argparse
"""
import argparse
import json
import logging
import requests
import smtplib
import sys
from email.mime.text import MIMEText
DATAGREPPER_URL = 'https://apps.fedoraproject.org/datagrepper/raw/'
DELTA = 7 * 24 * 60 * 60 # 7 days
TOPIC = 'org.fedoraproject.prod.pkgdb.owner.update'
EMAIL_TO = 'pingou@pingoured.fr'
EMAIL_FROM = 'nobody@fedoraproject.org'
SMTP_SERVER = 'localhost'
# Initial simple logging stuff
logging.basicConfig()
LOG = logging.getLogger("owner-change")
def send_report(report):
""" This function sends the actual report.
:arg report: the content to send by email
"""
report = report.encode('utf-8', 'replace')
msg = MIMEText(report)
msg['Subject'] = '[Owner-change] Fedora packages ownership change'
msg['From'] = EMAIL_FROM
msg['To'] = EMAIL_TO
# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP(SMTP_SERVER)
s.sendmail(EMAIL_FROM,
EMAIL_TO,
msg.as_string())
s.quit()
def retrieve_pkgdb_change():
""" Query datagrepper to retrieve the list of change in ownership
on packages of pkgdb over the DELTA period of time.
"""
messages = []
page = 1
pages = 2
while page <= pages:
LOG.debug('Retrieving page %s of %s' % (page, pages))
data = {'delta': DELTA,
'topic': [
'org.fedoraproject.prod.pkgdb.owner.update',
'org.fedoraproject.prod.pkgdb.package.retire',
],
'rows_per_page': 100,
'page': page,
'order': 'asc',
}
output = requests.get(DATAGREPPER_URL, params=data)
json_output = json.loads(output.text)
pages = json_output['pages']
page += 1
messages.extend(json_output['raw_messages'])
LOG.debug('Should have retrieved %s' % json_output['total'])
return messages
def setup_parser():
"""
Set the command line arguments.
"""
parser = argparse.ArgumentParser(
prog="fedora-owner-change")
parser.add_argument(
'--nomail', action='store_true',
help="Prints the report instead of sending it by email")
parser.add_argument(
'--debug', action='store_true',
help="Outputs debugging info")
return parser
def __format_dict(dic):
keys = dic.keys()
pkgs = [it[0] for it in keys]
tmp = {}
for pkg in pkgs:
lcl_keys = [key for key in keys if pkg in key]
for key in lcl_keys:
lcl = json.dumps(dic[key])
if lcl in tmp:
tmp[lcl].append(key)
else:
tmp[lcl] = [key]
output = {}
for key in tmp:
pkg_name = tmp[key][0][0]
branches = set([val[1] for val in tmp[key]])
data = json.loads(key)
data['pkg_name'] = pkg_name
data['branches'] = ','.join(sorted(branches, key=unicode.lower))
output[pkg_name] = data
return output
def get_category(message):
""" For a given message specify if it has been orphaned, retired,
unorphaned, unretired, given or changed.
"""
output = None
if 'retirement' in message \
and message['retirement'] == 'retired':
output = 'retired'
elif 'retirement' in message \
and message['retirement'] == 'unretired':
output = 'unretired'
elif 'previous_owner' in message \
and message['package_listing']['owner'] == 'orphan':
output = 'orphaned'
elif 'previous_owner' in message \
and message['package_listing']['owner'] != 'orphan' \
and message['previous_owner'] == 'orphan':
output = 'unorphaned'
elif 'previous_owner' in message \
and message['package_listing']['owner'] == message['previous_owner'] \
and message['previous_owner'] != 'orphan':
output = 'new'
elif 'previous_owner' in message \
and message['package_listing']['owner'] != message['previous_owner'] \
and message['previous_owner'] != 'orphan':
output = 'given'
else:
LOG.info('Could not parse message %s', message)
return output
def main():
""" Retrieve all the change in ownership from pkgdb via datagrepper
and report the changes either as packages have been orphaned or
packages changed owner.
"""
parser = setup_parser()
args = parser.parse_args()
global LOG
if args.debug:
LOG.setLevel(logging.DEBUG)
changes = retrieve_pkgdb_change()
LOG.debug('%s changes retrieved' % len(changes))
packages = {}
for change in changes:
pkg_name = change['msg']['package_listing']['package']['name']
owner = change['msg']['package_listing']['owner']
branch = change['msg']['package_listing']['collection']['branchname']
user = change['msg']['agent']
LOG.debug('"%s" changed to %s by %s on %s - topic: %s' % (
pkg_name, owner, user, branch, change['topic']))
key = (pkg_name, branch)
if key not in packages:
packages[key] = {}
packages[key]['action'] = get_category(change['msg'])
packages[key]['msg'] = change['msg']
actions = {}
for act in ['orphaned', 'unorphaned', 'retired', 'unretired', 'given',
'new']:
actions[act] = {}
for package in sorted(packages) :
action = packages[package]['action']
if package[0] not in actions[action]:
actions[action][package[0]] = {}
actions[action][package[0]][package[1]] = packages[package]
hours = int(DELTA) / 3600
report = 'Change in package status over the last %s hours\n' % hours
report += '=' * (45 + len(str(hours))) + '\n'
report += '\n%s packages were orphaned\n' % len(actions['orphaned'])
report += '-' * (len(str(len(actions['orphaned']))) + 23) + '\n'
for pkg in sorted(actions['orphaned']):
branches = [item for item in actions['orphaned'][pkg]]
agents = set([
actions['orphaned'][pkg][item]['msg']['agent']
for item in actions['orphaned'][pkg]])
value = u'%s [%s] was orphaned by %s' % (
pkg,
', '.join(branches),
', '.join(agents)
)
report += value + '\n'
report += ' ' * 5 + actions['orphaned'][pkg][branches[0]]['msg'][
'package_listing']['package']['summary'] + '\n'
report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\
'acls/name/%s\n' % pkg
report += '\n%s packages unorphaned\n' % len(actions['unorphaned'])
report += '-' * (len(str(len(actions['unorphaned']))) + 20) + '\n'
for pkg in sorted(actions['unorphaned']):
branches = [item for item in actions['unorphaned'][pkg]]
agents = set([
actions['unorphaned'][pkg][item]['msg']['agent']
for item in actions['unorphaned'][pkg]])
value = u'%s [%s] was unorphaned by %s' % (
pkg,
', '.join(branches),
', '.join(agents)
)
report += value + '\n'
report += ' ' * 5 + actions['unorphaned'][pkg][branches[0]]['msg'][
'package_listing']['package']['summary'] + '\n'
report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\
'acls/name/%s\n' % pkg
report += '\n%s packages were retired\n' % len(actions['retired'])
report += '-' * (len(str(len(actions['retired']))) + 23) + '\n'
for pkg in sorted(actions['retired']):
branches = [item for item in actions['retired'][pkg]]
agents = set([
actions['retired'][pkg][item]['msg']['agent']
for item in actions['retired'][pkg]])
value = u'%s [%s] was retired by %s' % (
pkg,
', '.join(branches),
', '.join(agents)
)
report += value + '\n'
report += ' ' * 5 + actions['retired'][pkg][branches[0]]['msg'][
'package_listing']['package']['summary'] + '\n'
report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\
'acls/name/%s\n' % pkg
report += '\n%s packages were unretired\n' % len(actions['unretired'])
report += '-' * (len(str(len(actions['unretired']))) + 23) + '\n'
for pkg in sorted(actions['unretired']):
branches = [item for item in actions['unretired'][pkg]]
agents = set([
actions['unretired'][pkg][item]['msg']['agent']
for item in actions['unretired'][pkg]])
value = u'%s [%s] was unretired by %s' % (
pkg,
', '.join(branches),
', '.join(agents)
)
report += value + '\n'
report += ' ' * 5 + actions['unretired'][pkg][branches[0]]['msg'][
'package_listing']['package']['summary'] + '\n'
report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\
'acls/name/%s\n' % pkg
report += '\n%s packages were given\n' % len(actions['given'])
report += '-' * (len(str(len(actions['given']))) + 23) + '\n'
for pkg in sorted(actions['given']):
branches = [item for item in actions['given'][pkg]]
agents = set([
actions['given'][pkg][item]['msg']['agent']
for item in actions['given'][pkg]])
owners = set([
actions['given'][pkg][item]['msg']['package_listing']['owner']
for item in actions['given'][pkg]])
value = u'%s [%s] was given by %s to %s' % (
pkg,
', '.join(branches),
', '.join(agents),
', '.join(owners)
)
report += value + '\n'
report += ' ' * 5 + actions['given'][pkg][branches[0]]['msg'][
'package_listing']['package']['summary'] + '\n'
report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\
'acls/name/%s\n' % pkg
report += '\n%s packages had new branches\n' % len(actions['new'])
report += '-' * (len(str(len(actions['new']))) + 23) + '\n'
for pkg in sorted(actions['new']):
branches = [item for item in actions['new'][pkg]]
agents = set([
actions['new'][pkg][item]['msg']['agent']
for item in actions['new'][pkg]])
owners = set([
actions['new'][pkg][item]['msg']['package_listing']['owner']
for item in actions['new'][pkg]])
if len(branches) == 1:
branch = ': %s' % branches[0]
else:
branch = 'es: %s' % ', '.join(branches)
value = u'%s had a new branch%s for %s by %s' % (
pkg,
branch,
', '.join(owners),
', '.join(agents),
)
report += value + '\n'
report += ' ' * 5 + actions['new'][pkg][branches[0]]['msg'][
'package_listing']['package']['summary'] + '\n'
report += ' ' * 5 + 'https://admin.fedoraproject.org/pkgdb/'\
'acls/name/%s\n' % pkg
report += '\n\nSources: https://github.com/pypingou/fedora-owner-change'
if args.nomail:
print report
else:
send_report(report)
if __name__ == '__main__':
import sys
sys.exit(main())

View file

@ -0,0 +1,28 @@
---
# Cron job for the fedora-owner-change
## Install packages
- name: Install needed packages
yum: pkg={{ item }} state=installed
with_items:
- python-requests
tags:
- packages
## Install all files
- name: Install the fedora-owner-change script
copy: >
src=fedora-owner-change.py dest=/usr/local/bin/fedora-owner-change.py
owner=root group=root mode=0755
tags:
- files
## Install the cron job
- name: Install the fedora-owner-change cronjob
copy: >
src=fedora-owner-change.cron dest=/etc/cron.d/fedora-owner-change.cron
owner=root group=root mode=0755
tags:
- files

View file

@ -9,8 +9,8 @@ import zmq
try:
service = sys.argv[1]
check_consumer = sys.argv[2]
backlog_warning = sys.argv[3]
backlog_critical = sys.argv[4]
backlog_warning = int(sys.argv[3])
backlog_critical = int(sys.argv[4])
fname = '/var/run/fedmsg/monitoring-%s.socket' % service
if not os.path.exists(fname):
print "UNKNOWN - %s does not exist" % fname

View file

@ -9,8 +9,8 @@ import zmq
try:
service = sys.argv[1]
check_consumer = sys.argv[2]
exceptions_warning = sys.argv[3]
exceptions_critical = sys.argv[4]
exceptions_warning = int(sys.argv[3])
exceptions_critical = int(sys.argv[4])
fname = '/var/run/fedmsg/monitoring-%s.socket' % service
if not os.path.exists(fname):
print "UNKNOWN - %s does not exist" % fname
@ -25,7 +25,7 @@ try:
for consumer in msg['consumers']:
if consumer['name'] == check_consumer:
if consumer['exceptions'] > exceptions_critical:
if consumer['exceptions'] > exceptions_critical:
print 'CRITICAL: fedmsg consumer %s exceptions value is %i' % (consumer['name'],consumer['exceptions'])
sys.exit(2)
elif consumer['exceptions'] > exceptions_warning:

View file

@ -80,6 +80,11 @@
state=true
persistent=true
- name: set sebooleans so apache can send emails
action: seboolean name=httpd_can_sendmail
state=true
persistent=true
- name: apply selinux type to the wsgi file
file: >
dest=/usr/share/nuancier/nuancier.wsgi

Binary file not shown.

View file

@ -0,0 +1,26 @@
{
"org.fedoraproject.prod.buildsys.repo.done": {
"args": [
"msg/tag",
"msg/instance"
]
},
"org.fedoraproject.prod.buildsys.tag": {
"args": [
"msg/tag",
"msg/name",
"msg/version",
"msg/release",
"msg/user"
]
},
"org.fedoraproject.prod.buildsys.untag" : {
"args": [
"msg/tag",
"msg/name",
"msg/version",
"msg/release",
"msg/user"
]
}
}

View file

@ -0,0 +1,35 @@
---
- name: copy repo definition
template: src=koji-tag-package.repo dest="/etc/yum.repos.d/{{ kojitag }}.repo" owner=root group=root
- name: install publican & brand
yum: name="publican-{{ publican_brand }}-web" state=installed
- name: install fedwatch
yum: name=fedwatch state=installed enablerepo=epel-testing
# needs updating!
- name: copy fedwatch.conf
copy: src=fedwatch.conf dest=/etc/fedwatch.conf mode=0644
# verify + test
- name: copy fedwatch triggers
template: src=20-docs-trigger.sh dest=/etc/fedwatch.d/ owner=root mode=0744
- name: turn on fedwatch.service
service: name=fedwatch enabled=yes state=started
- name: hourly check for doc updates
cron: name="{{ kojitag }}-repo-check" day=* hour=* state=present job="yum -y --disablerepo=\* --enablerepo=el6-docs install \*web-[a-z][a-z]-[A-Z][A-Z]\*.noarch 2>&1 > /tmp/latest_{{ kojitag }}_update.log"
# needs inspection, web_version maybe?
# more templating?
- name: copy publican website config
template: src=publican-website.cfg dest=/etc/publican-website.cfg
# verify
- name: copy empty sqlite db; publican only creates this interactively
copy: src=empty_publican_site.db dest=/var/www/html/{{ publican_brand }}.{{ kojitag }}.db
# do stuff ?

View file

@ -0,0 +1,36 @@
#!/bin/bash
if [[ "$1" == "org.fedoraproject.prod.buildsys.repo.done" && "$3" == "{{ kojitag }}" ]];then
# Let us know when the repo finishes rebuilding, so that we can install *all*
# documents (based on a slightly fragile match)
echo "Repo_done::start topic=$1; name=$2; instance=$3 " >> /tmp/fedwatch_{{ kojitag }}.log
echo "* Calling on yum to install all outstanding docs *" >> /tmp/fedwatch{{ kojitag }}.log
yum --disablerepo=\* --enablerepo={{ kojitag }} clean all 2>&1 >> /tmp/fedwatch_{{ kojitag }}.log
yum -y --disablerepo=\* --enablerepo={{ kojitag }} install \*-web-[a-z][a-z]\*-[A-Z][A-Z]\*.noarch 2>&1 >> /tmp/fedwatch{{ kojitag }}.log
echo "Repo_done::end" >> /tmp/fedwatch_{{ kojitag }}.log
elif [[ "$1" == "org.fedoraproject.prod.buildsys.tag" && "$2" == "el6-docs" ]]; then
# Let us know when packages have been tagged into the {{ kojitag }} tag, just for
# informational purposes. We can't install based on this trigger, as we have to wait
# for the createrepo process to finish
echo "Tagged::info topic=$1; tag=$2; name=$3; version=$4; release=$5; user=$6" >> /tmp/fedwatch_{{ kojitag }}.log
elif [[ "$1" == "org.fedoraproject.prod.buildsys.untag" ]]; then
echo "Untagged::start topic=$1; name=$2; version=$3; release=$4; user=$5" >> /tmp/fedwatch_{{ kojitag }}.log
# fedwatch isn't telling us which repo/tag/target the package is being untagged from, so we have to
# resort to silly shell games in order to make sure it's really a Publican document
if [[ $(locale -a | sed -e 's/_/-/' | grep -c $(echo "$2-$3-$4" | sed -r 's/.*-web-([a-z]{2,3}-[A-Z]{2})-.*/\1/')) -gt 0 ]]; then
if [[ "$5" == "oscar" ]]; then
# Do not do any removals that are triggered by "oscar", who is the
# garbage collector in Koji
echo "* Skipping the removal of $2-$3-$4, because of garbage collection *" >> /tmp/fedwatch{{ kojitag }}.log
else
echo "* Calling on yum to remove $2-$3-$4 *" >> /tmp/fedwatch{{ kojitag }}.log
yum -y remove $2-$3-$4 2>&1 >> /tmp/fedwatch{{ kojitag }}.log
fi
else
echo "* Skipping removal of $2-$3-$4, because it doesn't appear to be a docs package *" >> /tmp/fedwatch{{ kojitag }}.log
fi
echo "Untagged::end" >> /tmp/fedwatch{{ kojitag }}.log
else
# Uncomment this next line for more debugging info
echo "Unknown::info topic=$1; 2=$2; 3=$3; 4=$4; 5=$5; 6=$6; 7=$7" >> /tmp/fedwatch{{ kojitag }}.log
fi

View file

@ -0,0 +1,7 @@
# {{ ansible_managed }}
[{{ kojitag }}]
name={{ kojitag }} Repository: $releasever - $basearch
baseurl=http://kojipkgs.fedoraproject.org/repos/{{ kojitag }}/latest/$basearch/
enabled=1
gpgcheck=0
cost=1337

View file

@ -0,0 +1,6 @@
db_file: /var/www/html/{{ publican_brand }}.{{ kojitag }}.db
toc_path: /var/www/html/docs/
host: {{ site_host }}
title: "site_host"
search: '<p/>'
web_style: 2