Run a gerrit container on review-dev01

This runs gerrit in a container on review-dev01 using podman.

Remove an unused web_server.py file that we found from copying it
from puppet to ansible.

Change-Id: I399d3cf8471bc8063022b0db0ff81718b2ee2941
This commit is contained in:
James E. Blair 2019-01-31 09:26:38 -08:00 committed by Monty Taylor
parent 3b48ad0def
commit 4f9720e76e
27 changed files with 1645 additions and 185 deletions

View File

@ -1007,6 +1007,32 @@
- playbooks/roles/zuul-preview/
- testinfra/test_zuul_preview.py
- job:
name: system-config-run-review-dev
parent: system-config-run
description: |
Run the playbook for gerrit (in a container).
nodeset:
nodes:
- name: bridge.openstack.org
label: ubuntu-bionic
- name: review-dev01.openstack.org
label: ubuntu-bionic
vars:
run_playbooks:
- playbooks/service-review-dev.yaml
host-vars:
review-dev01.openstack.org:
host_copy_output:
'/home/gerrit2/review_site/etc': logs
'/home/gerrit2/review_site/logs': logs
files:
- playbooks/group_vars/review-dev.yaml
- ^playbooks/host_vars/review-dev\d+.opendev.org.yaml
- playbooks/zuul/templates/group_vars/review.yaml.j2
- playbooks/roles/gerrit/
- testinfra/test_gerrit.py
- job:
name: infra-prod-playbook
description: |
@ -1064,6 +1090,7 @@
soft: true
- name: system-config-build-image-haproxy-statsd
soft: true
- system-config-run-review-dev
- system-config-run-zuul-preview
- system-config-run-letsencrypt
- system-config-build-image-bazel
@ -1123,6 +1150,7 @@
soft: true
- name: system-config-upload-image-haproxy-statsd
soft: true
- system-config-run-review-dev
- system-config-run-zuul-preview
- system-config-run-letsencrypt
- system-config-upload-image-bazel

View File

