HTTP/1 mock server built with Python Flask and supported by docker/kubernetes.
This image is already available at docker hub
for every repository tag
, and also for master as latest
:
$ docker pull testillano/h1mock:<tag>
You could also build it using the script ./build.sh
located at project root:
./build.sh
This image is built with ./Dockerfile
.
h1mock
is delivered in a helm
chart called h1mock
(./helm/h1mock
) so you may integrate it in your regular helm
chart deployments by just adding a few artifacts.
-
Add the project's helm repository with alias
erthelm
:helm repo add erthelm https://testillano.github.io/helm
-
Add one dependency to your
Chart.yaml
file per each service you want to mock withh1mock
service (use alias when two or more dependencies are included).dependencies: - name: h1mock version: 1.0.0 repository: alias:erthelm alias: server1 - name: h1mock version: 1.0.0 repository: alias:erthelm alias: server2
-
Refer to
h1mock
values through the corresponding dependency alias, for example.Values.h1server.image
to access process repository and tag.
The application is built on demand from pieces of source code which define the server behavior. The implementation must follow the flask API referring to an app
application (this instance name is mandatory, no other can be used).
The needed code only requires the definition of the URL rules inside a function which must be called registerRules()
and also the functions required by those rules. For example:
def registerRules():
app.add_url_rule("/foo", "foo_get", view_func=foo_get, methods=['GET'])
app.add_url_rule("/bar", "bar_post", view_func=bar_post, methods=['POST'])
def foo_get:
# <here your code>
def bar_post:
# <here your code>
Summing up, these are the requirements:
-
Flask application instance:
app
. -
Mandatory rules registration definition:
registerRules()
. -
No need to re-import those already available:
os
,logging
and of course,flask
(Flask, Blueprint, jsonify, request). -
Also, you have available the flask API status codes.
-
The piece of source code must not be indented on first level (definitions), and although it is not mandatory, 2-spaces are recommended for inner tabs.
-
Files within your deployed
configmap
shall be accessible under directory path/app/provision
(or justprovision
as/app
is the mock image working directory). This is useful if you consider to load auxiliary files (json or any other format) from your mock source code implementation.
More examples could be found at ./examples
directory.
To configure the service, that source code could be provisioned in two ways:
The chart value service.provisionsDir
could be used to specify a directory path where provision files are installed at deployment time. From these files, the one named 'initial' will be used as the working provision after deployment (symlink it to any of them or just name it so), and the rest are available for further optional activation operations (touch). A default 'initial' provision (which always responds status code 404 Not Found
with an html
response containing a help hyper link) will be created as fall back when no initial provision is found during deployment.
Provisions must be accessible from helm chart
root level and a ConfigMap
must be created for them using the h1mock.configmap
function from h1mock
chart templates/_helpers.tpl
. For example:
$> tree examples
examples
├── default
├── foo-bar
├── healthz
└── initial -> default
$> cd helm/h1mock
$> ln -sf ../../examples
$> cat << EOF > templates/provision-config.yaml
{{- include "h1mock.configmap" ( list $ $.Values ) }}
EOF
$> kubectl create namespace h1m
$> helm install h1m -n h1m . --set service.provisionsDir=examples --wait
$> POD=$(kubectl get pods -n h1m --no-headers | awk '{ if ($3 == "Running") print $1 }')
$> kubectl exec -it -n h1m ${POD} -- sh -c "ls /app/provision"
default foo-bar healthz initial
$> helm delete -n h1m h1m
$> kubectl delete namespace h1m
All these steps have been done in component test chart (./helm/ct-h1mock
) which has a ConfigMap
already created and also a specific provisions directory enabled at values.yaml
file.
This can be done in two main ways:
- Through
kubectl cp
of the source file intoh1mock
container's path/app/provision
. The utilityinotify
will detect the creation event to upgrade the server source activating the new behavior. You could send different server definitions and they will be loaded on demand (this is thanks to flask debug mode option). You could even reactivate any of the available provision files within the docker internal directory, by mean touching them by meankubectl exec
. - Through an administrative service which is launched on value
service.admin_port
(8074 by default). These are the supported methods of this control API:- POST
/app/v1/provision/<file basename>
with source code sent over the request body in plain text. This operation always receives status code201 Created
, but possible crash of container's application may be provoked by a bad design of the content sent (in that case, the 'initial' provision will be restored). - GET
/app/v1/provision/<file basename>
, to "touch" and so reactivate an existing provision. This also receives200 OK
, even when the touched provision was missing: in that case, an empty provision is created and this shall provoke the crash, being a rude way to reboot the container and then, restore the initial configuration. - There is also a keep-alive for administration interface, via GET
/healthz
. This could be used to check that the provision system throughHTTP/1
interface is available.
- POST
To deploy the main micro service chart, execute the following:
./deploy.sh
Once installed, a template notes will be shown. Follow the instructions to execute manually a basic check.
The following script will deploy the component test chart and then start the pytest framework:
./ct/test.sh
External provision by mean kubectl
commands is tested too, but using bash
instead of pytest
:
./ct/ktest.sh