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