@ -1,178 +0,0 @@
#!/usr/bin/env python
#
# Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""
This is a simple test server that serves up the web content locally
as if it was a working remote server. It also proxies all the live
date/*.json files into the local test server, so that the Ajax async
loading works without hitting Cross Site Scripting violations.
"""
import argparse
import BaseHTTPServer
import os.path
import urllib2
import requests
# Values for these set via cli defaults
GERRIT_UPSTREAM = ""
ZUUL_UPSTREAM = ""
def replace_urls(line, port):
line = line.replace(
GERRIT_UPSTREAM,
"http://localhost:%s" % port)
line = line.replace(
ZUUL_UPSTREAM,
"http://localhost:%s" % port)
return line
class GerritHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""A request handler to create a magic local Gerrit server"""
def do_POST(self):
data = self.rfile.read(int(self.headers['content-length']))
headers = {}
# we need to trim some of the local headers in order for this
# request to remain valid.
for header in self.headers:
if header not in ("host", "origin", "connection"):
headers[header] = self.headers[header]
resp = requests.post("%s%s" %
(GERRIT_UPSTREAM, self.path),
headers=headers,
data=data)
# Process request back to client
self.send_response(resp.status_code)
for header in resp.headers:
# Requests has now decoded the response so it's no longer
# a gzip stream, which also means content-length is
# wrong. So we remove content-encoding, then drop
# content-length because if provided Gerrit strictly uses
# it for reads. We also drop all the keep-alive related
# headers, our server doesn't do that.
if header not in ("connection", "content-length",
"keep-alive", "content-encoding"):
self.send_header(header, resp.headers[header])
self.end_headers()
self.wfile.write(resp.text)
def do_GET(self):
# possible local file path
local_path = self.path.replace('/static/', '').split('?')[0]
# if the file exists locally, we'll serve it up directly
if os.path.isfile(local_path):
self.send_response(200, "Success")
self.end_headers()
with open(local_path) as f:
for line in f.readlines():
line = replace_urls(line, self.server.server_port)
self.wfile.write(line)
print "Loaded from local override"
return
# First we'll look for a zuul status call, /status doesn't map
# to gerrit so we can overload the localhost server for this.
if self.path.startswith("/status"):
try:
zuul_url = "%s%s" % (ZUUL_UPSTREAM, self.path)
# BUG(sdague): for some reason SSL connections to zuul
# from python 2.7 blow up with an SSL exception
zuul_url = zuul_url.replace('https', 'http')
response = urllib2.urlopen(zuul_url)
self.send_response(200, "Success")
for header in response.info():
# need to reset content-length otherwise jquery complains
if header not in ("connection", "content-length",
"keep-alive", "content-encoding"):
self.send_header(header, response.info()[header])
self.end_headers()
for line in response.readlines():
line = replace_urls(line, self.server.server_port)
self.wfile.write(line)
return
except urllib2.HTTPError as e:
self.send_response(e.code)
self.end_headers()
self.wfile.write(e.read())
return
except urllib2.URLError as e:
print "URLError on %s" % (zuul_url)
print e
# If you've not built local data to test with, instead grab
# the data off the production server on the fly and serve it
# up from our server.
try:
response = urllib2.urlopen("%s%s" %
(GERRIT_UPSTREAM, self.path))
self.send_response(200, "Success")
for header in response.info():
self.send_header(header, response.info()[header])
self.end_headers()
for line in response.readlines():
line = replace_urls(line, self.server.server_port)
self.wfile.write(line)
except urllib2.HTTPError as e:
self.send_response(e.code)
self.end_headers()
self.wfile.write(e.read())
def parse_opts():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('-p', '--port',
help='port to bind to [default: 8001]',
type=int,
default=8001)
parser.add_argument('-z', '--zuul-url',
help='url for zuul server',
default="https://zuul.openstack.org")
parser.add_argument('-g', '--gerrit-url',
help='url for gerrit server',
default="https://review.opendev.org")
return parser.parse_args()
def main():
global ZUUL_UPSTREAM
global GERRIT_UPSTREAM
opts = parse_opts()
ZUUL_UPSTREAM = opts.zuul_url
GERRIT_UPSTREAM = opts.gerrit_url
server_address = ('', opts.port)
httpd = BaseHTTPServer.HTTPServer(server_address, GerritHandler)
print "Test Server is running at http://localhost:%s" % opts.port
print "Ctrl-C to exit"
print
while True:
httpd.handle_request()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print "\n"
print "Thanks for testing! Please come again."

View File

@ -0,0 +1 @@
Run Gerrit.

View File

@ -0,0 +1,5 @@
gerrit_id: 3000
gerrit_user_name: gerrit2
gerrit_home_dir: /home/gerrit2
gerrit_site_dir: "{{ gerrit_home_dir }}/review_site"
gerrit_run_init: false

View File

@ -0,0 +1,259 @@
<html><body><div>
<h1>
OpenStack Project Individual Contributor License Agreement
</h1>
<!--
This is the current OpenStack Project Individual Contributor License Agreement
reformatted for HTML from the original "RevisedCLA.doc" with SHA1 sum
0467dd893d276cefde614e063a363b995d67e5ee provided by Jonathan Bryce, Executive
Director on behalf of The OpenStack Foundation on Monday, January 7, 2013. No
textual content was changed except to replace quote marks with their strict
ASCII equivalents, add the original LLC CLA text as a block quote, and restore
a previously inapplicable statement (sentence #2 of paragraph #2) adapted from
the Apache Software Foundation ICLA at his direction.
-->
<p><em>
In order to clarify the intellectual property license granted with
Contributions from any person or entity, the OpenStack Project (the "Project")
must have a Contributor License Agreement ("Agreement") on file that has been
signed by each Contributor, indicating agreement to the license terms below.
This license is for your protection as a Contributor as well as the protection
of OpenStack Foundation as Project manager (the "Project Manager") and the
Project users; it does not change your rights to use your own Contributions for
any other purpose.
</em></p>
<p><em>
You accept and agree to the following terms and conditions for Your present and
future Contributions submitted to the Project Manager. In return, the Project
Manager shall not use Your Contributions in a way that is contrary to the
public benefit or inconsistent with its nonprofit status and bylaws in effect
at the time of the Contribution. Except for the license granted herein to the
Project Manager and recipients of software distributed by the Project Manager,
You reserve all right, title, and interest in and to Your Contributions.
</em></p>
<ol>
<li><p><strong>
Definitions.
</strong>
"You" (or "Your") shall mean the copyright owner or legal entity authorized by
the copyright owner that is making this Agreement with the Project Manager. For
legal entities, the entity making a Contribution and all other entities that
control, are controlled by, or are under common control with that entity are
considered to be a single Contributor. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership
of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial
ownership of such entity. "Contribution" shall mean any original work of
authorship, including any modifications or additions to an existing work, that
is intentionally submitted by You to the Project Manager for inclusion in, or
documentation of, any of the projects owned or managed by the Project Manager
(the "Work"). For the purposes of this definition, "submitted" means any form of
electronic, verbal, or written communication sent to the Project Manager or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems that are
managed by, or on behalf of, the Project Manager for the purpose of discussing
and improving the Work, but excluding communication that is conspicuously marked
or otherwise designated in writing by You as "Not a Contribution."
</p></li>
<li><p><strong>
Grant of Copyright License.
</strong>
Subject to the terms and conditions of this Agreement, You hereby grant to the
Project Manager and to recipients of software distributed by the Project
Manager a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare derivative works of,
publicly display, publicly perform, sublicense, and distribute Your
Contributions and such derivative works.
</p></li>
<li><p><strong>
Grant of Patent License.
</strong>
Subject to the terms and conditions of this Agreement, You hereby grant to the
Project Manager and to recipients of software distributed by the Project
Manager a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by You that are
necessarily infringed by Your Contribution(s) alone or by combination of Your
Contribution(s) with the Work to which such Contribution(s) was submitted. If
any entity institutes patent litigation against You or any other entity
(including a cross-claim or counterclaim in a lawsuit) alleging that Your
Contribution, or the Work to which You have contributed, constitutes direct or
contributory patent infringement, then any patent licenses granted to that
entity under this Agreement for that Contribution or Work shall terminate as of
the date such litigation is filed.
</p></li>
<li><p>
You represent that you are legally entitled to grant the above license. If your
employer(s) has rights to intellectual property that you create that includes
your Contributions, You represent that you have received permission to make
Contributions on behalf of that employer, that your employer has waived such
rights for your Contributions to the Project Manager, or that your employer has
executed a separate Corporate Contributor License Agreement with the Project
Manager.
</p></li>
<li><p>
You represent that each of Your Contributions is Your original creation (see
Section 7 for submissions on behalf of others). You represent that Your
Contribution submissions include complete details of any third-party license or
other restriction (including, but not limited to, related patents and
trademarks) of which you are personally aware and which are associated with any
part of Your Contributions.
</p></li>
<li><p>
You are not expected to provide support for Your Contributions, except to the
extent You desire to provide support. You may provide support for free, for a
fee, or not at all. Unless required by applicable law or agreed to in writing,
You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NONINFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
</p></li>
<li><p>
Should You wish to submit work that is not Your original creation, You may
submit it to the Project Manager separately from any Contribution, identifying
the complete details of its source and of any license or other restriction
(including, but not limited to, related patents, trademarks, and license
agreements) of which you are personally aware, and conspicuously marking the
work as "Submitted on behalf of a third-party: [named here]".
</p></li>
<li><p>
You agree to notify the Project Manager of any facts or circumstances of which
you become aware that would make these representations inaccurate in any
respect.
</p></li>
<li><p>
In addition, if you have provided a Contribution (as defined in the LLC
Contribution License Agreement below) to the Project under the Contribution
License Agreement to OpenStack, LLC ("LLC Contribution Agreement"), you agree
that OpenStack, LLC may assign the LLC Contribution Agreement along with all
its rights and obligations under the LLC Contribution License Agreement to the
Project Manager.
</p></li>
</ol>
<blockquote>
<p><em>In order to clarify the intellectual property license granted with
Contributions from any person or entity, the OpenStack Project (the "Project")
must have a Contributor License Agreement ("Agreement") on file that has been
signed by each Contributor, indicating agreement to the license terms below.
This license is for your protection as a Contributor as well as the protection
of OpenStack, LLC as Project manager (the "Project Manager") and the Project
users; it does not change your rights to use your own Contributions for any
other purpose. If you have not already done so, please complete and sign this
Individual License Agreement by following the instructions embedded below.
After you fill in the required information and apply your digital signature to
the Agreement, the signature service will generate an email to you. You must
confirm your digital signature as instructed in this email to complete the
signing process. The signature service will then send you a signed copy of this
Agreement for your records.</em></p>
<p><em>You accept and agree to the following terms and conditions for Your
present and future Contributions submitted to the Project Manager. Except for
the license granted herein to the Project Manager and recipients of software
distributed by the Project Manager, You reserve all right, title, and interest
in and to Your Contributions.</em></p>
<ol>
<li><p><strong>Definitions</strong>"You" (or "Your") shall mean the copyright
owner or legal entity authorized by the copyright owner that is making this
Agreement with the Project Manager. For legal entities, the entity making a
Contribution and all other entities that control, are controlled by, or are
under common control with that entity are considered to be a single
Contributor. For the purposes of this definition, "control" means (i) the
power, direct or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or
more of the outstanding shares, or (iii) beneficial ownership of such
entity. "Contribution" shall mean any original work of authorship, including
any modifications or additions to an existing work, that is intentionally
submitted by You to the Project Manager for inclusion in, or documentation of,
any of the projects owned or managed by the Project Manager (the "Work"). For
the purposes of this definition, "submitted" means any form of electronic,
verbal, or written communication sent to the Project Manager or its
representatives, including but not limited to communication on electronic
mailing lists, source code control systems, and issue tracking systems that are
managed by, or on behalf of, the Project Manager for the purpose of discussing
and improving the Work, but excluding communication that is conspicuously
marked or otherwise designated in writing by You as "Not a
Contribution."</p></li>
<li><p><strong>Grant of Copyright License.</strong> Subject to the terms and
conditions of this Agreement, You hereby grant to the Project Manager and to
recipients of software distributed by the Project Manager a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright
license to reproduce, prepare derivative works of, publicly display, publicly
perform, sublicense, and distribute Your Contributions and such derivative
works.</p></li>
<li><p><strong>Grant of Patent License.</strong> Subject to the terms and
conditions of this Agreement, You hereby grant to the Project Manager and to
recipients of software distributed by the Project Manager a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as
stated in this section) patent license to make, have made, use, offer to sell,
sell, import, and otherwise transfer the Work, where such license applies only
to those patent claims licensable by You that are necessarily infringed by Your
Contribution(s) alone or by combination of Your Contribution(s) with the Work
to which such Contribution(s) was submitted. If any entity institutes patent
litigation against You or any other entity (including a cross-claim or
counterclaim in a lawsuit) alleging that Your Contribution, or the Work to
which You have contributed, constitutes direct or contributory patent
infringement, then any patent licenses granted to that entity under this
Agreement for that Contribution or Work shall terminate as of the date such
litigation is filed.</p></li>
<li><p>You represent that you are legally entitled to grant the above license.
If your employer(s) has rights to intellectual property that you create that
includes your Contributions, You represent that you have received permission to
make Contributions on behalf of that employer, that your employer has waived
such rights for your Contributions to the Project Manager, or that your
employer has executed a separate Corporate Contributor License Agreement with
the Project Manager.</p></li>
<li><p>You represent that each of Your Contributions is Your original creation
(see Section 7 for submissions on behalf other others). You represent that Your
Contribution submissions include complete details of any third-party license or
other restriction (including, but not limited to, related patents and
trademarks) of which you are personally aware and which are associated with any
part of Your Contributions.</p></li>
<li><p>You are not expected to provide support for Your Contributions, except
to the extent You desire to provide support. You may provide support for free,
for a fee, or not at all. Unless required by applicable law or agreed to in
writing, You provide Your Contributions on as "AS IS" BASIS, WITHOUT WARRANTIES
OR CONDITIONS OR ANY KIND, either express or implied, including, without
limitation, any warranties or conditions of TITLE, NONINFRINGEMENT,
MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.</p></li>
<li><p>Should You wish to submit work that is not Your original creation, You
may submit it to the Project Manager separately from any Contribution,
identifying the complete details of its source and of any license or other
restriction (including, but not limited to, related patents, trademarks, and
license agreements) of which you are personally aware, and conspicuously
marking the work as "Submitted on behalf of a third-party: [named
here]".</p></li>
<li><p>You agree to notify the Project Manager of any facts or circumstances of
which you become aware that would make these representations inaccurate in any
respect.</p></li>
</ol>
</blockquote>
</div></body></html>

View File

@ -0,0 +1,179 @@
body {color: #000 !important;}
a,a:visited {color: #264D69 !important; text-decoration: none;}
a:hover {color: #000 !important; text-decoration: underline}
a.gwt-InlineHyperlink {background: none !important}
#openstack-logo img { height: 40px; }
#openstack-logo h1 { margin: 20px; }
#gerrit_header #openstack-logo h1 { margin: 20px 0 0 0; }
#gerrit_header {display: block !important; position: relative; top: -60px; margin-bottom: -60px; width: 200px; padding-left: 17px}
#gerrit_header h1 {font-family: 'PT Sans', sans-serif; font-weight: normal; letter-spacing: -1px}
#gerrit_topmenu {background: none; position:relative; top: 0px; left: 220px; margin-right: 220px}
#gerrit_topmenu tbody tr td table {border: 0}
#gerrit_topmenu tbody tr td table.gwt-TabBar {color: #353535; border-bottom: 1px solid #C5E2EA;}
#gerrit_topmenu .gwt-Button {padding: 3px 6px}
.gwt-TabBarItem-selected {color: #CF2F19 !important; border-bottom: 3px solid #CF2F19;}
.gwt-TabBarItem {color: #353535; border-right: 0 !important}
.gwt-TabBar .gwt-TabBarItem, .gwt-TabBar .gwt-TabBarRest, .gwt-TabPanelBottom {background: 0 !important;}
#gerrit_topmenu .searchTextBox {width: 250px}
#change_infoTable {
border-collapse: collapse;
}
#change_infoTable th {
padding: 2px 4px 2px 6px;
background-color: #eef3f5;
font-style: italic;
text-align: left;
}
#change_infoTable td {
padding: 2px 4px 2px 6px;
border-bottom: 1px solid #eef3f5;
border-right: 1px solid #eef3f5;
}
#change_infoTable tr:last-child td {
border: none;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2 {
padding-left: 10px;
padding-right: 10px;
}
/* Section headers */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-headerLine,
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-sectionHeader {
margin-top: 10px !important;
margin-bottom: 10px !important;
}
/* Commit message */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-text::first-line {
font-weight: bold !important;
}
/* Commit metadata */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-commitColumn
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-header th {
padding: 2px 4px 2px 6px;
background-color: #eef3f5;
font-style: italic;
text-align: left;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-commitColumn
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-header td {
border-bottom: 1px solid #eef3f5;
padding: 2px 4px 2px 6px;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-commitColumn
.com-google-gerrit-client-change-CommitBox_BinderImpl_GenCss_style-header td:last-child {
border-right: 1px solid #eef3f5;
}
/* increase the middle info column to fill empty space (for wide
monitors), but ensure there is a sufficient lower bound to kick in
horiz scroll bar. This will relieve the preasure on the hideci test
results. */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-infoColumn {
width: 100% !important;
min-width: 400px;
}
/* Review history */
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-Message_BinderImpl_GenCss_style-name {
font-weight: bold !important;
}
.com-google-gerrit-client-change-ChangeScreen_BinderImpl_GenCss_style-cs2
.com-google-gerrit-client-change-Message_BinderImpl_GenCss_style-messageBox {
width: inherit;
max-width: 1168px;
}
.comment_test_name {
display: inline-block;
*display: inline;
*zoom: 1;
width: auto !important;
width: 25em;
min-width: 20em;
padding-bottom: 2pt;
}
.comment_test_result {
}
.result_SUCCESS {
color: #007f00;
}
.result_FAILURE, .result_POST_FAILURE, .result_TIMED_OUT, .result_RETRY_LIMIT, .result_DISK_FULL {
color: #cf2f19;
}
.result_UNSTABLE, .result_WARNING {
color: #e39f00;
}
.result_LOST {
color: #e39f00;
}
li.comment_test {list-style-type: none; }
/* this is for support of 'Display Person Name In Review Category' */
.cAPPROVAL {
max-width: 100px;
overflow: hidden;
}
/* fixes to make this like old gerrit */
.changeTable td.dataCell {
height: 1em;
}
/* don't make the non voting stand out more than the voting */
table.infoTable td.notVotable,
.changeTable td.dataCell.labelNotApplicable {
background: inherit;
}
.test_result_table {
border-collapse: collapse;
}
.test_result_table tr {
border-left: 1px solid #eef3f5;
border-right: 1px solid #eef3f5;
}
.test_result_table td.header {
background-color: #eef3f5;
}
.test_result_table td {
padding: 2px 4px 2px 6px;
border: 1px solid #eef3f5;
}
.addMemberTextBox {
width: 20em;
}
/* css attribute selector to make -1s show up red in new screen */
[title="Doesn't seem to work"],
[title="This patch needs further work before it can be merged"] {
color: red;
}

View File

@ -0,0 +1,6 @@
<div id="openstack-logo">
<script type="text/javascript" src="static/jquery.js" />
<script type="text/javascript" src="static/jquery-visibility.js"></script>
<script type="text/javascript" src="static/hideci.js" />
<a href="/"><h1><img src="static/title.svg" style="vertical-align:middle;" /></h1></a>
</div>

View File

@ -0,0 +1,16 @@
version: '3'
services:
gerrit:
image: docker.io/opendevorg/gerrit:2.13
network_mode: host
user: gerrit
volumes:
- /home/gerrit2/review_site/cache:/var/gerrit/cache
- /home/gerrit2/review_site/etc:/var/gerrit/etc
- /home/gerrit2/review_site/git:/var/gerrit/git
- /home/gerrit2/review_site/tmp:/var/gerrit/tmp
- /home/gerrit2/review_site/hooks:/var/gerrit/hooks
- /home/gerrit2/review_site/index:/var/gerrit/index
- /home/gerrit2/review_site/logs:/var/log/gerrit
- /home/gerrit2/review_site/static:/var/gerrit/static

View File

@ -0,0 +1,4 @@
#!/bin/sh
# Use timeout to kill any process running longer than 10 minutes.
timeout -k 2m 10m /usr/local/bin/update-bug change-abandoned "$@"

View File

@ -0,0 +1,4 @@
#!/bin/sh
# Use timeout to kill any process running longer than 10 minutes.
timeout -k 2m 10m /usr/local/bin/update-bug change-merged "$@"

View File

@ -0,0 +1,11 @@
# Directions for web crawlers.
# See http://www.robotstxt.org/wc/norobots.html.
User-agent: HTTrack
User-agent: puf
User-agent: MSIECrawler
User-agent: Nutch
Disallow: /
User-agent: msnbot
Crawl-delay: 1

View File

@ -0,0 +1,575 @@
// Copyright (c) 2014 VMware, Inc.
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
// this regex matches the hash part of review pages
var hashRegex = /^\#\/c\/([\d]+)((\/\d+)([.][.](\d+))?)?\/?$/;
// this regex matches CI comments
var ciRegex = /^(.* CI|Jenkins|Zuul)$/;
// this regex matches "Patch set #"
var psRegex = /^(Uploaded patch set|Patch Set) (\d+)(:|\.)/;
// this regex matches merge failure messages
var mergeFailedRegex = /Merge Failed\./;
// this regex matches the name of CI systems we trust to report merge failures
var trustedCIRegex = /^(OpenStack CI|Jenkins|Zuul)$/;
// this regex matches the name+pipeline that we want at the top of the CI list
var firstPartyCI = /^(Jenkins|Zuul)/;
// this regex matches the pipeline markup
var pipelineNameRegex = /Build \w+ \(([-\w]+) pipeline\)/;
// The url to full status information on running jobs
var zuulStatusURL = 'https://zuul.openstack.org';
// The json URL to check for running jobs
var zuulStatusJSON = 'https://zuul.openstack.org/status/change/';
// This is a variable to determine if we're in debugging mode, which
// lets you globally set it to see what's going on in the flow.
var hideci_debug = false;
// This is a variable to enable zuul integration, we default it off so
// that it creates no additional load, and that it's easy to turn off
// the feature.
var zuul_inline = false;
/**
dbg(...) - prints a list of items out to the javascript
console.log. This allows us to leave tracing in this file which is a
no-op by default, but can be triggered if you enter a javascript
console and set hideci_debug = true.
*/
function dbg () {
if (hideci_debug == true) {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
}
function format_time(ms, words) {
if (ms == null) {
return "unknown";
}
var seconds = (+ms)/1000;
var minutes = Math.floor(seconds/60);
var hours = Math.floor(minutes/60);
seconds = Math.floor(seconds % 60);
minutes = Math.floor(minutes % 60);
r = '';
if (words) {
if (hours) {
r += hours;
r += ' hr ';
}
r += minutes + ' min';
} else {
if (hours < 10) r += '0';
r += hours + ':';
if (minutes < 10) r += '0';
r += minutes + ':';
if (seconds < 10) r += '0';
r += seconds;
}
return r;
}
var ci_parse_psnum = function($panel) {
var match = psRegex.exec($panel.html());
if (match !== null) {
return parseInt(match[2]);
}
return 0;
};
var ci_parse_is_merge_conflict = function($panel) {
return (mergeFailedRegex.exec($panel.html()) !== null);
};
var ci_find_pipeline = function($panel) {
var match = pipelineNameRegex.exec($panel.html());
if (match !== null) {
return match[1];
} else {
return null;
}
};
var ci_parse_results = function($panel) {
var result_list = [];
var test_results = $panel.find("li.comment_test");
var pipeline = null;
if (test_results !== null) {
test_results.each(function(i, li) {
var result = {};
if ($(li).find("a").length > 0) {
result["name"] = $(li).find("span.comment_test_name").find("a")[0].innerHTML;
result["link"] = $(li).find("span.comment_test_name").find("a")[0];
}
else {
result["name"] = $(li).find("span.comment_test_name")[0].innerHTML;
}
result["result"] = $(li).find("span.comment_test_result")[0];
result_list.push(result);
});
}
return result_list;
};
/***
* function ci_group_by_ci_pipeline - create a group by structure for
* iterating on CI's pipelines
*
* This function takes the full list of comments, the current patch
* number, and builds an array of (ci_name_pipelinename, comments array)
* tuples. That makes it very easy to process during the display
* phase to ensure we only display the latest result for every CI
* pipeline.
*
* Comments that do not have a parsable pipeline (3rd party ci
* systems) get collapsed by name, and we specify 'check' for their
* pipeline.
*
**/
var ci_group_by_ci_pipeline = function(current, comments) {
var ci_pipelines = [];
var ci_pipeline_comments = [];
for (var i = 0; i < comments.length; i++) {
var comment = comments[i];
if ((comment.psnum != current) || !comment.is_ci || (comment.results.length == 0)) {
continue;
}
var name_pipeline = comment.name;
if (comment.pipeline !== null) {
name_pipeline += ' ' + comment.pipeline;
}
var index = ci_pipelines.indexOf(name_pipeline);
if (index == -1) {
// not found, so create new entries
ci_pipelines.push(name_pipeline);
ci_pipeline_comments.push([comment]);
} else {
ci_pipeline_comments[index].push(comment);
}
}
function sort_by_name(a,b) {
if (a[0] < b[0])
return -1;
else if (a[0] > b[0])
return 1;
else
return 0;
}
var results = [];
var notfirstparty = [];
// we want to separate out first party CI results to always be the
// top of the list, and third party CI to come after, so that
// hunting for first party CI isn't tough.
for (i = 0; i < ci_pipelines.length; i++) {
if (firstPartyCI.test(ci_pipelines[i])) {
results.push([ci_pipelines[i], ci_pipeline_comments[i]]);
} else {
notfirstparty.push([ci_pipelines[i], ci_pipeline_comments[i]]);
}
}
notfirstparty.sort(sort_by_name);
for (i = 0; i < notfirstparty.length; i++) {
results.push(notfirstparty[i]);
}
return results;
};
var ci_parse_comments = function() {
var comments = [];
$("p").each(function() {
var match = psRegex.exec($(this).html());
if (match !== null) {
var psnum = parseInt(match[2]);
var top = $(this).parent().parent().parent();
// old change screen
var name = top.attr("name");
if (!name) {
// new change screen
name = $(this).parent().parent().parent().children().children()[0].innerHTML;
top = $(this).parent().parent().parent().parent();
}
var comment = {};
comment.name = name;
var date_cell = top.find(".commentPanelDateCell");
if (date_cell.attr("title")) {
// old change screen
comment.date = date_cell.attr("title");
} else {
// new change screen
comment.date = $(this).parent().parent().parent().children().children()[2].innerHTML
}
var comment_panel = $(this).parent();
comment.psnum = psnum;
comment.merge_conflict = ci_parse_is_merge_conflict(comment_panel);
comment.pipeline = ci_find_pipeline(comment_panel);
comment.results = ci_parse_results(comment_panel);
comment.is_ci = (ciRegex.exec(comment.name) !== null);
comment.is_trusted_ci = (trustedCIRegex.exec(comment.name) !== null);
comment.ref = top;
dbg("Found comment", comment);
comments.push(comment);
}
});
return comments;
};
var ci_latest_patchset = function(comments) {
var psnum = 0;
for (var i = 0; i < comments.length; i++) {
psnum = Math.max(psnum, comments[i].psnum);
}
return psnum;
};
var ci_is_merge_conflict = function(comments) {
var latest = ci_latest_patchset(comments);
var conflict = false;
for (var i = 0; i < comments.length; i++) {
var comment = comments[i];
// only if we are actually talking about the latest patch set
if (comment.psnum == latest) {
if (comment.is_trusted_ci) {
conflict = comment.merge_conflict;
}
}
}
return conflict;
};
var ci_prepare_results_table = function() {
// Create a table and insert it after the approval table
var table = $("table.test_result_table")[0];
if (!table) {
table = document.createElement("table");
$(table).addClass("test_result_table");
$(table).addClass("infoTable").css({"margin-top":"1em", "margin-bottom":"1em"});
var approval_table = $("div.approvalTable");
if (approval_table.length) {
var outer_table = document.createElement("table");
$(outer_table).insertBefore(approval_table);
var outer_table_row = document.createElement("tr");
$(outer_table).append(outer_table_row);
var td = document.createElement("td");
$(outer_table_row).append(td);
$(td).css({"vertical-align":"top"});
$(td).append(approval_table);
td = document.createElement("td");
$(outer_table_row).append(td);
$(td).css({"vertical-align":"top"});
$(td).append(table);
} else {
var big_table_row = $("div.screen>div>div>table>tbody>tr");
var td = $(big_table_row).children()[1];
$(td).append(table);
}
} else {
$(table).empty();
}
return table;
};
var ci_display_results = function(comments) {
var table = ci_prepare_results_table();
if (ci_is_merge_conflict(comments)) {
var mc_header = $("<tr>").append($('<td class="merge_conflict" colpsan="2">Patch in Merge Conflict</td>'));
mc_header.css('width', '400');
mc_header.css('font-weight', 'bold');
mc_header.css('color', 'red');
mc_header.css('padding-left', '2em');
$(table).append(mc_header);
return;
}
var current = ci_latest_patchset(comments);
var ci_pipelines = ci_group_by_ci_pipeline(current, comments);
for (var i = 0; i < ci_pipelines.length; i++) {
var ci_pipeline_name = ci_pipelines[i][0];
var ci_pipeline_comments = ci_pipelines[i][1];
// the most recent comment on a pipeline
var last = ci_pipeline_comments.length - 1;
var comment = ci_pipeline_comments[last];
var rechecks = "";
if (last > 0) {
rechecks = " (" + last + " rechecks)";
}
var header = $("<tr>").append($('<td class="header">' + ci_pipeline_name + rechecks + '</td>'));
header.append('<td class="header ci_date">' + comment.date + '</td>');
$(table).append(header);
for (var j = 0; j < comment.results.length; j++) {
var result = comment.results[j];
var tr = $("<tr>");
if ("link" in result) {
tr.append($("<td>").append($(result["link"]).clone()));
}
else {
tr.append($("<td>").text(result["name"]));
}
tr.append($("<td>").append($(result["result"]).clone()));
$(table).append(tr);
}
}
};
var set_cookie = function (name, value) {
document.cookie = name + "=" + value + "; path=/";
};
var read_cookie = function (name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) == 0) {
return c.substring(nameEQ.length, c.length);
}
}
return null;
};
var ci_toggle_visibility = function(comments, showOrHide) {
if (!comments) {
comments = ci_parse_comments();
}
$.each(comments, function(i, comment) {
if (comment.is_ci && !comment.is_trusted_ci) {
$(comment.ref).toggle(showOrHide);
}
});
};
var ci_hide_ci_comments = function(comments) {
if (!comments) {
comments = ci_parse_comments();
}
$.each(comments, function(i, comment) {
if (comment.is_ci && !comment.is_trusted_ci) {
$(comment.ref).hide();
}
});
};
var ci_page_loaded = function() {
if (hashRegex.test(window.location.hash)) {
dbg("Searching for ci results on " + window.location.hash);
$("#toggleci").show();
var comments = ci_parse_comments();
ci_display_results(comments);
var showOrHide = 'true' == read_cookie('show-ci-comments');
if (!showOrHide) {
ci_hide_ci_comments(comments);
}
if (zuul_inline === true) {
ci_zuul_for_change(comments);
}
} else {
$("#toggleci").hide();
}
};
var ci_current_change = function() {
var change = hashRegex.exec(window.location.hash);
if (change.length > 1) {
return change[1];
}
return null;
};
// recursively find the zuul status change, will be much more
// efficient once zuul supports since json status.
var ci_find_zuul_status = function (data, change_psnum) {
var objects = [];
for (var i in data) {
if (!data.hasOwnProperty(i)) continue;
if (typeof data[i] == 'object') {
objects = objects.concat(ci_find_zuul_status(data[i],
change_psnum));
} else if (i == 'id' && data.id == change_psnum) {
objects.push(data);
}
}
return objects;
};
var ci_zuul_all_status = function(jobs) {
var status = "passing";
for (var i = 0; i < jobs.length; i++) {
if (jobs[i].result && jobs[i].result != "SUCCESS") {
status = "failing";
break;
}
}
return status;
};
var ci_zuul_display_status = function(status) {
var zuul_table = $("table.zuul_result_table")[0];
if (!zuul_table) {
var test_results = $("table.test_result_table")[0];
zuul_table = document.createElement("table");
$(zuul_table).addClass("zuul_result_table");
$(zuul_table).addClass("infoTable").css({"margin-bottom":"1em"});
if (test_results) {
$(test_results).prepend(zuul_table);
}
}
$(zuul_table).empty();
$(zuul_table).show();
$(zuul_table).append("<tr><td class='header'>Change currently being tested (<a href='" + zuulStatusURL + "'>full status</a>)</td></tr>");
for (var i = 0; i < status.length; i++) {
var item = status[i];
var pipeline = item.jobs[0].pipeline;
var passing = (item.failing_reasons && item.failing_reasons.length > 0) ? "failing" : "passing";
var timeleft = item.remaining_time;
var row = "<tr><td>";
if (pipeline != null) {
row += pipeline + " pipeline: " + passing;
row += " (" + format_time(timeleft, false) + " left)";
} else {
row += "in between pipelines, status should update shortly";
}
row += "</td></tr>";
$(zuul_table).append(row);
}
};
var ci_zuul_clear_status = function () {
var zuul_table = $("table.zuul_result_table")[0];
if (zuul_table) {
$(zuul_table).hide();
}
};
var ci_zuul_process_changes = function(data, change_psnum) {
var zuul_status = ci_find_zuul_status(data, change_psnum);
if (zuul_status.length) {
ci_zuul_display_status(zuul_status);
} else {
ci_zuul_clear_status();
}
};
var ci_zuul_for_change = function(comments) {
if (!comments) {
comments = ci_parse_comments();
}
var change = ci_current_change();
var psnum = ci_latest_patchset(comments);
var change_psnum = change + "," + psnum;
// do the loop recursively in ajax
(function poll() {
$.ajax({
url: zuulStatusJSON + change_psnum,
type: "GET",
success: function(data) {
dbg("Found zuul data for " + change_psnum, data);
ci_zuul_process_changes(data, change_psnum);
},
dataType: "json",
complete: setTimeout(function() {
// once we are done with this cycle in the loop we
// schedule ourselves again in the future with
// setTimeout. However, by the time the function
// actually gets called, other things might have
// happened, and we may want to just dump the data
// instead.
//
// the UI might have gone hidden (user was bored,
// switched to another tab / window).
//
// the user may have navigated to another review url,
// so the data returned is not relevant.
//
// both cases are recoverable when the user navigates
// around, because a new "thread" gets started on
// ci_page_load.
//
// BUG(sdague): there is the possibility that the user
// navigates away from a page and back fast enough
// that the first "thread" is not dead, and a second
// one is started. greghaynes totally said he'd come
// up with a way to fix that.
if (window.zuul_enable_status_updates == false) {
return;
}
var current = ci_current_change();
if (current && change_psnum.indexOf(current) != 0) {
// window url is dead, so don't schedule any more future
// updates for this url.
return;
}
poll();
}, 15000),
timeout: 5000
});
})();
};
window.onload = function() {
var input = document.createElement("input");
input.id = "toggleci";
input.type = "button";
input.className = "gwt-Button";
input.value = "Toggle Extra CI";
input.onclick = function () {
// Flip the cookie
var showOrHide = 'true' == read_cookie('show-ci-comments');
set_cookie('show-ci-comments', showOrHide ? 'false' : 'true');
// Hide or Show existing comments based on cookie
ci_toggle_visibility(null, !showOrHide);
};
document.body.appendChild(input);
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(function(mutations, observer) {
var span = $("span.rpcStatus");
$.each(mutations, function(i, mutation) {
if (mutation.target === span[0] &&
mutation.attributeName === "style" &&
(!(span.is(":visible")))) {
ci_page_loaded();
}
});
});
observer.observe(document, {
subtree: true,
attributes: true
});
$(document).on({
'show.visibility': function() {
window.zuul_enable_status_updates = true;
ci_page_loaded();
},
'hide.visibility': function() {
window.zuul_enable_status_updates = false;
}
});
};

