system-config/testinfra/test_gitea.py
Clark Boylan 67662bb735 Run gitea with memcached cache adapter
By default gitea caches everything in memory using a Go hashmap. There
is suspicion that the now many persistent AI web crawlers cause this
hashmap to grow in ways that eventually cause the Go GC system to pause
the world in noticeable ways when loading pages. Restarting the gitea
services seems to temporarily reset things (as it should with an in
memory map) until we cross some threshold and things become slow again.

The good news is that gitea supports several backends (called adapters)
for the cache. We elect to use memcached because it is relatively
simple and has a FOSS license (unlike redis). The other alternative we
could consider is twoqueue which also caches within memory in the Go
runtime but allows for setting a size limit. I've gone with memcached
because it doesn't rely on Golang GC, but twoqueue is likely simpler if
we want to start there.

Note we also bump the job timeout to 5400 seconds (90 minutes) from 4800
seconds (80 minutes) because a run on ovh-gra1 timed out while running
testinfra test cases (the very end of the job). It is possible that
using memcache is slightly slower than using in process memory caching,
but the goal here isn't to make things faster it is to make things more
consistent over time. As long as memcached performance is within the
same ballpark and doesn't degrade over time this is acceptable.

Change-Id: Ie9ca246a8321fe84d9a1582e35cd4c5459b48bee
2025-02-28 10:49:27 -08:00

172 lines
7.0 KiB
Python

