#!/usr/bin/env bash-shlib # -*- mode: shell-script -*- include shunit depends sed grep git mkdir readlink export -f matches export grep tmp=/tmp tprog="../bin/compose-core" tprog=$(readlink -f $tprog) export PATH=".:$PATH" short_tprog=$(basename "$tprog") ## ## Convenience function ## init_test() { test_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX) cd "$test_tmpdir" export CACHEDIR="$test_tmpdir/.cache" export VARDIR="$test_tmpdir/.var" export COMPOSE_DISABLE_DOCKER_COMPOSE_STORE="1" mkdir -p "$CACHEDIR" } tear_test() { rm -rf "$test_tmpdir" } ## ## Tests ## ## # Checking arguments test_calling_sourcing() { assert_list < $test_tmpdir/testcharm/metadata.yml EOF2 . "$tprog" _setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" expected='\ labels: - compose.charm=testcharm' [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } ## -- volumes export CHARM_STORE=$test_tmpdir export CONFIGSTORE=/tmp/CONFIG export DATASTORE=/tmp/DATA mkdir -p $test_tmpdir/testcharm cat < $test_tmpdir/testcharm/metadata.yml data-resources: - /a config-resources: - /b host-resources: - /tmp:/tmp EOF2 . "$tprog" _setup_state_dir out=\$(get_docker_compose_mixin_from_metadata testcharm) || exit 1 expected="\ labels: - compose.charm=testcharm volumes: - /tmp/DATA/testcharm/a:/a:rw - /tmp/CONFIG/testcharm/b:/b:rw - /tmp:/tmp:rw" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } ## -- docker-compose export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm cat < $test_tmpdir/testcharm/metadata.yml docker-compose: volumes: - /any:/vol entrypoint: any EOF2 . "$tprog" _setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" || exit 1 expected="\ entrypoint: any labels: - compose.charm=testcharm volumes: - /any:/vol" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } ## -- image export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm cat < $test_tmpdir/testcharm/metadata.yml docker-image: toto EOF2 . "$tprog" _setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" || exit 1 expected="\ image: toto labels: - compose.charm=testcharm" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } ## -- build export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm/build cat < $test_tmpdir/testcharm/metadata.yml # XXX new content to invalidate cache EOF2 . "$tprog" _setup_state_dir out="\$(get_docker_compose_mixin_from_metadata testcharm)" || exit 1 expected="\ build: $test_tmpdir/testcharm/build labels: - compose.charm=testcharm" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } ## -- subordinate with image export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm cat < $test_tmpdir/testcharm/metadata.yml subordinate: true docker-image: toto EOF2 . "$tprog" _setup_state_dir ! get_docker_compose_mixin_from_metadata testcharm ## -- subordinate with build subdir export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/testcharm/build cat < $test_tmpdir/testcharm/metadata.yml subordinate: true EOF2 . "$tprog" _setup_state_dir ! get_docker_compose_mixin_from_metadata testcharm EOF tear_test } function test_merge_yaml { init_test assert_list < $test_tmpdir/compose.yml toto: charm: www blabla: xxx EOF2 . "$tprog" _setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml out="\$(get_compose_service_def toto)" test "\$out" == "charm: www blabla: xxx" || { echo -e "** get_compose_service_def toto:\n\$out" exit 1 } ## -- Addition of default charm export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/www cat < $test_tmpdir/compose.yml www: blabla: xxx EOF2 . "$tprog" _setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml test "\$(get_compose_service_def www)" == "blabla: xxx charm: www" EOF } ## ## ## function test_get_master_service_for_service() { init_test assert_list < $test_tmpdir/www/metadata.yml EOF2 . "$tprog" _setup_state_dir get_all_relations www >/dev/null || exit 3 test "\$(get_master_service_for_service www)" == "www" ## -- subordinate export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} touch $test_tmpdir/mysql/metadata.yml cat < $test_tmpdir/www/metadata.yml subordinate: true uses: a-name-relation: constraint: required scope: container EOF2 cat < $test_tmpdir/compose.yml www: charm: www relations: a-name-relation: mysql: label: value EOF2 . "$tprog" _setup_state_dir get_all_relations www >/dev/null || exit 3 COMPOSE_YML_FILE=$test_tmpdir/compose.yml test "\$(get_master_service_for_service www)" == "mysql" EOF } ## ## ## function test_get_docker_compose_service_mixin() { init_test assert_list < $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2 . "$tprog" _setup_state_dir get_all_relations www >/dev/null || exit 3 out=\$(_get_docker_compose_service_mixin www | shyaml get-value www.volumes) [[ "\$out" == "\ - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" ]] || { echo -e "** _get_docker_compose_service_mixin www:\n\$out"; exit 1 } ## -- Simple (compose, but no subordinate) export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2 touch $test_tmpdir/mysql/metadata.yml cat < $test_tmpdir/compose.yml www: charm: www relations: a-name-relation: mysql: label: value EOF2 . "$tprog" _setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml get_all_relations www >/dev/null || exit 3 out="\$(_get_docker_compose_service_mixin www)" || exit 1 [ "\$out" == "www: labels: - compose.service=www - compose.master-service=www - compose.project=\$(basename "$test_tmpdir") - compose.charm=www links: - mysql volumes: - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" ] || { echo -e "OUT:\n\$out" exit 1 } ## -- compose, subordinate export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b uses: a-name-relation: constraint: required scope: container EOF2 cat < $test_tmpdir/compose.yml www: charm: www relations: a-name-relation: mysql: label: value EOF2 . "$tprog" _setup_state_dir COMPOSE_YML_FILE=$test_tmpdir/compose.yml get_all_relations www >/dev/null || exit 3 out="\$(_get_docker_compose_service_mixin www)" || exit 1 expected="mysql: labels: - compose.service=www - compose.master-service=mysql - compose.project=$(basename "$test_tmpdir") - compose.charm=www volumes: - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" [ "\$out" == "\$expected" ] || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } EOF } function test_get_docker_compose { init_test assert_list < $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2 . "$tprog" _setup_state_dir get_all_relations www >/dev/null || exit 3 out=\$(get_docker_compose www) echo "OUT:" echo "\$out" out=\$(echo "\$out" | shyaml get-value services.www.volumes) echo "OUT volumes:" echo "\$out" test "\$out" == "\\ - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" ## -- simple with docker-compose export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml data-resources: - /tmp/a config-resources: - /tmp/b EOF2 cat < $test_tmpdir/mysql/metadata.yml data-resources: - /tmp/c config-resources: - /tmp/d EOF2 cat < $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata EOF2 . "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir get_all_relations web_site >/dev/null || exit 3 out=\$(get_docker_compose www) || exit 4 out=\$(printf "%s" "\$out" | shyaml get-value services.www.volumes) || exit 5 test "\$out" == "\\ - /www/tmp/a:/tmp/a:rw - /www/tmp/b:/tmp/b:rw" || { echo -e "** get_docker_compose www:\n\$out" exit 1 } out=\$(get_docker_compose_links web_site) || exit 6 out=\$(printf "%s" "\$out" | shyaml get-value web_site.links) || exit 7 test "\$out" == "- mysql" || { echo -e "** get_docker_compose_links web_site:\n\$out" exit 1 } out=\$(get_docker_compose web_site | shyaml get-value services) expected="\ mysql: labels: - compose.service=mysql - compose.master-service=mysql - compose.project=$(basename "$test_tmpdir") - compose.charm=mysql volumes: - /mysql/tmp/c:/tmp/c:rw - /mysql/tmp/d:/tmp/d:rw web_site: labels: - compose.service=web_site - compose.master-service=web_site - compose.project=$(basename "$test_tmpdir") - compose.charm=www links: - mysql volumes: - /web_site/tmp/a:/tmp/a:rw - /web_site/tmp/b:/tmp/b:rw" test "\$out" == "\$expected" || { echo -e "** get_docker_compose web_site:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } ## -- subordinate export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b uses: db-connection: constraint: required scope: container EOF2 cat < $test_tmpdir/mysql/metadata.yml data-resources: - /tmp/c config-resources: - /tmp/d EOF2 cat < $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata EOF2 . "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir get_all_relations web_site >/dev/null || exit 3 # should fail because of missing relations ! get_docker_compose www || exit 1 # volumes gets mixed out="\$(get_docker_compose web_site | shyaml get-value services.mysql.volumes)" test "\$out" == "\ - /web_site/tmp/a:/tmp/a:rw - /web_site/tmp/b:/tmp/b:rw - /mysql/tmp/c:/tmp/c:rw - /mysql/tmp/d:/tmp/d:rw" || { echo -e "OUT:\n\$out" exit 1 } ## -- subordinate with complex features export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b uses: db-connection: constraint: required scope: container docker-compose: volumes: - /special-volume-from-www:/special-volume-from-www EOF2 cat < $test_tmpdir/mysql/metadata.yml data-resources: - /tmp/c config-resources: - /tmp/d docker-compose: entrypoint: custom-entrypoint volumes: - /special-volume-from-mysql:/special-volume-from-mysql EOF2 cat < $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata EOF2 . "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir get_all_relations web_site >/dev/null || exit 3 # should fail because of missing relations #! get_docker_compose www || exit 1 # volumes gets mixed out="\$(get_docker_compose web_site | shyaml get-value services.mysql)" expected="\ entrypoint: custom-entrypoint labels: - compose.service=web_site - compose.charm=www - compose.service=mysql - compose.master-service=mysql - compose.project=$(basename "$test_tmpdir") - compose.charm=mysql volumes: - /web_site/tmp/a:/tmp/a:rw - /web_site/tmp/b:/tmp/b:rw - /special-volume-from-www:/special-volume-from-www - /mysql/tmp/c:/tmp/c:rw - /mysql/tmp/d:/tmp/d:rw - /special-volume-from-mysql:/special-volume-from-mysql" test "\$out" == "\$expected" || { echo -e "DIFF:\n\$(diff <(echo "\$out") <(echo "\$expected"))" exit 1 } EOF tear_test } ## XXXvlab: only broken due to Wrap being used for relations # function test_run_service_relations { # init_test # assert_list < $test_tmpdir/www/metadata.yml # data-resources: # - /tmp/a # config-resources: # - /tmp/b # EOF2 # . "$tprog" # _setup_state_dir # echo "Docker Compose:" # get_docker_compose www # echo "Run Service relations:" # _run_service_relation() { # echo "\$FUNCNAME: received $*" # } # out=\$(run_service_relations www) # test -z "\$out" # ## -- simple with docker-compose # export CHARM_STORE=$test_tmpdir # mkdir -p $test_tmpdir/{www,mysql} # cat < $test_tmpdir/www/metadata.yml # data-resources: # - /tmp/a # config-resources: # - /tmp/b # EOF2 # cat < $test_tmpdir/mysql/metadata.yml # data-resources: # - /tmp/c # config-resources: # - /tmp/d # EOF2 # cat < $test_tmpdir/compose.yml # web_site: # charm: www # relations: # db-connection: # mysql: # user: toto # dbname: tata # EOF2 # . "$tprog" # COMPOSE_YML_FILE=$test_tmpdir/compose.yml # _setup_state_dir # _setup_state_dir # echo "Docker Compose:" # get_docker_compose web_site # echo "Run Service relations:" # _run_service_relation() { # echo "\$FUNCNAME \$2 <-- \$1 --> \$3" # } # export -f _run_service_relation # out=\$(run_service_relations www) # test -z "\$out" || exit 1 # out=\$(run_service_relations web_site) # echo "OUT: \$out" # test "\$out" == "_run_service_relation web_site <-- db-connection --> mysql" # ## -- subordinate # export CHARM_STORE=$test_tmpdir # mkdir -p $test_tmpdir/{www,mysql} # cat < $test_tmpdir/www/metadata.yml # subordinate: true # data-resources: # - /tmp/a # config-resources: # - /tmp/b # uses: # db-connection: # constraint: required # scope: container # EOF2 # cat < $test_tmpdir/mysql/metadata.yml # data-resources: # - /tmp/c # config-resources: # - /tmp/d # EOF2 # cat < $test_tmpdir/compose.yml # web_site: # charm: www # relations: # db-connection: # mysql: # user: toto # dbname: tata # EOF2 # . "$tprog" # COMPOSE_YML_FILE=$test_tmpdir/compose.yml # _setup_state_dir # echo "Docker Compose:" # get_docker_compose web_site # echo "Run Service relations:" # _run_service_relation() { # echo "\$FUNCNAME \$2 <-- \$1 --> \$3" # } # export -f _run_service_relation # out=\$(run_service_relations www) # test -z "\$out" || exit 1 # out=\$(run_service_relations web_site) # echo "\$out" # test "\$out" == "_run_service_relation web_site <-- db-connection --> mysql" # EOF # tear_test # } function test_get_docker_compose_2() { init_test assert_list < $test_tmpdir/compose.yml app: charm: app relations: web-proxy: www: user: toto db: mysql EOF2 . "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir get_all_relations app >/dev/null || exit 3 out=\$(get_docker_compose_links "app") test "\$out" == "app: links: - www - mysql" || { echo -e "** get_docker_compose_links:\n\$out"; exit 1 } ## -- reverse-tech-dep export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml provides: web-proxy: tech-dep: reversed EOF2 touch $test_tmpdir/mysql/metadata.yml cat < $test_tmpdir/compose.yml web_site: charm: mysql relations: web-proxy: www: user: toto EOF2 . "$tprog" COMPOSE_YML_FILE=$test_tmpdir/compose.yml _setup_state_dir get_all_relations web_site >/dev/null || exit 3 out=\$(get_charm_relation_def "www" "web-proxy") || exit 1 test "\$out" == "tech-dep: reversed" || { echo -e "** get_charm_relation_def:\n\$out"; exit 1 } out=\$(get_charm_tech_dep_orientation_for_relation "www" "web-proxy") test "\$out" == "reversed" || { echo -e "** get_charm_tech_dep_orientation_for_relation:\n\$out"; exit 1 } out=\$(get_docker_compose_links "web_site") expected="www: links: - web_site" test "\$out" == "\$expected" || { echo -e "** get_docker_compose_links:\n\$out\nExpected:\n\$expected"; exit 1 } out=\$(get_docker_compose web_site | shyaml get-value services.www.links) test "\$out" == "- web_site" || { echo -e "** get_docker_compose:\n\$out"; exit 1 } EOF tear_test } function test_compose_config { init_test export CHARM_STORE=$test_tmpdir mkdir -p $test_tmpdir/{www,mysql} cat < $test_tmpdir/www/metadata.yml subordinate: true data-resources: - /tmp/a config-resources: - /tmp/b uses: db-connection: constraint: required scope: container docker-compose: volumes: - /special-volume-from-www:/special-volume-from-www EOF2 cat < $test_tmpdir/mysql/metadata.yml docker-image: docker.0k.io/mysql data-resources: - /tmp/c config-resources: - /tmp/d docker-compose: entrypoint: custom-entrypoint volumes: - /special-volume-from-mysql:/special-volume-from-mysql EOF2 cat < $test_tmpdir/compose.yml web_site: charm: www relations: db-connection: mysql: user: toto dbname: tata EOF2 assert_list <