View File

@ -0,0 +1,14 @@
<html><body><div>
<h1>
Gerrit System Role Accounts Proxy CLA
</h1>
<p>
This is not a real CLA and cannot be signed. See <a
href="https://docs.openstack.org/infra/manual/developers.html#account-setup">the
account setup instructions</a> for more information on OpenStack Contributor
License Agreements.
</p>
</div></body></html>

View File

@ -0,0 +1,16 @@
<html><body><div>
<h1>
OpenStack Project U.S. Government Contributor License Agreement
</h1>
<p>
This agreement is not managed through Gerrit. If you need to sign the U.S.
Government Contributor License Agreement, please contact the OpenStack
Foundation to initiate the process. See <a
href="https://docs.openstack.org/infra/manual/developers.html#account-setup">the
account setup instructions</a> for more information on OpenStack Contributor
License Agreements.
</p>
</div></body></html>

View File

@ -0,0 +1,170 @@
# TODO(mordred) We should do *something* where this could use a zuul cloned
# copy of project-config instead. This is needed not just for things like
# manage-projects (which could be run completely differently and non-locally)
# but also for things like notify-impact, which is currently run by a gerrit
# hook inside of the container via jeepyb.
- name: Clone project-config repo
git:
repo: https://opendev.org/openstack/project-config
dest: /opt/project-config
force: yes
- name: Synchronize podman-compose directory
synchronize:
src: gerrit-podman/
dest: /etc/gerrit-podman/
- name: Create Gerrit Group
group:
name: "{{ gerrit_user_name }}"
gid: "{{ gerrit_id }}"
system: yes
- name: Create Gerrit User
user:
name: "{{ gerrit_user_name }}"
uid: "{{ gerrit_id }}"
comment: Gerit User
shell: /bin/bash
home: "{{ gerrit_home_dir }}"
group: "{{ gerrit_user_name }}"
create_home: yes
system: yes
- name: Ensure review_site directory exists
file:
state: directory
path: "{{ gerrit_site_dir }}"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0755
- name: Ensure Gerrit volume directories exists
file:
state: directory
path: "{{ gerrit_site_dir }}/{{ item }}"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0755
loop:
- etc
- git
- index
- cache
- static
- hooks
- tmp
- logs
- name: Write Gerrit config file
template:
src: gerrit.config
dest: "{{ gerrit_site_dir }}/etc/gerrit.config"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0644
- name: Write Gerrit SSH private key
copy:
content: "{{ gerrit_ssh_rsa_key_contents }}"
dest: "{{ gerrit_site_dir }}/etc/ssh_host_rsa_key"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0600
- name: Write Gerrit SSH public key
copy:
content: "{{ gerrit_ssh_rsa_pubkey_contents }}"
dest: "{{ gerrit_site_dir }}/etc/ssh_host_rsa_key.pub"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0644
- name: Write Welcome SSH private key
copy:
content: "{{ welcome_message_gerrit_ssh_private_key }}"
dest: "{{ gerrit_site_dir }}/etc/ssh_welcome_rsa_key"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0600
when: welcome_message_gerrit_ssh_private_key is defined
- name: Write Welcome SSH public key
copy:
content: "{{ welcome_message_gerrit_ssh_public_key }}"
dest: "{{ gerrit_site_dir }}/etc/ssh_welcome_rsa_key.pub"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0644
when: welcome_message_gerrit_ssh_public_key is defined
- name: Copy static hooks
copy:
src: "hooks/{{ item }}"
dest: "{{ gerrit_site_dir }}/hooks/{{ item }}"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0555
loop:
- change-merged
- change-abandoned
- name: Copy notify-impact yaml file
copy:
src: "/opt/project-config/gerrit/notify_impact.yaml"
dest: "{{ gerrit_site_dir }}/hooks/notify_impact.yaml"
remote_src: yes
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0444
- name: Install patchset-created hook
template:
src: patchset-created.j2
dest: "{{ gerrit_site_dir }}/hooks/patchset-created"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: 0555
# TODO(mordred) These things should really go into the image instead.
- name: Copy static and etc
copy:
src: "{{ item }}"
dest: "{{ gerrit_site_dir }}/{{ item }}"
owner: "{{ gerrit_user_name }}"
group: "{{ gerrit_user_name }}"
mode: preserve
loop:
- static
- etc
- name: Install podman-compose
pip:
name: podman-compose
state: latest
# NOTE(mordred) Cannot use full path to pip3 here because it is
# different on zuul test nodes and in production. This is, of
# course, not stellar.
executable: pip3
# TODO(mordred) Make this suck less, like if we could do an init container
# or something just generally less gross.
- name: Run gerrit init
when: gerrit_run_init | bool
command: >
podman run -it --rm --net=host -u gerrit
-v /home/gerrit2/review_site/cache:/var/gerrit/cache
-v /home/gerrit2/review_site/etc:/var/gerrit/etc
-v /home/gerrit2/review_site/git:/var/gerrit/git
-v /home/gerrit2/review_site/tmp:/var/gerrit/tmp
-v /home/gerrit2/review_site/hooks:/var/gerrit/hooks
-v /home/gerrit2/review_site/index:/var/gerrit/index
-v /home/gerrit2/review_site/logs:/var/log/gerrit
-v /home/gerrit2/review_site/static:/var/gerrit/static
docker.io/opendevorg/gerrit:2.13
/usr/local/openjdk-8/bin/java -jar /var/gerrit/bin/gerrit.war init -d /var/gerrit -b --no-auto-start --install-all-plugins
- name: Run podman-compose up
shell:
cmd: podman-compose up -d
chdir: /etc/gerrit-podman/

