add tests and a dynamic config section generator
This commit is contained in:
parent
f41f9d25d2
commit
5f5ce51ce7
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.yaml
|
122
gen_cfg_section.py
Normal file
122
gen_cfg_section.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
def parse_cli_args():
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.ArgumentDefaultsHelpFormatter
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'api_versions',
|
||||||
|
nargs='+',
|
||||||
|
help=(
|
||||||
|
'Docker API version(s) to support. ' +
|
||||||
|
'If exactly two versions are passed, ' +
|
||||||
|
'it will act as a range.'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--yaml-dir',
|
||||||
|
help='Save and load Swagger YAML files from this directory'
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--add-comments',
|
||||||
|
action='store_true',
|
||||||
|
help='Add comments to the haproxy.cfg output'
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_api_versions(api_versions):
|
||||||
|
if len(api_versions) == 2:
|
||||||
|
min_ver = int(float(api_versions[0]) * 100)
|
||||||
|
max_ver = int(float(api_versions[1]) * 100)
|
||||||
|
assert min_ver < max_ver
|
||||||
|
return [f'{ver / 100.0:.2f}' for ver in range(min_ver, max_ver + 1)]
|
||||||
|
return api_versions
|
||||||
|
|
||||||
|
|
||||||
|
def create_cfg_line(endpoint):
|
||||||
|
return r' http-request allow if {{ path,url_dec -m reg -i ^(/v[\d\.]+)?/{} }} {{ env({}) -m bool }}'.format(
|
||||||
|
endpoint, re.sub(r'[^A-Z]', '', endpoint.upper())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_cfg_comment(endpoint, api_versions):
|
||||||
|
version_nums = [float(ver) for ver in api_versions]
|
||||||
|
return ' # /{} first seen: v{:.2f}, last seen: v{:.2f}'.format(
|
||||||
|
endpoint,
|
||||||
|
min(version_nums),
|
||||||
|
max(version_nums),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_base_endpoints(swagger):
|
||||||
|
return set(
|
||||||
|
path_name.split('/')[1]
|
||||||
|
for path_name in swagger['paths'].keys()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def load_swagger_yaml(api_version, yaml_dir=None):
|
||||||
|
|
||||||
|
if yaml_dir:
|
||||||
|
yaml_path = os.path.join(
|
||||||
|
cli_args.yaml_dir,
|
||||||
|
f"docker_v{api_version.replace('.', '_')}.yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
if os.path.isfile(yaml_path):
|
||||||
|
print(f'Reading file {yaml_path!r}...')
|
||||||
|
with open(yaml_path) as fd:
|
||||||
|
return yaml.safe_load(fd)
|
||||||
|
|
||||||
|
swagger_url = 'https://docs.docker.com/engine/api/v{}/swagger.yaml'.format(
|
||||||
|
api_version
|
||||||
|
)
|
||||||
|
|
||||||
|
print(f'Downloading Docker API version {api_version}...')
|
||||||
|
with urlopen(swagger_url) as fd:
|
||||||
|
swagger = yaml.safe_load(fd)
|
||||||
|
|
||||||
|
if yaml_dir:
|
||||||
|
print(f'Writing file {yaml_path!r}...')
|
||||||
|
with open(yaml_path, 'w') as fd:
|
||||||
|
yaml.dump(swagger, fd)
|
||||||
|
|
||||||
|
return swagger
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
cli_args = parse_cli_args()
|
||||||
|
|
||||||
|
api_versions = parse_api_versions(cli_args.api_versions)
|
||||||
|
|
||||||
|
if cli_args.yaml_dir:
|
||||||
|
os.makedirs(cli_args.yaml_dir, exist_ok=True)
|
||||||
|
|
||||||
|
swaggers = {}
|
||||||
|
for api_version in api_versions:
|
||||||
|
swaggers[api_version] = load_swagger_yaml(
|
||||||
|
api_version,
|
||||||
|
yaml_dir=cli_args.yaml_dir
|
||||||
|
)
|
||||||
|
|
||||||
|
all_base_endpoints = {}
|
||||||
|
for api_version, swagger in swaggers.items():
|
||||||
|
for endpoint in get_base_endpoints(swagger):
|
||||||
|
if endpoint in all_base_endpoints:
|
||||||
|
all_base_endpoints[endpoint].append(api_version)
|
||||||
|
else:
|
||||||
|
all_base_endpoints[endpoint] = [api_version]
|
||||||
|
|
||||||
|
for base_endpoint, api_versions in sorted(all_base_endpoints.items()):
|
||||||
|
if cli_args.add_comments:
|
||||||
|
print()
|
||||||
|
print(create_cfg_comment(base_endpoint, api_versions))
|
||||||
|
print(create_cfg_line(base_endpoint))
|
84
run_tests.sh
Executable file
84
run_tests.sh
Executable file
@ -0,0 +1,84 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
proxy_container=docksockprox_test
|
||||||
|
socket_proxy=127.0.0.1:2375
|
||||||
|
|
||||||
|
start_proxy() {
|
||||||
|
echo "Starting $proxy_container with args: ${*}..."
|
||||||
|
docker run -d --name "$proxy_container" \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||||
|
-p "${socket_proxy}:2375" \
|
||||||
|
"$@" \
|
||||||
|
tecnativa/docker-socket-proxy &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_proxy() {
|
||||||
|
echo "Removing ${proxy_container}..."
|
||||||
|
docker rm -f "$proxy_container" &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
docker_with_proxy() {
|
||||||
|
docker --host "$socket_proxy" "$@" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
assert() {
|
||||||
|
assertion=$1
|
||||||
|
shift 1
|
||||||
|
if docker_with_proxy "$@" | grep -qi 'forbidden'; then
|
||||||
|
result='forbidden'
|
||||||
|
else
|
||||||
|
result='allowed'
|
||||||
|
fi
|
||||||
|
if [ "$assertion" == "$result" ]; then
|
||||||
|
printf '%s' 'PASS'
|
||||||
|
else
|
||||||
|
printf '%s' 'FAIL'
|
||||||
|
fi
|
||||||
|
echo " | assert 'docker $*' is $assertion"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
trap delete_proxy EXIT
|
||||||
|
|
||||||
|
start_proxy
|
||||||
|
assert allowed version
|
||||||
|
assert forbidden run --rm alpine
|
||||||
|
assert forbidden pull alpine
|
||||||
|
assert forbidden logs "$proxy_container"
|
||||||
|
assert forbidden wait "$proxy_container"
|
||||||
|
assert forbidden rm -f "$proxy_container"
|
||||||
|
assert forbidden restart "$proxy_container"
|
||||||
|
assert forbidden network ls
|
||||||
|
assert forbidden config ls
|
||||||
|
assert forbidden service ls
|
||||||
|
assert forbidden stack ls
|
||||||
|
assert forbidden secret ls
|
||||||
|
assert forbidden plugin ls
|
||||||
|
assert forbidden info
|
||||||
|
assert forbidden system info
|
||||||
|
assert forbidden build .
|
||||||
|
assert forbidden swarm init
|
||||||
|
|
||||||
|
delete_proxy
|
||||||
|
start_proxy -e CONTAINERS=1
|
||||||
|
assert allowed logs "$proxy_container"
|
||||||
|
assert allowed inspect "$proxy_container"
|
||||||
|
assert forbidden wait "$proxy_container"
|
||||||
|
assert forbidden run --rm alpine
|
||||||
|
assert forbidden rm -f "$proxy_container"
|
||||||
|
assert forbidden restart "$proxy_container"
|
||||||
|
|
||||||
|
delete_proxy
|
||||||
|
start_proxy -e POST=1
|
||||||
|
assert forbidden rm -f "$proxy_container"
|
||||||
|
assert forbidden pull alpine
|
||||||
|
assert forbidden run --rm alpine
|
||||||
|
assert forbidden network create foobar
|
||||||
|
|
||||||
|
delete_proxy
|
||||||
|
start_proxy -e NETWORKS=1 -e POST=1
|
||||||
|
assert allowed network ls
|
||||||
|
assert allowed network create foo
|
||||||
|
assert allowed network rm foo
|
Loading…
Reference in New Issue
Block a user