diff --git a/.mkdkr b/.mkdkr index fc33b5b..5a73a7f 100755 --- a/.mkdkr +++ b/.mkdkr @@ -272,6 +272,8 @@ _job_destroy() { rm "${_MKDKR_TMP_DIR}/${MKDKR_JOB_NAME}.log" fi fi + + docker network rm "network_${MKDKR_JOB_NAME}" _pretty "orange" "\ncompleted:" times } @@ -285,6 +287,18 @@ _exit_handler() { fi } +_network_create() { + _NETWORK_EXIST="$(docker network ls | awk '{ print $2 }' | grep network_${MKDKR_JOB_NAME})" + if [ ! "${_NETWORK_EXIST}" ]; then + _pretty "orange" "network: network_${MKDKR_JOB_NAME}" + docker network create "network_${MKDKR_JOB_NAME}" + fi +} + +slug() { + echo "${1}" | sed -E 's/:|\.|\/|-/_/g' +} + instance:() { OLDIFS=$IFS IFS='⠀' # Braille Pattern Blank (U+2800) @@ -292,20 +306,16 @@ instance:() { ARGS="${*:2}" _remove_running_job + _network_create _pretty "cyan" "\ninstance: ${IMAGE} ${ARGS[*]}" - SERVICE=$(_image "service_${MKDKR_JOB_NAME}" | sed 's/:.*//g;s/\//_/g') - if [ "${SERVICE}" != "" ]; then - SERVICES=(--link "service_${MKDKR_JOB_NAME}:${SERVICE}") - fi - docker run --rm -d \ -v "${PWD}":"${PWD}" \ --workdir "${PWD}" \ --entrypoint "" \ + --network "network_${MKDKR_JOB_NAME}" \ $ARGS \ - ${SERVICES[@]} \ --name "job_${MKDKR_JOB_NAME}" \ "${IMAGE}" sleep "${MKDKR_TTL:-3600}" >&2 @@ -320,14 +330,28 @@ service:() { ARGS="${*:2}" _remove_running_job + _network_create _pretty "cyan" "\nservice: ${IMAGE} ${ARGS[*]}" + NETWORK_ALIAS="$(slug $IMAGE)" + _pretty "cyan" "network alias: ${NETWORK_ALIAS}" + + SERVICE_COUNT="$(docker ps | grep -cE 'service_.*'${MKDKR_JOB_NAME})" + + if [ "$SERVICE_COUNT" != "0" ]; then + SERVICE_COUNT="${SERVICE_COUNT}_" + else + SERVICE_COUNT="" + fi + docker run --rm -d \ -v "${PWD}":"${PWD}" \ --workdir "${PWD}" \ + --network "network_${MKDKR_JOB_NAME}" \ + --network-alias "$NETWORK_ALIAS" \ $ARGS \ - --name "service_${MKDKR_JOB_NAME}" \ + --name "service_${SERVICE_COUNT}${MKDKR_JOB_NAME}" \ "${IMAGE}" >&2 _exit_handler "$?" @@ -341,21 +365,17 @@ dind:() { ARGS="${*:2}" _remove_running_job + _network_create _pretty "cyan" "\ndind: ${IMAGE} ${ARGS[*]}" - SERVICE=$(_image "service_${MKDKR_JOB_NAME}" | sed 's/:.*//g;s/\//_/g') - if [ "${SERVICE}" != "" ]; then - SERVICES=(--link "service_${MKDKR_JOB_NAME}:${SERVICE}") - fi - docker run --rm -d \ -v "${PWD}":"${PWD}" \ --workdir "${PWD}" \ --entrypoint "" \ + --network "network_${MKDKR_JOB_NAME}" \ $ARGS \ --privileged -v /var/run/docker.sock:/var/run/docker.sock \ - ${SERVICES[@]} \ --name "job_${MKDKR_JOB_NAME}" \ "${IMAGE}" sleep "${MKDKR_TTL:-3600}" >&2 diff --git a/Makefile b/Makefile index dec297a..8f69905 100644 --- a/Makefile +++ b/Makefile @@ -79,8 +79,9 @@ examples.simple: make --silent -f examples/simple.mk multi-images examples.service: - make --silent -f examples/service.mk service make --silent -f examples/service.mk link + make --silent -f examples/service.mk service + make --silent -f examples/service.mk multiply examples.dind: make --silent -f examples/dind.mk dind diff --git a/README.md b/README.md index 64c3c6e..d9aea81 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,8 @@ Table of contents * [Implicit](#implicit) * [mkdkr.csv](#mkdkr.csv) * [Collection](#collection) +* [Helpers](#helpers) + * [slug](#slug) * [Examples](#examples) * [Simple](#simple) * [Service](#service) @@ -153,7 +155,7 @@ mkdkr-job: ## instance: -Create a docker container, without special privileges. +Create docker containers, without special privileges. ```Makefile my-instance: @@ -173,7 +175,7 @@ my-instance: ## service: -Create a docker container in detached mode. Useful to bring up a required service for a job, like a webserver or a database. +Create a docker container in detached mode. Useful to bring up a required service for a job, like a webserver or database. ```Makefile my-service: @@ -181,6 +183,30 @@ my-service: service: nginx # up a nginx instance: alpine ``` +Is possible start more than one service. + +```Makefile +multi-service: + @$(dkr) + service: mysql + service: redis + instance: node:12 + run: npm install + run: npm test +``` + +> \* Instance and services are connected in same network
+> \*\* The name of service is the same of image name with safe values + +| Image Name | Network Name | +|----------------------------|----------------------------| +| nginx | nginx | +| nginx:1.2 | nginx_1_2 | +| redis:3 | redis_3 | +| project/apache_1.2 | project_apache_1_2 | +| registry/my/service:latest | registry_my_service_latest | + +> replace role `'s/:|\.|\/|-/_/g'` **Parameters:** @@ -323,6 +349,26 @@ The file contains four values per line in following order > Small collection, use it as example +# Helpers + +A set of small functions to common pipelines process. + +## slug + +Replace unsafe values from a string. + +- safe for docker +- safe for network domain + +```shell +slug "my/unsafe/v1.0.0:string" +# "my_unsafe_v1_0_0_0_string" +``` + +Usage example: + +[service: multiply](examples/service.mk) + # Examples ## Simple diff --git a/examples/service.mk b/examples/service.mk index 4faa7a3..ffaa54c 100644 --- a/examples/service.mk +++ b/examples/service.mk @@ -1,13 +1,13 @@ include $(shell bash .mkdkr init) -service: +link: @$(dkr) service: nginx instance: alpine --link service_$$MKDKR_JOB_NAME:nginx run: apk add curl run: curl -s nginx -link: +service: @$(dkr) service: nginx instance: alpine @@ -17,3 +17,16 @@ link: run: apt-get update run: apt-get install curl -y run: curl -s nginx + +multiply: + @$(dkr) + service: nginx + service: httpd + service: httpd:2.4 + service: docker.io/bitnami/nginx:latest + instance: alpine + run: apk add curl + run: curl -s nginx + run: curl -s httpd + run: curl -s httpd_2_4 + run: curl -s $$(slug docker.io/bitnami/nginx:latest):8080 diff --git a/test/unit_create_instance b/test/unit_create_instance index c7aca3c..1914d4e 100755 --- a/test/unit_create_instance +++ b/test/unit_create_instance @@ -7,7 +7,7 @@ _helper_instance() { assertEquals "$(docker inspect ${1}_${MKDKR_JOB_NAME} | jq .[0].Config.Cmd[0])" "${3}" [[ "$?" == "0" ]] && - _pretty "light_purple" "cmd is ${2} [ OK ]" + _pretty "light_purple" "cmd is ${3} [ OK ]" assertEquals "$(docker inspect ${1}_${MKDKR_JOB_NAME} | jq .[0].Config.Image)" "${2}" [[ "$?" == "0" ]] && @@ -128,13 +128,17 @@ test_test_mkdkr_create_service_and_job() { _helper_instance "job" '"alpine"' '"sleep"' - assertNotEquals "$(docker inspect job_${MKDKR_JOB_NAME} | jq .[0].HostConfig.Links[0])" 'null' + _JOB_NETWORK="$(docker inspect service_${MKDKR_JOB_NAME} | jq '.[0].NetworkSettings.Networks' | jq -r 'keys[0]')" + _SERVICE_NETWORK="$(docker inspect service_${MKDKR_JOB_NAME} | jq '.[0].NetworkSettings.Networks' | jq -r 'keys[0]')" + _SERVICE_NETWORK_ALIAS=$(docker inspect service_${MKDKR_JOB_NAME} | jq -r '.[0].NetworkSettings.Networks["'$_SERVICE_NETWORK'"].Aliases[0]') + + assertEquals "$_JOB_NETWORK" "$_SERVICE_NETWORK" [[ "$?" == "0" ]] && - _pretty "light_purple" "linked with service [ OK ]" + _pretty "light_purple" "job and service connected at same network [ OK ]" - assertContains "$(docker inspect job_${MKDKR_JOB_NAME} | jq .[0].HostConfig.Links[0])" "nginx" + assertEquals "$_SERVICE_NETWORK_ALIAS" "nginx" [[ "$?" == "0" ]] && - _pretty "light_purple" "alias linked name [ OK ]" + _pretty "light_purple" "service alias name [ OK ]" _job_destroy @@ -142,6 +146,65 @@ test_test_mkdkr_create_service_and_job() { } +test_test_mkdkr_create_multi_service_and_job() { + # shellcheck disable=SC1091 + source .mkdkr + unset MKDKR_JOB_NAME + + NAME="my_service" + _job_uniq_name "${NAME}" + + service: nginx + _helper_instance "service" '"nginx"' '"nginx"' + + service: httpd + _helper_instance "service_1" '"httpd"' '"httpd-foreground"' + + service: httpd:2.4 + _helper_instance "service_2" '"httpd:2.4"' '"httpd-foreground"' + + instance: alpine + + _helper_instance "job" '"alpine"' '"sleep"' + + _JOB_NETWORK="$(docker inspect service_${MKDKR_JOB_NAME} | jq '.[0].NetworkSettings.Networks' | jq -r 'keys[0]')" + _SERVICE_NETWORK="$(docker inspect service_${MKDKR_JOB_NAME} | jq '.[0].NetworkSettings.Networks' | jq -r 'keys[0]')" + _SERVICE_NETWORK_ALIAS=$(docker inspect service_${MKDKR_JOB_NAME} | jq -r '.[0].NetworkSettings.Networks["'$_SERVICE_NETWORK'"].Aliases[0]') + _SERVICE_NETWORK_1="$(docker inspect service_1_${MKDKR_JOB_NAME} | jq '.[0].NetworkSettings.Networks' | jq -r 'keys[0]')" + _SERVICE_NETWORK_ALIAS_1=$(docker inspect service_1_${MKDKR_JOB_NAME} | jq -r '.[0].NetworkSettings.Networks["'$_SERVICE_NETWORK'"].Aliases[0]') + _SERVICE_NETWORK_2="$(docker inspect service_2_${MKDKR_JOB_NAME} | jq '.[0].NetworkSettings.Networks' | jq -r 'keys[0]')" + _SERVICE_NETWORK_ALIAS_2=$(docker inspect service_2_${MKDKR_JOB_NAME} | jq -r '.[0].NetworkSettings.Networks["'$_SERVICE_NETWORK'"].Aliases[0]') + + assertEquals "$_JOB_NETWORK" "$_SERVICE_NETWORK" + [[ "$?" == "0" ]] && + _pretty "light_purple" "job and service (nginx) connected at same network [ OK ]" + + assertEquals "$_SERVICE_NETWORK_ALIAS" "nginx" + [[ "$?" == "0" ]] && + _pretty "light_purple" "service (nginx) alias name [ OK ]" + + assertEquals "$_JOB_NETWORK" "$_SERVICE_NETWORK_1" + [[ "$?" == "0" ]] && + _pretty "light_purple" "job and service (httpd) connected at same network [ OK ]" + + assertEquals "$_SERVICE_NETWORK_ALIAS_1" "httpd" + [[ "$?" == "0" ]] && + _pretty "light_purple" "service (httpd) alias name [ OK ]" + + assertEquals "$_JOB_NETWORK" "$_SERVICE_NETWORK_2" + [[ "$?" == "0" ]] && + _pretty "light_purple" "job and service (httpd 2.4) connected at same network [ OK ]" + + assertEquals "$_SERVICE_NETWORK_ALIAS_2" "httpd_2_4" + [[ "$?" == "0" ]] && + _pretty "light_purple" "service (httpd 2.4) alias name [ OK ]" + + _job_destroy + + _pretty "light_green" "\nRan 26 assert(s)\n" + +} + test_mkdkr_create_instance_with_parameters() { # shellcheck disable=SC1091 source .mkdkr