View File

@ -0,0 +1,180 @@
# This file is managed by ansible.
# https://opendev.org/opendev/system-config
[gerrit]
basePath = git
canonicalWebUrl = https://review.opendev.org/
changeScreen = OLD_UI
reportBugText = Get Help
reportBugUrl = https://docs.openstack.org/infra/system-config/project.html#contributing
gitHttpUrl = https://review.opendev.org/
{{ gerrit_database_config_section }}
[auth]
contributorAgreements = true
type = OPENID_SSO
cookieSecure = true
enableRunAs = true
openIdSsoUrl = https://login.ubuntu.com/+openid
[sendemail]
smtpServer = localhost
from = MIXED
includeDiff = false
[container]
user = gerrit2
startupTimeout = 300
heapLimit = 48g
[gc]
[core]
packedGitOpenFiles = 4096
packedGitLimit = 400m
packedGitWindowSize = 16k
[sshd]
listenAddress = *:29418
threads = 100
maxConnectionsPerUser = 96
[httpd]
listenUrl = proxy-https://*:8081/
minThreads = 20
maxThreads = 100
maxQueued = 200
[cache]
directory = cache
[cache "web_sessions"]
maxAge = 7days
[cache "accounts"]
memoryLimit = 32768
[cache "accounts_byemail"]
memoryLimit = 32768
[cache "accounts_byname"]
memoryLimit = 32768
[cache "groups_byuuid"]
memoryLimit = 32768
[user]
email = review@openstack.org
[change]
allowDrafts = false
[receive]
maxObjectSizeLimit = 100 m
[commentlink "bugheader"]
match = "([Cc]loses|[Pp]artial|[Rr]elated)-[Bb]ug:\\s*#?(\\d+)"
link = "https://launchpad.net/bugs/$2"
html = ""
[commentlink "bug"]
match = "\\b[Bb]ug:? #?(\\d+)"
link = "https://launchpad.net/bugs/$1"
html = ""
[commentlink "story"]
match = "\\b[Ss]tory:? #?(\\d+)"
link = "https://storyboard.openstack.org/#!/story/$1"
html = ""
[commentlink "task"]
match = "\\b[Tt]ask:? #?(\\d+)"
link = "https://storyboard.openstack.org/#!/task/$1"
html = ""
[commentlink "its-storyboard"]
match = "\\b[Tt]ask:? #?(\\d+)"
link = "task: $1"
html = ""
[commentlink "blueprint"]
match = "(\\b[Bb]lue[Pp]rint\\b|\\b[Bb][Pp]\\b)[ \\t#:]*([A-Za-z0-9\\-]+)"
link = "https://blueprints.launchpad.net/openstack/?searchtext=$2"
html = ""
[commentlink "testresult"]
match = "<li>([^ ]+) <a href=\"[^\"]+\" target=\"_blank\" rel=\"nofollow\">([^<]+)</a> : ([^ ]+)([^<]*)</li>"
link = ""
html = "<li class=\"comment_test\"><span class=\"comment_test_name\"><a href=\"$2\" rel=\"nofollow\">$1</a></span> <span class=\"comment_test_result\"><span class=\"result_$3\">$3</span>$4</span></li>"
[commentlink "testresultnoop"]
match = "<li>noop noop : SUCCESS([^<]*)</li>"
link = ""
html = "<li class=\"comment_test\"><span class=\"comment_test_name\">noop</span> <span class=\"comment_test_result\"><span class=\"result_SUCCESS\">SUCCESS</span>$1</span></li>"
[commentlink "launchpadbug"]
match = "<a href=\"(https://bugs\\.launchpad\\.net/[a-zA-Z0-9\\-]+/\\+bug/(\\d+))[^\"]*\">[^<]+</a>"
link = ""
html = "<a href=\"$1\">$1</a>"
[commentlink "changeid"]
match = "(I[0-9a-f]{8,40})"
link = "/#/q/$1"
html = ""
[commentlink "gitsha"]
match = "(<p>|[\\s(])([0-9a-f]{40})(</p>|[\\s.,;:)])"
link = ""
html = "$1<a href=\"/#/q/$2\">$2</a>$3"
[its-storyboard]
url = https://storyboard.openstack.org
[trackingid "launchpad-bug"]
match = "\\#?(\\d+)"
footer = "closes-bug:"
footer = "partial-bug:"
footer = "related-bug:"
system = "Launchpad"
[trackingid "storyboard-story"]
match = "\\#?(\\d+)"
footer = "story:"
system = "Storyboard"
[trackingid "storyboard-task"]
match = "\\#?(\\d+)"
footer = "task:"
system = "Storyboard"
[theme]
backgroundColor = ffffff
topMenuColor = ffffff
textColor = 264d69
trimColor = eef3f5
selectionColor = d1e6ea
changeTableOutdatedColor = f5cccc
tableOddRowColor = ffffff
tableEvenRowColor = f5f5ff
[melody]
monitoring = true
session = true
[plugin "javamelody"]
allowTopMenu = false
# Gerrit upstream hardcodes a .git extension for cgit.
# The cgit settings below are the same just without the
# .git extension.
[gitweb]
type = gitweb
cgi = /usr/share/gitweb/gitweb.cgi
revision = "?p=${project}.git;a=commitdiff;h=${commit}"
[index]
type = LUCENE
threads = 4
[download]
command = checkout
command = cherry_pick
command = pull
command = format_patch
scheme = ssh
scheme = anon_http
scheme = anon_git
archive = tar
archive = tbz2
archive = tgz
archive = txz
[commitmessage]
maxLineLength = 72
[groups]
newGroupsVisibleToAll = true
[mimetype "image/*"]
safe = true
[mimetype "text/x-yaml"]
safe = true
[mimetype "text/xml"]
safe = true
[mimetype "application/xml"]
safe = true
[mimetype "text/x-rst"]
safe = true
[mimetype "text/plain"]
safe = true
[mimetype "text/x-puppet"]
safe = true
[mimetype "text/x-ini"]
safe = true
[mimetype "text/x-properties"]
safe = true
[mimetype "text/x-markdown"]
safe = true
[mimetype "text/css"]
safe = true

