Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide stand-alone pbench server container for external integration #3081

Merged
merged 12 commits into from
Jan 5, 2023
Merged
1 change: 0 additions & 1 deletion jenkins/Pipeline.gy
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ pipeline {
returnStdout: true,
script: 'echo ${CHANGE_ID:-${BRANCH_NAME}}'
)}""".trim()
PB_POD_NAME="pbench-in-a-can_${PB_SERVER_IMAGE_TAG}"

PB_DASHBOARD_DIR="${WORKSPACE}/dashboard/build/"
}
Expand Down
10 changes: 5 additions & 5 deletions jenkins/run-server-func-tests
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

export EXTRA_PODMAN_SWITCHES=${EXTRA_PODMAN_SWITCHES:-"--pull=always -e=COV_REPORT_XML=yes"}
export EXTRA_PODMAN_SWITCHES=${EXTRA_PODMAN_SWITCHES:-"--pull=always"}
export IMAGE_KIND=${IMAGE_KIND:-"fedora"}
export IMAGE_REPO=${IMAGE_REPO:-"quay.io/pbench"}
export IMAGE_ROLE=${IMAGE_ROLE:-"ci"}
Expand Down Expand Up @@ -36,7 +36,7 @@ function cleanup {
}

if [[ ${1} == "--cleanup" ]]; then
trap "cleanup ${PB_POD_NAME}" INT QUIT ERR EXIT
trap "cleanup ${PB_POD_NAME}" INT QUIT EXIT
fi

envsubst < server/pbenchinacan/pod.yml | podman play kube -
Expand All @@ -47,17 +47,17 @@ SERVER_API_ENDPOINTS="${SERVER_URL}/api/v1/endpoints"
# Wait at most 10 minutes before giving up.
end_in_epoch_secs=$(( $(date +"%s") + 600 ))

echo "Waiting for pod's httpd to show up ..."
echo "Waiting for pod's reverse proxy to show up ..."
until curl -s -o /dev/null ${SERVER_API_ENDPOINTS}; do
if [[ $(date +"%s") -ge ${end_in_epoch_secs} ]]; then
echo "Timed out waiting for pod's httpd to show up!" >&2
echo "Timed out waiting for pod's reverse proxy to show up!" >&2
exit 1
fi
sleep 1
done
echo "Waiting for pod's Pbench Server to show up ..."
status_code=$(curl -s -o /dev/null -w "%{http_code}" ${SERVER_API_ENDPOINTS})
while [[ "${status_code}" == "503" ]]; do
while [[ "${status_code}" == "502" || "${status_code}" == "503" ]]; do
if [[ $(date +"%s") -ge ${end_in_epoch_secs} ]]; then
echo "Timed out waiting for pod's Pbench Server to show up!" >&2
exit 1
Expand Down
17 changes: 12 additions & 5 deletions jenkins/runlocal
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
#!/bin/bash
set -o errexit

export PB_INTERNAL_CONTAINER_REG=images.paas.redhat.com
export PB_CONTAINER_REG=images.paas.redhat.com
export PB_ORG_NAME=pbench
export PB_SERVER_IMAGE_NAME=pbench-server-ci
export PB_SERVER_IMAGE_TAG=${USER}
export PB_SERVER_IMAGE="${PB_INTERNAL_CONTAINER_REG}/${PB_ORG_NAME}/${PB_SERVER_IMAGE_NAME}"
export PB_POD_NAME=pbench-in-a-can
export PB_DASHBOARD_DIR=$(pwd)/dashboard/build

make -C server/rpm clean rpm

#buildah login -u='$app' -p="${__LOGIN_SECRET__}" ${PB_INTERNAL_CONTAINER_REG}
# Typically, one logs in to a container registery with automated scripts using
# an "application" token. When using quay.io based container registries, the
# application token uses the user name `$app` and the token is provided as the
# password.
#
# For example, if you generate a token and set the value to the environment
# variable named, __LOGIN_SECRET__, then the `buildah login` command below
# demonstrates how to login with that token.
#
# $ buildah login -u='$app' -p="${__LOGIN_SECRET__}" ${PB_CONTAINER_REG}

RPM_PATH=${HOME}/rpmbuild/RPMS/noarch/pbench-server-*.rpm bash -ex ./server/pbenchinacan/container-build-ci.sh
buildah push localhost/${PB_SERVER_IMAGE_NAME}:${PB_SERVER_IMAGE_TAG} ${PB_SERVER_IMAGE}:${PB_SERVER_IMAGE_TAG}
buildah push localhost/${PB_SERVER_IMAGE_NAME}:${PB_SERVER_IMAGE_TAG} ${PB_CONTAINER_REG}/${PB_ORG_NAME}/${PB_SERVER_IMAGE_NAME}:${PB_SERVER_IMAGE_TAG}

jenkins/run-server-func-tests
17 changes: 10 additions & 7 deletions lib/pbench/cli/server/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ def main():
db_wait_timeout = int(server_config.get("database", "wait_timeout"))
workers = str(server_config.get("pbench-server", "workers"))
worker_timeout = str(server_config.get("pbench-server", "worker_timeout"))
oidc_server = server_config.get("authentication", "server_url")
crontab_dir = server_config.get("pbench-server", "crontab-dir")
except (NoOptionError, NoSectionError) as exc:
logger.error("Error fetching required configuration: {}", exc)
Expand All @@ -209,12 +208,16 @@ def main():
logger.error("Database {} not responding", db_uri)
sys.exit(1)

logger.info("Pbench server using OIDC server {}", oidc_server)

logger.debug("Waiting for OIDC server to become available.")
ret_val = keycloak_connection(oidc_server, logger)
if ret_val != 0:
sys.exit(ret_val)
try:
oidc_server = server_config.get("authentication", "server_url")
except (NoOptionError, NoSectionError) as exc:
logger.warning("KeyCloak not configured, {}", exc)
else:
logger.debug("Waiting for OIDC server to become available.")
ret_val = keycloak_connection(oidc_server, logger)
if ret_val != 0:
sys.exit(ret_val)
logger.info("Pbench server using OIDC server {}", oidc_server)

# Multiple gunicorn workers will attempt to connect to the DB; rather than
# attempt to synchronize them, detect a missing DB (from the database URI)
Expand Down
33 changes: 18 additions & 15 deletions lib/pbench/server/api/resources/endpoint_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from flask.globals import current_app
from flask_restful import abort, Resource

from pbench.server import NoOptionError, PbenchServerConfig
from pbench.server import NoOptionError, NoSectionError, PbenchServerConfig


class EndpointConfig(Resource):
Expand Down Expand Up @@ -174,25 +174,28 @@ def get(self):
apis[path] = urljoin(host, url)
templates[path] = template

endpoints = {
"identification": f"Pbench server {self.server_config.COMMIT_ID}",
"api": apis,
"uri": templates,
}

try:
oidc_secret = self.server_config.get("authentication", "secret")
except NoOptionError:
oidc_secret = ""
try:
secret = self.server_config.get("authentication", "secret")
client = self.server_config.get("authentication", "client")
realm = self.server_config.get("authentication", "realm")
issuer = self.server_config.get("authentication", "server_url")
endpoints = {
"authentication": {
"client": client,
"realm": realm,
"issuer": issuer,
"secret": oidc_secret,
},
"identification": f"Pbench server {self.server_config.COMMIT_ID}",
"api": apis,
"uri": templates,
except (NoOptionError, NoSectionError):
pass
else:
endpoints["authentication"] = {
"client": client,
"realm": realm,
"issuer": issuer,
"secret": secret,
}

try:
response = jsonify(endpoints)
except Exception:
self.logger.exception("Something went wrong constructing the endpoint info")
Expand Down
2 changes: 1 addition & 1 deletion lib/pbench/test/unit/server/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

server_cfg_tmpl = """[DEFAULT]
install-dir = {TMP}/opt/pbench-server
default-host = pbench.example.com