# 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.
from util import take_screenshots
testinfra_hosts = ['gitea99.opendev.org']
def test_gitea_listening(host):
gitea_https = host.socket("tcp://0.0.0.0:3000")
assert gitea_https.is_listening
gitea_http = host.socket("tcp://0.0.0.0:3080")
assert gitea_http.is_listening
gitea_ssh = host.socket("tcp://0.0.0.0:222")
assert gitea_ssh.is_listening
gitea_proxy = host.socket("tcp://0.0.0.0:3081")
assert gitea_proxy.is_listening
memcached = host.socket("tcp://127.0.0.1:11211")
assert memcached.is_listening
def test_ulimit(host):
cmd = host.run("/usr/local/bin/docker-compose "
"-f /etc/gitea-docker/docker-compose.yaml "
"exec -T gitea-web prlimit")
expected = ("STACK max stack size "
"16777216 9223372036854775807 bytes")
assert expected in cmd.stdout.split('\n')
def test_robots(host):
cmd = host.run('curl --insecure '
'--resolve gitea99.opendev.org:3081:127.0.0.1 '
'https://gitea99.opendev.org:3081/robots.txt')
assert 'Disallow: /' in cmd.stdout
assert 'This was kindly seeded with a mix of' in cmd.stdout
def test_matrix_server(host):
cmd = host.run('curl --insecure -v '
'--resolve gitea99.opendev.org:3081:127.0.0.1 '
'https://gitea99.opendev.org:3081/.well-known/matrix/server')
assert '"m.server": "opendev.ems.host:443"' in cmd.stdout
assert 'Access-Control-Allow-Origin' not in cmd.stderr
def test_matrix_client(host):
cmd = host.run('curl --insecure -v '
'--resolve gitea99.opendev.org:3081:127.0.0.1 '
'https://gitea99.opendev.org:3081/.well-known/matrix/client')
assert '"base_url": "https://opendev.ems.host"' in cmd.stdout
assert 'Access-Control-Allow-Origin' in cmd.stderr
def test_proxy(host):
cmd = host.run('curl --insecure '
'--resolve gitea99.opendev.org:3081:127.0.0.1 '
'https://gitea99.opendev.org:3081/')
assert 'Git with a cup of tea' in cmd.stdout
def test_proxy_ua_blacklist(host):
cmd = host.run('curl --insecure -A '
'" Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)" '
'--resolve gitea99.opendev.org:3081:127.0.0.1 '
'https://gitea99.opendev.org:3081/')
assert '403 Forbidden' in cmd.stdout
def test_ondisk_logs(host):
mariadb_log = host.file('/var/log/containers/docker-mariadb.log')
assert mariadb_log.exists
# Commented out for now as memcached logging is either very quiet and
# we don't create the file or very verbose and far too chatty for
# production (basically no logs or every set and get is logged).
#memcached_log = host.file('/var/log/containers/docker-memcached.log')
#assert memcached_log.exists
gitea_log = host.file('/var/log/containers/docker-gitea.log')
assert gitea_log.exists
gitea_ssh_log = host.file('/var/log/containers/docker-gitea-ssh.log')
assert gitea_ssh_log.exists
assert gitea_ssh_log.contains("Server listening on :: port 222.")
def test_project_clone(host):
# Note this tests the result of a project rename in gitea as well.
cmd = host.run(
'GIT_SSL_NO_VERIFY=1 '
'git clone https://localhost:3081/opendev/disk-image-builder '
'/tmp/disk-image-builder')
assert "Cloning into '/tmp/disk-image-builder'..." in cmd.stderr
assert cmd.succeeded
# Check that our default of master is still honored.
# Gitea defaults to main as of 1.17.0.
cmd = host.run(
'git -C /tmp/disk-image-builder '
'symbolic-ref refs/remotes/origin/HEAD')
assert "refs/remotes/origin/master" in cmd.stdout
assert "refs/remotes/origin/main" not in cmd.stdout
assert cmd.succeeded
def test_partial_project_clone(host):
cmd = host.run(
'GIT_SSL_NO_VERIFY=1 '
'git clone --filter=blob:none '
'https://localhost:3081/opendev/system-config '
'/tmp/test-system-config-clone')
assert "Cloning into '/tmp/test-system-config-clone'..." in cmd.stderr
assert cmd.succeeded
# Check that our default of master is still honored.
# Gitea defaults to main as of 1.17.0.
cmd = host.run(
'git -C /tmp/test-system-config-clone '
'symbolic-ref refs/remotes/origin/HEAD')
assert "refs/remotes/origin/master" in cmd.stdout
assert "refs/remotes/origin/main" not in cmd.stdout
assert cmd.succeeded
def test_no_500_template_content(host):
# We discovered that gitea template rendering errors produce 500 errors
# in the rendered template but not in our http response codes. Check a
# number of pages for 500 errors in the html response.
paths_to_check = [
'/',
'/opendev/system-config',
'/opendev/system-config/src/branch/master/playbooks/roles/gitea/tasks/main.yaml',
'/explore/repos',
'/explore/users',
'/explore/organizations',
'/explore/code?q=gitea&t=',
]
for path in paths_to_check:
cmd = host.run('curl --insecure '
'--resolve gitea99.opendev.org:3081:127.0.0.1 '
'https://gitea99.opendev.org:3081' + path)
assert 'status-page-500' not in cmd.stdout
assert '<title>Internal Server Error' not in cmd.stdout
def test_gitea_screenshots(host):
shots = (
('https://localhost:3081', None, 'gitea-main.png'),
('https://localhost:3081/opendev/system-config', None,
'gitea-project-system-config.png'),
# Fetch system-config twice to ensure we exercise the caching
# system.
('https://localhost:3081/opendev/system-config', None,
'gitea-project-system-config2.png'),
('https://localhost:3081/opendev/disk-image-builder', None,
'gitea-project-dib.png'),
('https://localhost:3081/opendev/', None,
'gitea-org-opendev.png'),
('https://localhost:3081/explore/organizations', None,
'gitea-org-explore.png'),
)
take_screenshots(host, shots)
def test_memcached_has_data(host):
# We only listen on localhost on the gitea server otherwise we could
# open a socket directly from this test case and request the stats data.
cmd = host.run("echo 'stats' | nc -N 127.0.0.1 11211")
assert cmd.succeeded
# Having more than 0 bytes in memcached implies gitea is using
# the server as a cache.
assert 'STAT bytes 0' not in cmd.stdout