View File

@ -0,0 +1,11 @@
#!/bin/sh
# Use timeout to kill any process running longer than 10 minutes.
timeout -k 2m 10m /usr/local/bin/update-blueprint patchset-created "$@"
timeout -k 2m 10m /usr/local/bin/update-bug patchset-created "$@"
timeout -k 2m 10m /usr/local/bin/notify-impact patchset-created "$@" --impact SecurityImpact --dest-address 'openstack-security@lists.openstack.org'
{% if welcome_message_gerrit_ssh_private_key is defined %}
timeout -k 2m 10m /usr/local/bin/welcome-message patchset-created \
--verbose --ssh-user=welcome-message \
--ssh-key=/var/gerrit/etc/ssh_welcome_rsa_key "$@"
{% endif %}

View File

@ -0,0 +1 @@
An ansible role to install podman in the OpenDev production environment

View File

@ -0,0 +1,29 @@
projectatomic_gpg_key: |
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsFNBFlRJjABEADuE3ZLY/2W++bPsxtcaoi7VaNnkvsXuVYbbHalEh/YwKFVsDTo
PQpuw1UlPpmVTwT3ufWfv2v42eZiiWMZaKG9/aWF/TeIdH5+3anfVi+X+tuIW9sv
GKTHZdtDqd7fIhtY6AuNQ/D629TJxLvafZ5MoGeyxjsebt5dOvOrl0SHpwR75uPP
aCXTWrokhH7W2BbJQUB+47k62BMd03EKe8stz9FzUxptROFJJ2bITijJlDXNfSbV
bwCiyREIkzXS6ZdWliJAqencOIZ4UbUax+5BT8SRbSLtr/c4YxvARilpSVCkxo8/
EkPHBGygmgfw0kRPSGtLL7IqfWip9mFObji2geoU3A8gV/i3s9Ccc9GPKApX8r7b
QFs1tIlgUJKPqVwB2FAh+Xrqlsy/+8r95jL2gfRptSw7u8OP4AySj5WVm7cCEQ69
aLyemCsf+v72bFOUXuYQ22Kr3yqz2O/1IsG/0Usr4riTdG65Aq6gnq4KRHMNgXu8
7fC9omoy3sKHvzeAJsw/eC9chYNwO8pv8KRIvpDSGL5L7Ems8mq2C5xMyzSVegTr
AvXu7nJoZWVBFRluh42bZa9QesX9MzzfOQ+G3085aW8BE++lhtX5QOkfRd74E49H
1I2piAq/aE8P9jUHr60Po1C1Tw9iXeEaULLKut8eTMLkQ/02DXhBfq0I5QARAQAB
zSBMYXVuY2hwYWQgUFBBIGZvciBQcm9qZWN0IEF0b21pY8LBeAQTAQIAIgUCWVEm
MAIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQi+zxY3rYx50HLw/5Ad6k
EHf2uT4owvzu393S/bUR6VVwCWYMbg14XgphxnoOfrHZWUjbrETTURyd1UexoHt7
ZDtMCVmzeY0jpvMb1W3WDebFVo+wR4CI15sPjyycsOxWTviD743wxaPCL1s009co
CzWg5AgP88B0D353Y39meC07BBgOJgIfk1OkFdeRjqHfAtucT99NrCuKr/bbBwDn
0E+wWaJoIbQvBzsPIFzMWWQ6RcnrZtyQv35epo+VBmW3VEIkorv1VoStF0RjvJM+
cMW/ogZsIEZk0IUREOtrtTKUXVrMw1hZ9IGYZRpbJ2g670UGuNjW/vo3rRCRSDaF
6Txp5Pn6ZLTgQWsWMw/6M6ooFIEpz3rhYmQSJLNmUN6SgKeWGVmOrQlg4f7YM75o
UEw56GKQWl9FAthO0qH0qF1OMfUKp/Tv2OSV/FNZsokf6alWXOB6Bzj6gYmmGXIv
MfFW5fZ1cuu5/0ULDckxWhVQ1ywLHREEoBQ6oKYONwUjSdWcM+VsKCEFeCqsNwak
qweP8C0fooycfiEZuncc/9ZujgkQ2p7xXTlv3t2SPF9h43xHs3515VS/OTJPGW59
98AqllpfqGxggYs5cwi2LO3xwvHyPoTqj3hcl1dRMspZINRsIo4VC8bSrCOqbjDc
CD2WFOo2c4mwTDmJpz0PLK87ev/WZ8K0OEflTfc=
=DzDk
-----END PGP PUBLIC KEY BLOCK-----