[pbench-server]
pbench-top-dir = {TMP}/srv/pbench
Expand All @@ -58,6 +57,7 @@
server_url = keycloak.example.com:0000
realm = pbench
client = pbench-client
secret = my_precious

###########################################################################
# The rest will come from the default config file.
Expand Down
6 changes: 4 additions & 2 deletions lib/pbench/test/unit/server/test_endpoint_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ def check_config(self, client, server_config, host, my_headers={}):
uri = urljoin(host, uri_prefix)
auth_realm = server_config.get("authentication", "realm")
auth_issuer = server_config.get("authentication", "server_url")
auth_client = server_config.get("authentication", "client")
auth_secret = server_config.get("authentication", "secret")
expected_results = {
"authentication": {
"realm": auth_realm,
"client": server_config.get("authentication", "client"),
"client": auth_client,
"issuer": auth_issuer,
"secret": "",
"secret": auth_secret,
},
"identification": f"Pbench server {server_config.COMMIT_ID}",
"api": {
Expand Down
1 change: 0 additions & 1 deletion server/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ install-bin:

install-lib:
${COPY} lib ${DESTDIR}
${RM} ${DESTDIR}/lib/config/nginx.conf.example

clean:
${RM} -rf ${DESTDIR}
141 changes: 141 additions & 0 deletions server/lib/config/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
#+
# Nginx configuration for the Pbench Server.
#-

user nginx;
worker_processes auto;
pid /run/nginx.pid;

# All nginx error logs flow through syslog.
error_log syslog:server=unix:/dev/log,facility=local5,tag=nginx,nohostname info;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
worker_connections 1024;
}

http {
log_format main escape=json '@cee:{"nginx":{"v0":{'
'"body_bytes_sent": $body_bytes_sent, '
'"bytes_sent": $bytes_sent, '
'"connection": $connection, '
'"connection_requests": $connection_requests, '
'"http": {'
'"referer": "$http_referer", '
'"user_agent": "$http_user_agent", '
'"x_forwarded_for": "$http_x_forwarded_for"'
'}, '
'"msec": $msec, '
'"pipe": "$pipe", '
'"remote": {'
'"addr": "$remote_addr", '
'"port": "$remote_port", '
'"user": "$remote_user"'
'}, '
'"request": {'
'"args": "$args", '
'"length": $request_length, '
'"method": "$request_method", '
'"raw": "$request", '
'"time": $request_time, '
'"uri": "$uri"'
'}, '
'"server": {'
'"name": "$server_name", '
'"port": "$server_port"'
'}, '
'"status": $status, '
'"time": "$time_iso8601", '
'"upstream": {'
'"connect_time": "$upstream_connect_time", '
'"header_time": "$upstream_header_time", '
'"response_time": "$upstream_response_time"'
'}'
'}}}';

# All nginx access logs flow through syslog as well.
access_log syslog:server=unix:/dev/log,facility=local6,tag=nginx,severity=info,nohostname main;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;

include /etc/nginx/mime.types;
default_type application/octet-stream;

server {
listen 8080;
listen [::]:8080;
server_name _;
root /srv/pbench/public_html;
index index.html;

error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
error_page 597 @maintenance;

location @maintenance {
rewrite ^(.*)$ /maintenance.json break;
}

location = /404.html {
internal;
}

location = /50x.html {
internal;
}

location /api {
if (-f $document_root/maintenance.json) {
# If the file /srv/pbench/public_html/maintenance.json is
# present, then a response code of 597 will be returned,
# indicating the Pbench Server is under maintenance. The
# error_page definition above, combined with the @maintenance
# internal location, means that the content of the
# maintenance.json file will be used as the body of the message.
# This allows the SRE to update the maintenance JSON response
# with an appropriate message.
return 597;
}

proxy_pass http://127.0.0.1:8001;
proxy_redirect off;
proxy_connect_timeout 20s;
proxy_read_timeout 120s;
proxy_buffering on;
proxy_buffers 512 4k;
proxy_request_buffering on;
proxy_http_version 1.1;

proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;

client_max_body_size 10G;
}

location /dashboard {
# See if the URI exists, as a file or as a directory, under
# /srv/pbench/public_html and serve that. If it doesn't, just serve
# /dashboard/index.html.
try_files $uri $uri/ /dashboard/index.html;
}

location /static/ {
# Serve the legacy web server files that support the agent generated
# HTML pages.
root /opt/pbench-server/html;
}

location / {
# Serve all other paths requested out of /srv/pbench/public_html/.
autoindex on;
autoindex_localtime off;
}
}
}
28 changes: 0 additions & 28 deletions server/lib/config/nginx.conf.example

This file was deleted.

Loading