View File

@ -0,0 +1,20 @@
- name: Add PPA GPG key
become: yes
apt_key:
data: "{{ projectatomic_gpg_key }}"
- name: Add projectatomic apt repo
become: yes
template:
dest: /etc/apt/sources.list.d/projectatomic.list
group: root
mode: 0644
owner: root
src: sources.list.j2
- name: Install podman
become: yes
apt:
name: podman
state: present
update_cache: yes

View File

@ -0,0 +1 @@
deb http://ppa.launchpad.net/projectatomic/ppa/ubuntu {{ ansible_lsb.codename }} main

View File

@ -0,0 +1,9 @@
- hosts: "review-dev01.openstack.org:!disabled"
name: "Configure gerrit on review-dev01.openstack.org"
roles:
- pip3
- install-podman
- role: gerrit
gerrit_ssh_rsa_key_contents: "{{ gerrit_dev_ssh_rsa_key_contents }}"
gerrit_ssh_rsa_pubkey_contents: "{{ gerrit_dev_ssh_rsa_pubkey_contents }}"
gerrit_database_config_section: "{{ gerrit_dev_database_config_section }}"

View File

@ -16,19 +16,32 @@
- hosts: all
tasks:
- name: List containers
command: "docker ps -a --format '{{ '{{ .Names }}' }}'"
register: docker_containers
ignore_errors: true
become: true
- name: Create container log dir
file:
path: "/var/log/docker"
state: directory
become: true
- name: Save container logs
- name: List podman containers
command: "podman ps -a --format '{{ '{{ .Names }}' }}'"
register: podman_containers
ignore_errors: true
become: true
- name: Save podman container logs
loop: "{{ podman_containers.stdout_lines | default([]) }}"
shell: "podman logs {{ item }} &> /var/log/docker/{{ item }}.txt"
args:
executable: /bin/bash
become: true
- name: List docker containers
command: "docker ps -a --format '{{ '{{ .Names }}' }}'"
register: docker_containers
ignore_errors: true
become: true
- name: Save docker container logs
loop: "{{ docker_containers.stdout_lines | default([]) }}"
shell: "docker logs {{ item }} &> /var/log/docker/{{ item }}.txt"
args:

View File

@ -80,6 +80,8 @@
- group_vars/gitea-lb.yaml
- group_vars/letsencrypt.yaml
- group_vars/registry.yaml
- group_vars/review.yaml
- group_vars/review-dev.yaml
- group_vars/control-plane-clouds.yaml
- group_vars/mirror_opendev.yaml
- host_vars/bridge.openstack.org.yaml

View File

@ -0,0 +1,34 @@
gerrit_dev_ssh_rsa_key_contents: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAvqQkJUwEGJgqzmOmj2728ikA3Dgl4mzzRiI5zzzLhCLQktL7
UZ6hAc+851mUuQ66vciqUToerhRdNWqNlZzY8On/jXUTVdfUVlXupmDfqmtlax9n
Gi8Aayj4h9F3P3iuNQ+eXWVOyFsCmAMPzaYgWgXx2rxcIqSPq5hG+vDB9oXIpg3a
/244vtIZId1/uNnZDb5jHbZLglupynQBIZ12h2XOUiUfxL84EQnwfL2zC9d6eOjv
cYaCYJ+2VrzG972keY8SJEMLLVEd+q2hFYbbQQxLlmrFpx2G6zNc3d6KLnW0xEH+
b1yEmShcoB8iRRam+IkO+ovoQ5W9FUCmQnWqJQIDAQABAoIBAQCABKeFKDPD9EMi
j0ZlIUXRPfmm6EmAcFs46Hjbkl60H9DiF63OlHBYUBDxZnV5g8ug8CR3IUlC6sfg
u+nR4x7HQMtsSYcvaRzc0R3OOlVYEoBrXA4XRiLI0x15zw593+NUHGXjH8m0v3DR
dZTiK0GkUkOj+EMCvHEB8OMRViVaDjel+TXI6lM2UuexpYLag/u+GotDUQ8sjq4v
kT2FWzrZAGHih98oZ7AflinasGjMBr21lCRq/u3w0ieU4ZPmxpLxz9EUbWS06kQe
W2pafIhDq+4mVtDuhmb87yMMpda+TCBcCRCzA3MGDMGVzQgQvPe49R4EPRWzBWXU
vso8JSzBAoGBAPrDobXukDJ0j2zD3Cw7xCSJy3foU4sdQF5yxeIWox1gfsgkAhn2
zxmuewdfdh0hZAnZWZ41sJzFrEhrvTV/wFIfIZ2qlMf3q3ZdG8c0CQ6E3blsAF8g
jExgck8mV2kvZItowS8JCdWvNw1zpwNJ8Ae+mMUSMBKbs5hzO8X0V1FxAoGBAMKf
JNjqN/LegvlnfFXMPM+vo39MX2RsukwmTZT6msMi3rNgN3oekXSpOK1Mkftrd/wL
B5Vp9Nl3d3kFu3bTKA+N8bjtokXfN+fF9zPFeLwOfEOEtQlnvzb/XF4LhSGiq7Kg
OP6/4udaa9cr9yLE7jTDoLTiyRP796k4ADGRo8n1AoGBAPad0XsAbPYCJk/ca7tg
5+zbS6zYYtlM4lJA5BYPF0o77VPd/ecVEOZ772j33EyX2y/If1eWC+SSj3YF52Yn
Brh8/211Jq9nB0z4EuqdZU7PItRJwC/N7czriWAIIC1FO8fTNTKR3Ac4M5daJ2WX
oKWtL8eYtIiIcl867Q0o2XsxAoGAHtJrWHsHb0wz++GavE/DFbUgNInY1aOugV7T
jJN/rQW5tTi4sHtk18/w7OkieWnUr7LjeZM1NreH0T/KJ5BbWNNHA92GhIBMb0VX
1/gfHdFBdsPuk9W9X61jaHV0mRYVEQ302Mt02OTmDUamNfhwLSUKL3t3EtYlq8P1
q+P/x30CgYEAiLaGdCtlPy5e35ULD/Ep73kOB1uRVtF4JlVpqZ4CygVoCguSZ3Sd
pHMmNylg7j2NyL/9aLKs1NzdGBxpxVa5A4vgcr1DjoS1cuRVEiQoSkI6D6DCmENA
Pb95AevPUxqqAKNZYsj4yDsXnmbFSHARijPWcpfkCDJmVhMFPObr4OE=
-----END RSA PRIVATE KEY-----
gerrit_dev_ssh_rsa_pubkey_contents: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+pCQlTAQYmCrOY6aPbvbyKQDcOCXibPNGIjnPPMuEItCS0vtRnqEBz7znWZS5Drq9yKpROh6uFF01ao2VnNjw6f+NdRNV19RWVe6mYN+qa2VrH2caLwBrKPiH0Xc/eK41D55dZU7IWwKYAw/NpiBaBfHavFwipI+rmEb68MH2hcimDdr/bji+0hkh3X+42dkNvmMdtkuCW6nKdAEhnXaHZc5SJR/EvzgRCfB8vbML13p46O9xhoJgn7ZWvMb3vaR5jxIkQwstUR36raEVhttBDEuWasWnHYbrM1zd3ooudbTEQf5vXISZKFygHyJFFqb4iQ76i+hDlb0VQKZCdaol gerrit-code-review@829f141b0fa5
gerrit_dev_database_config_section: |
[database]
type = h2
database = tmp/ReviewDB
gerrit_run_init: true

View File

@ -0,0 +1,29 @@
gerrit_ssh_rsa_key_contents: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAvqQkJUwEGJgqzmOmj2728ikA3Dgl4mzzRiI5zzzLhCLQktL7
UZ6hAc+851mUuQ66vciqUToerhRdNWqNlZzY8On/jXUTVdfUVlXupmDfqmtlax9n
Gi8Aayj4h9F3P3iuNQ+eXWVOyFsCmAMPzaYgWgXx2rxcIqSPq5hG+vDB9oXIpg3a
/244vtIZId1/uNnZDb5jHbZLglupynQBIZ12h2XOUiUfxL84EQnwfL2zC9d6eOjv
cYaCYJ+2VrzG972keY8SJEMLLVEd+q2hFYbbQQxLlmrFpx2G6zNc3d6KLnW0xEH+
b1yEmShcoB8iRRam+IkO+ovoQ5W9FUCmQnWqJQIDAQABAoIBAQCABKeFKDPD9EMi
j0ZlIUXRPfmm6EmAcFs46Hjbkl60H9DiF63OlHBYUBDxZnV5g8ug8CR3IUlC6sfg
u+nR4x7HQMtsSYcvaRzc0R3OOlVYEoBrXA4XRiLI0x15zw593+NUHGXjH8m0v3DR
dZTiK0GkUkOj+EMCvHEB8OMRViVaDjel+TXI6lM2UuexpYLag/u+GotDUQ8sjq4v
kT2FWzrZAGHih98oZ7AflinasGjMBr21lCRq/u3w0ieU4ZPmxpLxz9EUbWS06kQe
W2pafIhDq+4mVtDuhmb87yMMpda+TCBcCRCzA3MGDMGVzQgQvPe49R4EPRWzBWXU
vso8JSzBAoGBAPrDobXukDJ0j2zD3Cw7xCSJy3foU4sdQF5yxeIWox1gfsgkAhn2
zxmuewdfdh0hZAnZWZ41sJzFrEhrvTV/wFIfIZ2qlMf3q3ZdG8c0CQ6E3blsAF8g
jExgck8mV2kvZItowS8JCdWvNw1zpwNJ8Ae+mMUSMBKbs5hzO8X0V1FxAoGBAMKf
JNjqN/LegvlnfFXMPM+vo39MX2RsukwmTZT6msMi3rNgN3oekXSpOK1Mkftrd/wL
B5Vp9Nl3d3kFu3bTKA+N8bjtokXfN+fF9zPFeLwOfEOEtQlnvzb/XF4LhSGiq7Kg
OP6/4udaa9cr9yLE7jTDoLTiyRP796k4ADGRo8n1AoGBAPad0XsAbPYCJk/ca7tg
5+zbS6zYYtlM4lJA5BYPF0o77VPd/ecVEOZ772j33EyX2y/If1eWC+SSj3YF52Yn
Brh8/211Jq9nB0z4EuqdZU7PItRJwC/N7czriWAIIC1FO8fTNTKR3Ac4M5daJ2WX
oKWtL8eYtIiIcl867Q0o2XsxAoGAHtJrWHsHb0wz++GavE/DFbUgNInY1aOugV7T
jJN/rQW5tTi4sHtk18/w7OkieWnUr7LjeZM1NreH0T/KJ5BbWNNHA92GhIBMb0VX
1/gfHdFBdsPuk9W9X61jaHV0mRYVEQ302Mt02OTmDUamNfhwLSUKL3t3EtYlq8P1
q+P/x30CgYEAiLaGdCtlPy5e35ULD/Ep73kOB1uRVtF4JlVpqZ4CygVoCguSZ3Sd
pHMmNylg7j2NyL/9aLKs1NzdGBxpxVa5A4vgcr1DjoS1cuRVEiQoSkI6D6DCmENA
Pb95AevPUxqqAKNZYsj4yDsXnmbFSHARijPWcpfkCDJmVhMFPObr4OE=
-----END RSA PRIVATE KEY-----
gerrit_ssh_rsa_pubkey_contents: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+pCQlTAQYmCrOY6aPbvbyKQDcOCXibPNGIjnPPMuEItCS0vtRnqEBz7znWZS5Drq9yKpROh6uFF01ao2VnNjw6f+NdRNV19RWVe6mYN+qa2VrH2caLwBrKPiH0Xc/eK41D55dZU7IWwKYAw/NpiBaBfHavFwipI+rmEb68MH2hcimDdr/bji+0hkh3X+42dkNvmMdtkuCW6nKdAEhnXaHZc5SJR/EvzgRCfB8vbML13p46O9xhoJgn7ZWvMb3vaR5jxIkQwstUR36raEVhttBDEuWasWnHYbrM1zd3ooudbTEQf5vXISZKFygHyJFFqb4iQ76i+hDlb0VQKZCdaol gerrit-code-review@829f141b0fa5

21
testinfra/test_gerrit.py Normal file
View File

@ -0,0 +1,21 @@
# Copyright 2018 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
testinfra_hosts = ['review-dev01.openstack.org']
def test_gerrit_listening(host):
gerrit_web = host.socket("tcp://:::8081")
assert gerrit_web.is_listening