├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── ci.yml │ ├── main.yml │ └── shellcheck.yml ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Jenkinsfile ├── LICENSE ├── README.md ├── bin └── pot ├── etc ├── pot │ ├── flavours │ │ ├── dns │ │ ├── dns.sh │ │ ├── fbsd-update.sh │ │ └── slim.sh │ ├── pot.conf.sample │ └── pot.default.conf └── rc.d │ ├── pot │ └── pot_early ├── release.sh ├── share ├── doc │ └── pot │ │ ├── .gitignore │ │ ├── Description.md │ │ ├── Images.md │ │ ├── Installation.md │ │ ├── Makefile │ │ ├── QuickStart.md │ │ ├── Synopsis.md │ │ ├── conf.py │ │ ├── index.md │ │ └── migration.md ├── pot │ ├── add-dep.sh │ ├── clone-fscomp.sh │ ├── clone.sh │ ├── common-flv.sh │ ├── common.sh │ ├── config.sh │ ├── copy-in.sh │ ├── copy-out.sh │ ├── create-base.sh │ ├── create-fscomp.sh │ ├── create-private-bridge.sh │ ├── create.sh │ ├── de-init.sh │ ├── destroy.sh │ ├── exec.sh │ ├── export-ports.sh │ ├── export.sh │ ├── get-attribute.sh │ ├── get-rss.sh │ ├── help.sh │ ├── import.sh │ ├── info.sh │ ├── init.sh │ ├── last-run-stats.sh │ ├── list.sh │ ├── mount-in.sh │ ├── mount-out.sh │ ├── network.sh │ ├── prepare.sh │ ├── prune.sh │ ├── ps.sh │ ├── purge-snapshots.sh │ ├── rename.sh │ ├── revert.sh │ ├── set-attribute.sh │ ├── set-cmd.sh │ ├── set-env.sh │ ├── set-hook.sh │ ├── set-hosts.sh │ ├── set-rss.sh │ ├── set-status.sh │ ├── show.sh │ ├── signal.sh │ ├── snapshot.sh │ ├── start.sh │ ├── stop.sh │ ├── term.sh │ ├── top.sh │ ├── update-config.sh │ ├── version.sh │ └── vnet-start.sh └── zsh │ └── site-functions │ └── _pot └── tests ├── CI ├── resolv.conf-dual ├── resolv.conf-ipv4 ├── resolv.conf-ipv6 └── run.sh ├── add-dep1.sh ├── clone-fscomp1.sh ├── clone1.sh ├── clone2.sh ├── common-flv1.sh ├── common-stub.sh ├── common-zfs1.sh ├── common-zfs2.sh ├── common1.sh ├── common2.sh ├── common4.sh ├── common5.sh ├── common6.sh ├── common7.sh ├── common8.sh ├── conf-stub.sh ├── config1.sh ├── copy-in1.sh ├── copy-out1.sh ├── create-base1.sh ├── create-fscomp1.sh ├── create-private-bridge1.sh ├── create1.sh ├── create2.sh ├── create3.sh ├── destroy1.sh ├── export-ports1.sh ├── export1.sh ├── get-rss1.sh ├── import1.sh ├── info1.sh ├── info2.sh ├── list1.sh ├── list2.sh ├── monitor.sh ├── mount-in1.sh ├── mount-out1.sh ├── network1.sh ├── pipefail-stub.sh ├── ps1.sh ├── rename1.sh ├── rename2.sh ├── rename3.sh ├── rename4.sh ├── revert1.sh ├── set-attr1.sh ├── set-attr2.sh ├── set-cmd1.sh ├── set-env1.sh ├── set-env2.sh ├── set-hook1.sh ├── set-hosts1.sh ├── set-rss1.sh ├── show1.sh ├── shunit ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── doc │ ├── CHANGES-2.1.md │ ├── RELEASE_NOTES-2.1.0.txt │ ├── RELEASE_NOTES-2.1.1.txt │ ├── RELEASE_NOTES-2.1.2.txt │ ├── RELEASE_NOTES-2.1.3.txt │ ├── RELEASE_NOTES-2.1.4.txt │ ├── RELEASE_NOTES-2.1.5.txt │ ├── RELEASE_NOTES-2.1.6.txt │ ├── RELEASE_NOTES-2.1.7.md │ ├── TODO.txt │ ├── contributors.md │ └── design_doc.txt ├── examples │ ├── equality_test.sh │ ├── lineno_test.sh │ ├── math.inc │ ├── math_test.sh │ ├── mkdir_test.sh │ ├── mock_file.sh │ ├── mock_file_test.sh │ ├── party_test.sh │ └── suite_test.sh ├── lib │ ├── shflags │ └── versions ├── shunit2 ├── shunit2_args_test.sh ├── shunit2_asserts_test.sh ├── shunit2_failures_test.sh ├── shunit2_macros_test.sh ├── shunit2_misc_test.sh ├── shunit2_standalone_test.sh ├── shunit2_test_helpers └── test_runner ├── signal1.sh ├── signal2.sh ├── snapshot1.sh ├── start2.sh ├── start3.sh ├── start4.sh ├── stop1.sh ├── term1.sh ├── test-suite.sh ├── top1.sh └── version1.sh /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug you found 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Create the `pot` with this command: '...' 16 | 2. Run this command: '...' 17 | 3. See error 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **System configuration - if possible** 23 | - `/usr/local/etc/pot/pot.conf` 24 | 25 | ** If network related ** 26 | - `cat /etc/pf.conf` 27 | - `potnet show -v` 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: A nice to have 4 | title: '' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the feature you'd like to have** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe potential alternatives or workaround you've considered (if any)** 17 | A clear and concise description of any alternative solutions or workaround you've considered. 18 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Run CI 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: [ github-ci-action ] 6 | # pull_request: 7 | # branches: [ master ] 8 | 9 | jobs: 10 | ci_test_suite: 11 | name: CI test suite 12 | runs-on: ${{ matrix.job.os }} 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | job: 17 | - { os: macos-12 } 18 | release: [ "13.1" ] 19 | steps: 20 | - uses: actions/checkout@v3 21 | - name: Run tests/CI/run.sh 22 | uses: vmactions/freebsd-vm@v0 23 | with: 24 | mem: 8192 25 | usesh: true 26 | copyback: false 27 | prepare: pkg install -y curl gmake potnet freebsd-release-manifests nmap 28 | run: | 29 | ##################################################################################### 30 | ### Prepare, build, and test 31 | ##################################################################################### 32 | ### based on ref: 33 | ### and on ref: 34 | ### * NOTE: All steps need to be run in this block, otherwise, we are operating back 35 | ### on the mac host 36 | set -exo pipefail 37 | # 38 | ### Basic user setup ################################################################ 39 | TEST_USER=tester 40 | TEST_USER_HOME="/opt/$TEST_USER" 41 | REPO_NAME=${GITHUB_WORKSPACE##*/} 42 | WORKSPACE_PARENT="/Users/runner/work/${REPO_NAME}" 43 | WORKSPACE="${WORKSPACE_PARENT}/${REPO_NAME}" 44 | OS_VERSION="$(freebsd-version | awk -F- '{print $1}')" 45 | PUB_INTF="$(netstat -4rn | grep default | awk '{ print $4}')" 46 | ifconfig 47 | # 48 | mkdir -p "$TEST_USER_HOME" 49 | pw adduser -n "$TEST_USER" -d "$TEST_USER_HOME" -c "Tester" -h - 50 | chown -R "$TEST_USER":"$TEST_USER" "$TEST_USER_HOME" 51 | chown -R "$TEST_USER":"$TEST_USER" "/$WORKSPACE_PARENT"/ 52 | whoami 53 | # 54 | ### Output some information about the environment ################################## 55 | # environment 56 | echo "## environment" 57 | env | sort 58 | # tooling info 59 | echo "## installed packages" 60 | pkg info 61 | # 62 | ### Create zpool #################################################################### 63 | dd if=/dev/zero of=/zfs1 bs=1 count=1 seek=2G 64 | zdev=$(mdconfig -a -t vnode -S 4096 -f /zfs1) 65 | zpool create -f zroot "$zdev" 66 | # 67 | ### Configure pf and pot ############################################################ 68 | echo "set skip on lo0" >/etc/pf.conf 69 | echo pass >>/etc/pf.conf 70 | service pf enable 71 | service pf start 72 | pw groupadd pot 73 | bin/pot init 74 | # 75 | ### Run CI tests ################################################ 76 | cd "$WORKSPACE" 77 | cp -f etc/pot/pot.default.conf etc/pot/pot.conf 78 | cd tests/CI 79 | set +e 80 | FAULT=0 81 | ./run.sh || FAULT=1 82 | echo "Log output:" 83 | cat pot-ci-* 84 | if [ $FAULT -ne 0 ]; then exit 1; fi 85 | # 86 | ### Finished ######################################################################## 87 | echo "Done" 88 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: unit-test 4 | 5 | # Controls when the action will run. Triggers the workflow on push or pull request 6 | # events but only for the master branch 7 | on: 8 | push: 9 | branches: [ master ] 10 | pull_request: 11 | branches: [ master ] 12 | 13 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 14 | jobs: 15 | # This workflow contains a single job called "build" 16 | build: 17 | # The type of runner that the job will run on 18 | runs-on: ubuntu-latest 19 | 20 | # Steps represent a sequence of tasks that will be executed as part of the job 21 | steps: 22 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 23 | - uses: actions/checkout@v2 24 | 25 | # Runs a single command using the runners shell 26 | - name: Run a one-line script 27 | run: cd tests && ./test-suite.sh 28 | -------------------------------------------------------------------------------- /.github/workflows/shellcheck.yml: -------------------------------------------------------------------------------- 1 | name: Shellcheck 2 | 3 | on: [ pull_request ] 4 | 5 | jobs: 6 | shellcheck: 7 | name: Shellcheck 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Run ShellCheck 12 | uses: ludeeus/action-shellcheck@master 13 | with: 14 | scandir: share/pot 15 | additional_files: bin/pot 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /doc 2 | *.swp 3 | *~ 4 | /etc/pot/pot.conf 5 | /etc/pot/flavours/* 6 | !/etc/pot/flavours/dns.sh 7 | !/etc/pot/flavours/dns 8 | !/etc/pot/flavours/slim.sh 9 | !/etc/pot/flavours/fbsd-update.sh 10 | devenv.sh 11 | /tests/CI/pot-ci* 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | script: cd tests && ./test-suite.sh 3 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | environment { 5 | TERM = 'rxvt' 6 | } 7 | 8 | stages { 9 | stage('Test') { 10 | steps { 11 | sh 'echo "Hello World"' 12 | sh ''' 13 | cd tests 14 | ./test-suite.sh 15 | ''' 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Luca Pizzamiglio 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /etc/pot/flavours/dns: -------------------------------------------------------------------------------- 1 | set-attribute -A start-at-boot -V YES 2 | -------------------------------------------------------------------------------- /etc/pot/flavours/dns.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pkg install -y dnsmasq 4 | pkg install -y consul 5 | pkg clean -ayq 6 | 7 | if [ ! -d /usr/local/etc/consul.d ]; then 8 | mkdir -p /usr/local/etc/consul.d 9 | fi 10 | 11 | _epair="$(ifconfig | egrep 'epair.*b' | cut -f 1 -d':')" 12 | _ip="$( ifconfig $_epair inet | awk '/inet/ { print $2; }' )" 13 | _ip1="$( echo $_ip | cut -f 1 -d'.' )" 14 | _ip2="$( echo $_ip | cut -f 2 -d'.' )" 15 | _domain="$( hostname | cut -f 2 -d'.' )" 16 | echo "server=/${_domain}/127.0.0.1#8600" >> /usr/local/etc/dnsmasq.conf 17 | echo "server=/0.${_ip2}.${_ip1}.in-addr.arpa/127.0.0.1#8600" >> /usr/local/etc/dnsmasq.conf 18 | echo "listen-address=${_ip}" >> /usr/local/etc/dnsmasq.conf 19 | 20 | sysrc dnsmasq_enable="YES" 21 | sysrc consul_enable="YES" 22 | sysrc consul_args="-server -dev -domain=${_domain} -bind=${_ip}" 23 | -------------------------------------------------------------------------------- /etc/pot/flavours/fbsd-update.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export PAGER=/bin/cat 4 | freebsd-update --not-running-from-cron fetch install 5 | -------------------------------------------------------------------------------- /etc/pot/flavours/slim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | dirs="/usr/share/bsdconfig /usr/share/doc /usr/share/dtrace /usr/share/examples /usr/share/man /usr/share/openssl /usr/share/sendmail /usr/share/pc-sysinstall /usr/libexec/bsdinstall /usr/libexec/bsdconfig /rescue /usr/tests /usr/lib32 /usr/lib/clang /usr/include /var/db/freebsd-update /var/db/etcupdate /boot" 4 | usr_bin="c++ c++filt c89 c99 cc CC cpp clang clang-cpp clang-tblgen clang++ gdb gdbtui gdbserver ld ld.bfd ld.lld lldb llvm-objdump llvm-tblgen nm objcopy objdump strings strip" 5 | usr_bin_glob="svnlite yp" 6 | 7 | usr_sbin="dtrace" 8 | usr_sbin_glob="bhyve boot yp" 9 | rm -f /usr/lib/*.a 10 | ## Remove pkg stuff 11 | rm -rf /var/db/pkg/* 12 | rm -rf /usr/sbin/pkg 13 | rm -rf /usr/local/sbin/pkg 14 | 15 | for d in $dirs ; do 16 | rm -rf ${d} 17 | done 18 | ( 19 | cd /usr/bin 20 | for f in $usr_bin ; do 21 | rm -f $f 22 | done 23 | for g in $usr_bin_glob ; do 24 | rm -rf ${g}* 25 | done 26 | ) 27 | ( 28 | cd /usr/sbin 29 | for g in $usr_sbin_glob ; do 30 | rm -rf ${g}* 31 | done 32 | rm -f $usr_sbin 33 | ) 34 | -------------------------------------------------------------------------------- /etc/pot/pot.conf.sample: -------------------------------------------------------------------------------- 1 | # pot configuration file 2 | 3 | # All datasets related to pot use the some zfs dataset as parent 4 | # With this variable, you can choose which dataset has to be used 5 | # POT_ZFS_ROOT=zroot/pot 6 | 7 | # It is also important to know where the root dataset is mounted 8 | # POT_FS_ROOT=/opt/pot 9 | 10 | # This is the cache used to import/export pots 11 | # POT_CACHE=/var/cache/pot 12 | 13 | # This is where pot is going to store temporary files 14 | # POT_TMP=/tmp 15 | 16 | # This is the group owning POT_FS_ROOT 17 | # POT_GROUP=pot 18 | 19 | # This is the suffix added to temporary files created using mktemp, 20 | # X is a placeholder for a random character, see mktemp(1) 21 | # POT_MKTEMP_SUFFIX=.XXXXXXXX 22 | 23 | # Define the max length of the hostname inside the pot 24 | # POT_HOSTNAME_MAX_LENGTH=64 25 | 26 | # Internal Virtual Network configuration 27 | 28 | # IPv4 Internal Virtual network 29 | # POT_NETWORK=10.192.0.0/10 30 | 31 | # Internal Virtual Network netmask 32 | # POT_NETMASK=255.192.0.0 33 | 34 | # The default gateway of the Internal Virtual Network 35 | # POT_GATEWAY=10.192.0.1 36 | 37 | # The name of the network physical interface, to be used as default gateway 38 | # POT_EXTIF=em0 39 | 40 | # The list of extra network interface, to make other network segments accessible 41 | # POT_EXTRA_EXTIF=vlan20 vlan50 42 | # for each extra interface, a variable is used to sepcify its network segment 43 | # POT_NETWORK_vlan20=192.168.100.0/24 44 | # POT_NETWORK_vlan50=10.50.50.0/24 45 | 46 | # Do not allow bridge-based pots to forward traffic to each other 47 | # POT_ISOLATE_VNET_POTS=true 48 | 49 | # DNS on the Internal Virtual Network 50 | 51 | # name of the pot running the DNS 52 | # POT_DNS_NAME=dns 53 | 54 | # IP of the DNS 55 | # POT_DNS_IP=10.192.0.2 56 | 57 | # Path to default public key to verify pot signatures using signify(1) 58 | # on import/prepare - can be overridden using `-C pubkey`. 59 | # POT_DEFAULT_SIGNATURE_PUBKEY=/usr/local/etc/pot/sign_key.pub 60 | 61 | # VPN support 62 | 63 | # name of the tunnel network interface 64 | # POT_VPN_EXTIF=tun0 65 | # POT_VPN_NETWORKS=192.168.0.0/24 192.168.10.0/24 66 | -------------------------------------------------------------------------------- /etc/pot/pot.default.conf: -------------------------------------------------------------------------------- 1 | # pot configuration file - default values 2 | 3 | # All datasets related to pot use the some zfs dataset as parent 4 | # With this variable, you can choose which dataset has to be used 5 | POT_ZFS_ROOT=zroot/pot 6 | 7 | # It is also important to know where the root dataset is mounted 8 | POT_FS_ROOT=/opt/pot 9 | 10 | # This is the cache used to import/export pots 11 | POT_CACHE=/var/cache/pot 12 | 13 | # This is where pot is going to store temporary files 14 | POT_TMP=/tmp 15 | 16 | # This is the group owning POT_FS_ROOT 17 | POT_GROUP=pot 18 | 19 | # This is the suffix added to temporary files created using mktemp, 20 | # X is a placeholder for a random character, see mktemp(1) 21 | POT_MKTEMP_SUFFIX=.XXXXXXXX 22 | 23 | # Define the max length of the hostname inside the pot 24 | POT_HOSTNAME_MAX_LENGTH=64 25 | 26 | # Internal Virtual Network configuration 27 | # IPv4 Internal Virtual network 28 | POT_NETWORK=10.192.0.0/10 29 | # Internal Virtual Network netmask 30 | POT_NETMASK=255.192.0.0 31 | # The default gateway of the Internal Virtual Network 32 | POT_GATEWAY=10.192.0.1 33 | # The name of the network physical interface, to be used as default gateway 34 | POT_EXTIF=em0 35 | # Additional network interfaces 36 | POT_EXTRA_EXTIF= 37 | # If not empty, it will use this IPv4 on POT_EXTIF as defualt gateway 38 | POT_EXTIF_ADDR= 39 | 40 | # Three possible values: ipv4, ipv6, dual 41 | POT_NETWORK_STACK=ipv4 42 | 43 | # DNS on the Internal Virtual Network 44 | # name of the pot running the DNS 45 | POT_DNS_NAME=dns 46 | # IP of the DNS 47 | POT_DNS_IP=10.192.0.2 48 | 49 | # If set to true, isolate pot vnet bridge members 50 | # (by using `ifconfig private `, see ifconfig(8)) 51 | POT_ISOLATE_VNET_POTS=false 52 | 53 | # If not empty, this script will be called by pot and the pf rules 54 | # returned on stdout will be loaded into "pot-rdr/anchor" instead 55 | # of those which pot would usually create. This also skips 56 | # creation of netcat-based localhost-tunnels. 57 | # Only works with IPv4 at the moment. 58 | # 59 | # Parameters sent to the script are: 60 | # POT_EXTIF BRIDGE POT_NETWORK POT_GATEWAY proto host_port pot_ip pot_port 61 | # Example: 62 | # igb0 bridge1 10.192.0.0/10 10.192.0.1 tcp 32732 10.192.0.10 80 63 | POT_EXPORT_PORTS_PF_RULES_HOOK= 64 | # VPN support 65 | 66 | # Path to default public key to verify pot signatures using signify(1) 67 | # on import/prepare - can be overridden using `-C pubkey`. 68 | POT_DEFAULT_SIGNATURE_PUBKEY= 69 | 70 | # name of the tunnel network interface 71 | POT_VPN_EXTIF= 72 | POT_VPN_NETWORKS= 73 | 74 | # POT log facility 75 | POT_LOG_FACILITY=local2 76 | -------------------------------------------------------------------------------- /etc/rc.d/pot: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # PROVIDE: pot 4 | # REQUIRE: NETWORKING LOGIN FILESYSTEM 5 | # BEFORE: securelevel 6 | # KEYWORD: shutdown nojail 7 | 8 | . /etc/rc.subr 9 | 10 | PATH=$PATH:/usr/local/bin 11 | name="pot" 12 | desc="Pot containers" 13 | procname="pot" 14 | rcvar=pot_enable 15 | start_cmd="pot_start" 16 | stop_cmd="pot_stop" 17 | restart_cmd="pot_restart" 18 | status_cmd="pot_status" 19 | start_precmd="pot_deprecated_start" 20 | stop_postcmd="pot_deprecated_stop" 21 | 22 | load_rc_config $name 23 | : ${pot_enable:=NO} 24 | 25 | pot_start() 26 | { 27 | local _pname _dyn_pot_list _start 28 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 29 | for _pname in $_dyn_pot_list ; do 30 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A start-at-boot -q )" = "YES" ]; then 31 | /usr/local/bin/pot start "$_pname" 32 | fi 33 | done 34 | } 35 | 36 | pot_stop() 37 | { 38 | local _pname _dyn_pot_list _start 39 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 40 | for _pname in $_dyn_pot_list ; do 41 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A start-at-boot -q )" = "YES" ]; then 42 | /usr/local/bin/pot stop "$_pname" 43 | fi 44 | done 45 | } 46 | 47 | pot_early_start() 48 | { 49 | local _pname _dyn_pot_list _start 50 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 51 | for _pname in $_dyn_pot_list ; do 52 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A early-start-at-boot -q )" = "YES" ]; then 53 | /usr/local/bin/pot start "$_pname" 54 | fi 55 | done 56 | } 57 | 58 | pot_early_stop() 59 | { 60 | local _pname _dyn_pot_list _start 61 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 62 | for _pname in $_dyn_pot_list ; do 63 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A early-start-at-boot -q )" = "YES" ]; then 64 | /usr/local/bin/pot stop "$_pname" 65 | fi 66 | done 67 | } 68 | 69 | pot_restart() 70 | { 71 | pot_stop 72 | pot_early_stop 73 | sleep 5 74 | pot_early_start 75 | pot_start 76 | } 77 | 78 | pot_status() 79 | { 80 | local _pname _dyn_pot_list 81 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 82 | for _pname in $_dyn_pot_list ; do 83 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A early-start-at-boot -q )" = "YES" ] || 84 | [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A start-at-boot -q )" = "YES" ]; then 85 | if /usr/local/bin/pot info -qrp "$_pname" ; then 86 | echo "pot $_pname is up and running" 87 | else 88 | echo "pot $_pname is not running" 89 | fi 90 | fi 91 | done 92 | } 93 | 94 | run_rc_command "$1" 95 | -------------------------------------------------------------------------------- /etc/rc.d/pot_early: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # PROVIDE: pot_early 4 | # REQUIRE: NETWORKING syslogd pf 5 | # BEFORE: ntpdate 6 | # KEYWORD: shutdown nojail 7 | 8 | . /etc/rc.subr 9 | 10 | PATH=$PATH:/usr/local/bin 11 | name="pot_early" 12 | desc="Pot containers - early start" 13 | procname="pot" 14 | rcvar=pot_enable 15 | start_cmd="pot_early_start" 16 | stop_cmd="pot_early_stop" 17 | 18 | load_rc_config $name 19 | : ${pot_enable:=NO} 20 | 21 | pot_early_start() 22 | { 23 | local _pname _dyn_pot_list _start 24 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 25 | for _pname in $_dyn_pot_list ; do 26 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A early-start-at-boot -q )" = "YES" ]; then 27 | /usr/local/bin/pot start "$_pname" 28 | fi 29 | done 30 | } 31 | 32 | pot_early_stop() 33 | { 34 | local _pname _dyn_pot_list _start 35 | _dyn_pot_list=$(/usr/local/bin/pot ls -q) 36 | for _pname in $_dyn_pot_list ; do 37 | if [ "$( /usr/local/bin/pot get-attr -p "$_pname" -A early-start-at-boot -q )" = "YES" ]; then 38 | /usr/local/bin/pot stop "$_pname" 39 | fi 40 | done 41 | } 42 | 43 | run_rc_command "$1" 44 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | print_syntax() { echo "$0" X.Y.Z ; exit "${1:-1}"; } 4 | 5 | if [ -z "$1" ]; then 6 | print_syntax 7 | fi 8 | 9 | if [ "$1" = "$(echo "$1" | sed -E 's/[0-9]+(\.[0-9]+)+//')" ]; then 10 | echo invalid verion number $1 11 | print_syntax 12 | exit 13 | fi 14 | 15 | version="$1" 16 | tag_date="$(date +%Y-%m-%d)" 17 | echo applying new version "$version" with date "$tag_date" 18 | 19 | sed -i '' "s/^_POT_VERSION=.*$/_POT_VERSION=$version/" 'bin/pot' 20 | sed -i '' 's/^## \[Unreleased\]/## \[Unreleased\]\ 21 | \ 22 | ### NEWVERSION/' CHANGELOG.md 23 | 24 | sed -i '' "s/### NEWVERSION/## \[$version\] $tag_date/" CHANGELOG.md 25 | 26 | sed -i '' "s/^version = .*$/version = \"$version\"/" 'share/doc/pot/conf.py' 27 | sed -i '' "s/^release = .*$/release = \"$version\"/" 'share/doc/pot/conf.py' 28 | 29 | git diff -p --stat 30 | -------------------------------------------------------------------------------- /share/doc/pot/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | -------------------------------------------------------------------------------- /share/doc/pot/Description.md: -------------------------------------------------------------------------------- 1 | DESCRIPTION 2 | ----------- 3 | Another container framework based on jails, to run FreeBSD containers on 4 | FreeBSD. Every running instance is called "pot", but less flexible than a 5 | VM. It's heavily based on FreeBSD, in particular on jails, ZFS, pf and 6 | rctl. 7 | -------------------------------------------------------------------------------- /share/doc/pot/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = pot 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /share/doc/pot/Synopsis.md: -------------------------------------------------------------------------------- 1 | SYNOPSIS 2 | -------- 3 | 4 | `pot` SUBCOMMAND 5 | -------------------------------------------------------------------------------- /share/doc/pot/index.md: -------------------------------------------------------------------------------- 1 | Contents 2 | -------- 3 | 4 | * [Synopsis](Synopsis.md) 5 | * [Description](Description.md) 6 | * [QuickStart](QuickStart.md) 7 | * [Installation](Installation.md) 8 | * [migration](migration.md) 9 | * [Images](Images.md) 10 | -------------------------------------------------------------------------------- /share/doc/pot/migration.md: -------------------------------------------------------------------------------- 1 | ## Manual migration handbook 2 | 3 | ### Prerequisite 4 | 5 | * testing with single type pot 6 | * a snapshot is already present 7 | 8 | ### A xz archive of the datasets 9 | 10 | * `zfs send -R zroot/pot/jails/mypot@1539804703 | xz > mypot.1539804703.xz` 11 | 12 | Some statistics on FreeBSD 12.0 13 | The file systems are accounted for 801MB, lz4 providing 2.23 as compression ration, leaving 383MB on the disk. 14 | xz -9 is extremely slow, using +800MB of RAM and producing an output of 132MB 15 | xz -6 (default) is quite slow, producing an output of 148MB 16 | xz -3 is decently fast, producing an output of 164MB 17 | xz -0 is quite fast, producing an output of 182MB 18 | 19 | # Speculation 20 | 21 | ### A migration process 22 | 23 | send the first xz file and combine with the receive 24 | * `xzcat mypot.1539804703.xz | zfs receive ${POT_ZFS_ROOT}/jails/mypot@1539804703 25 | 26 | depending on the content of pot.conf and fscomp.conf, get and extract the other datasets propery 27 | In this case: 28 | * xzcat mypot_m.1539804703.xz | zfs receive ${POT_ZFS_ROOT}/jails/mypot/m@1539804703 29 | -------------------------------------------------------------------------------- /share/pot/add-dep.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | add-dep-help() 6 | { 7 | cat <<-"EOH" 8 | pot add-dep [-hv] -p potname -P depPot 9 | -h print this help 10 | -v verbose 11 | -p potname : the working pot 12 | -P depPot : the pot to depend on. Will be started automatically 13 | before starting the working pot "potname". 14 | EOH 15 | } 16 | 17 | # $1 pot 18 | # $2 depPot 19 | _add_dependency() 20 | { 21 | local _depPot _pname _cdir 22 | _pname="$1" 23 | _depPot="$2" 24 | _cdir=$POT_FS_ROOT/jails/$_pname/conf 25 | echo "pot.depend=$_depPot" >> "$_cdir"/pot.conf 26 | } 27 | 28 | pot-add-dep() 29 | { 30 | local _pname _depPot 31 | _depPot= 32 | _pname= 33 | OPTIND=1 34 | while getopts "hvp:P:" _o ; do 35 | case "$_o" in 36 | h) 37 | add-dep-help 38 | return 0 39 | ;; 40 | v) 41 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 42 | ;; 43 | P) 44 | _depPot="$OPTARG" 45 | ;; 46 | p) 47 | _pname="$OPTARG" 48 | ;; 49 | *) 50 | add-dep-help 51 | return 1 52 | ;; 53 | esac 54 | done 55 | 56 | if [ -z "$_pname" ]; then 57 | _error "A pot name is mandatory" 58 | add-dep-help 59 | return 1 60 | fi 61 | if [ -z "$_depPot" ]; then 62 | _error "A dependency pot is mandatory" 63 | add-dep-help 64 | return 1 65 | fi 66 | if [ "$_pname" = "$_depPot" ]; then 67 | _error "a pot cannot be run time dependecy of itself" 68 | add-dep-help 69 | return 1 70 | fi 71 | if ! _is_pot "$_pname" ; then 72 | _error "pot $_pname is not valid" 73 | add-dep-help 74 | return 1 75 | fi 76 | if ! _is_pot "$_depPot" ; then 77 | _error "dependency pot $_depPot is not valid" 78 | add-dep-help 79 | return 1 80 | fi 81 | if ! _is_uid0 ; then 82 | return 1 83 | fi 84 | _add_dependency "$_pname" "$_depPot" 85 | } 86 | -------------------------------------------------------------------------------- /share/pot/clone-fscomp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | clone-fscomp-help() 6 | { 7 | cat <<-"EOH" 8 | pot clone-fscomp [-hv] -f fscomp -F fscomp 9 | -h print this help 10 | -v verbose 11 | -F fscomp : the fscomp to be cloned (mandatory) 12 | -f fscomp : the fscomp name (mandatory) 13 | EOH 14 | } 15 | 16 | # $1 new fscomp name 17 | # $2 old fscomp name 18 | _cf_zfs() 19 | { 20 | local _fscomp _cfscomp _fsdset _fsdir _snap 21 | _fscomp=$1 22 | _cfscomp=$2 23 | _fsdset=${POT_ZFS_ROOT}/fscomp 24 | _fsdir=${POT_FS_ROOT}/fscomp 25 | _snap=$( _zfs_last_snap "$_fsdset/$_cfscomp" ) 26 | if [ -z "$_snap" ]; then 27 | _error "$_fsdset/$_cfscomp has no snapshots - please take one" 28 | return 1 29 | else 30 | _debug "Cloning $_cfscomp@$_snap into $_fsdset/$_fscomp" 31 | zfs clone -o mountpoint="$_fsdir/$_fscomp" "$_fsdset/$_cfscomp@$_snap" "$_fsdset/$_fscomp" 32 | fi 33 | return 0 # true 34 | } 35 | 36 | pot-clone-fscomp() 37 | { 38 | local _fscomp _cfscomp 39 | _fscomp= 40 | _cfscomp= 41 | OPTIND=1 42 | while getopts "hvf:F:" _o ; do 43 | case "$_o" in 44 | h) 45 | clone-fscomp-help 46 | ${EXIT} 0 47 | ;; 48 | v) 49 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 50 | ;; 51 | f) 52 | _fscomp=$OPTARG 53 | ;; 54 | F) 55 | _cfscomp=$OPTARG 56 | ;; 57 | *) 58 | clone-fscomp-help 59 | ${EXIT} 1 60 | ;; 61 | esac 62 | done 63 | # parameter validation 64 | if [ -z "$_fscomp" ]; then 65 | _error "fscomp name is missing (option -f)" 66 | clone-fscomp-help 67 | ${EXIT} 1 68 | fi 69 | if [ -z "$_cfscomp" ]; then 70 | _error "clonable fscomp name is missing (option -F)" 71 | clone-fscomp-help 72 | ${EXIT} 1 73 | fi 74 | if _zfs_dataset_valid "${POT_ZFS_ROOT}/fscomp/$_fscomp" ; then 75 | _error "fscomp $_fscomp already exists" 76 | ${EXIT} 1 77 | fi 78 | if ! _zfs_dataset_valid "${POT_ZFS_ROOT}/fscomp/$_cfscomp" ; then 79 | _error "fscomp $_cfscomp doesn't exist" 80 | ${EXIT} 1 81 | fi 82 | if ! _is_uid0 ; then 83 | ${EXIT} 1 84 | fi 85 | if ! _cf_zfs "$_fscomp" "$_cfscomp" ; then 86 | ${EXIT} 1 87 | fi 88 | } 89 | -------------------------------------------------------------------------------- /share/pot/common-flv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | 4 | # $1 flavour name 5 | _is_flavour() 6 | { 7 | local _flv_name 8 | _flv_name="$1" 9 | if [ -n "$( _get_flavour_script "$_flv_name" )" ] || 10 | [ -n "$( _get_flavour_cmd_file "$_flv_name" )" ]; then 11 | return 0 # true 12 | fi 13 | return 1 # false 14 | } 15 | 16 | _get_flavour_script() 17 | { 18 | local _flv_name 19 | _flv_name="$1" 20 | if [ -f "$_flv_name" ] && [ "$_flv_name" != "${_flv_name%%.sh}" ]; then ## it's a script path name 21 | echo "$_flv_name" 22 | elif [ -f "$_flv_name.sh" ]; then ## it's a path name 23 | echo "$_flv_name.sh" 24 | elif [ -f "./$_flv_name.sh" ]; then 25 | echo "./$_flv_name.sh" 26 | elif [ -f "${_POT_FLAVOUR_DIR}/$_flv_name.sh" ]; then 27 | echo "${_POT_FLAVOUR_DIR}/$_flv_name.sh" 28 | fi 29 | } 30 | 31 | _get_flavour_cmd_file() 32 | { 33 | local _flv_name 34 | _flv_name="$1" 35 | # if the flavor name ends with .sh return immediately 36 | if [ "$_flv_name" != "${_flv_name%%.sh}" ]; then 37 | return 38 | fi 39 | if [ -f "$_flv_name" ] && [ -r "$_flv_name" ]; then ## it's a cmd file path name 40 | echo "$_flv_name" 41 | elif [ -f "./$_flv_name" ] && [ -r "./$_flv_name" ]; then 42 | echo "./$_flv_name" 43 | elif [ -f "${_POT_FLAVOUR_DIR}/$_flv_name" ] || [ -r "${_POT_FLAVOUR_DIR}/$_flv_name" ]; then 44 | echo "${_POT_FLAVOUR_DIR}/$_flv_name" 45 | fi 46 | } 47 | 48 | # $1 the cmd 49 | # all other parameter will be ignored 50 | # tested 51 | _is_cmd_flavorable() 52 | { 53 | local _cmd 54 | _cmd=$1 55 | case $_cmd in 56 | add-dep|set-attribute|\ 57 | copy-in|copy-in-flv|mount-in|\ 58 | set-rss|export-ports|\ 59 | set-cmd|set-env) 60 | return 0 61 | ;; 62 | esac 63 | return 1 # false 64 | } 65 | 66 | # Special version of set-cmd usable only for flavours 67 | # $1 : pot name 68 | # $2 : the set-cmd line in the file 69 | _flv_set_cmd() 70 | { 71 | local _pname _line _cmd 72 | _pname="$1" 73 | _line="$2" 74 | _cmd="${_line#set-cmd -c }" 75 | if [ "$_line" = "$_cmd" ]; then 76 | _error "In flavour only 'set-cmd -c ' is supported" 77 | return 1 78 | fi 79 | _set_command "$_pname" "$_cmd" 80 | } 81 | 82 | _exec_flv() 83 | { 84 | local _pname _flv _pdir _flv_cmd_file _flv_script _flv_dir _previous_pwd _persist 85 | _pname=$1 86 | _flv=$2 87 | _pdir=${POT_FS_ROOT}/jails/$_pname 88 | _debug "Flavour: $_flv" 89 | _flv_cmd_file="$( _get_flavour_cmd_file "$_flv" )" 90 | _flv_dir=$(dirname "${_flv_cmd_file}") 91 | if [ -n "${_flv_cmd_file}" ]; then 92 | _debug "Executing $_flv pot commands on $_pname" 93 | while read -r line ; do 94 | # shellcheck disable=SC2086 95 | if _is_cmd_flavorable $line ; then 96 | if [ "$line" != "${line#set-cmd}" ]; then 97 | # workaround for set-cmd / damn quoting and shell scripts 98 | if ! _flv_set_cmd "$_pname" "$line" ; then 99 | return 1 100 | fi 101 | elif [ "$line" != "${line#copy-in-flv}" ]; then 102 | # copy-in relative to flavour dir 103 | _previous_pwd=$PWD 104 | if ! cd "$_flv_dir"; then 105 | _error "Can't chdir to flavour dir $_flv_dir" 106 | return 1 107 | fi 108 | line=$(echo "$line" | sed "s/^copy-in-flv/copy-in/") 109 | if ! pot-cmd $line -p "$_pname" ; then 110 | return 1 111 | fi 112 | if ! cd "$_previous_pwd"; then 113 | _error "Can't chdir to previous pwd $_previous_pwd" 114 | return 1 115 | fi 116 | else 117 | # shellcheck disable=SC2086 118 | if ! pot-cmd $line -p "$_pname" ; then 119 | return 1 120 | fi 121 | fi 122 | else 123 | _error "Flavor $_flv: line $line not valid - ignoring" 124 | fi 125 | done < "${_flv_cmd_file}" 126 | fi 127 | _flv_script="$( _get_flavour_script "$_flv" )" 128 | if [ -n "${_flv_script}" ]; then 129 | _debug "Starting $_pname pot for the initial bootstrap" 130 | 131 | _persist="$(_get_conf_var "$_pname" "pot.attr.persistent")" 132 | if [ "$_persist" = "NO" ]; then 133 | _debug "Setting pot $_pname temporarily to persistent" 134 | if ! pot-cmd set-attribute -A persistent -V YES -p "$_pname" ; then 135 | return 1 136 | fi 137 | fi 138 | 139 | pot-cmd start "$_pname" 140 | cp -v "${_flv_script}" "$_pdir/m/tmp" 141 | chmod a+x "$_pdir/m/tmp/$(basename "${_flv_script}" )" 142 | _debug "Executing $_flv script on $_pname" 143 | if ! jexec "$_pname" "/tmp/$(basename "${_flv_script}")" "$_pname" ; then 144 | _error "create: flavour $_flv failed (script)" 145 | return 1 146 | fi 147 | pot-cmd stop "$_pname" 148 | if [ "$_persist" = "NO" ]; then 149 | _debug "Reverting pot $_pname to non-persistent" 150 | if ! pot-cmd set-attribute -A persistent -V NO -p "$_pname" ; then 151 | return 1 152 | fi 153 | fi 154 | else 155 | _debug "No shell script available for the flavour $_flv" 156 | fi 157 | 158 | } 159 | -------------------------------------------------------------------------------- /share/pot/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | 4 | : "${_config_names:="fs_root zfs_root gateway syslogd pot_prefix fscomp_prefix network_stack"}" 5 | 6 | config-help() 7 | { 8 | cat <<-EOH 9 | pot config [-hvq] [-g name] 10 | -h print this help 11 | -v verbose 12 | -q quiet 13 | -g name : get value of config item "name", one of: 14 | $(echo "$_config_names" | xargs -n1 echo " +" | sort) 15 | EOH 16 | } 17 | 18 | # $1 quiet 19 | # $2 name 20 | # $3 value 21 | _config_echo() 22 | { 23 | if [ "$1" = "quiet" ]; then 24 | echo "$3" 25 | else 26 | echo "$2 = $3" 27 | fi 28 | } 29 | 30 | pot-config() 31 | { 32 | local _quiet 33 | _quiet="NO" 34 | _get= 35 | OPTIND=1 36 | 37 | while getopts "hvqg:" _o ; do 38 | case "$_o" in 39 | h) 40 | config-help 41 | ${EXIT} 0 42 | ;; 43 | v) 44 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 45 | ;; 46 | q) 47 | _quiet="quiet" 48 | ;; 49 | g) 50 | if _is_in_list "$OPTARG" "$_config_names" ; then 51 | _get="$OPTARG" 52 | else 53 | _qerror $_quiet "$OPTARG is not a valid name" 54 | [ "quiet" != "$_quiet" ] && config-help 55 | ${EXIT} 1 56 | fi 57 | ;; 58 | ?) 59 | config-help 60 | ${EXIT} 1 61 | ;; 62 | esac 63 | done 64 | 65 | if [ -z "$_get" ]; then 66 | _qerror $_quiet "option -g is mandatory" 67 | [ "quiet" != "$_quiet" ] && config-help 68 | ${EXIT} 1 69 | fi 70 | case $_get in 71 | fs_root) 72 | _config_echo $_quiet "fs_root" "$POT_FS_ROOT" 73 | ;; 74 | zfs_root) 75 | _config_echo $_quiet "zfs_root" "$POT_ZFS_ROOT" 76 | ;; 77 | gateway) 78 | _config_echo $_quiet "gateway" "$POT_GATEWAY" 79 | ;; 80 | syslogd) 81 | _config_echo $_quiet "syslogd flags" "-b 127.0.0.1 -b $POT_GATEWAY -a $POT_NETWORK" 82 | ;; 83 | pot_prefix) 84 | _config_echo $_quiet "pot prefix" "$POT_FS_ROOT/jails" 85 | ;; 86 | fscomp_prefix) 87 | _config_echo $_quiet "fscomp prefix" "$POT_FS_ROOT/fscomp" 88 | ;; 89 | network_stack) 90 | _config_echo $_quiet "network stack" "$( _get_network_stack )" 91 | ;; 92 | esac 93 | } 94 | -------------------------------------------------------------------------------- /share/pot/copy-out.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | copy-out-help() 6 | { 7 | cat <<-"EOH" 8 | pot copy-out [-hv] -p pot -s source -d dest 9 | -h print this help 10 | -v verbose 11 | -F force copy operation for running jails 12 | (warning: can expose parts of the host file system) 13 | -p pot : the working pot 14 | -s source : the file or directory inside the pot 15 | -d dest : the location (directory) on the host to copy-out to 16 | EOH 17 | } 18 | 19 | # $1 source 20 | _destination_validation() 21 | { 22 | local _destination 23 | _destination="$1" 24 | if [ -r "$_destination" ] && [ -d "$_destination" ] && [ -x "$_destination" ]; then 25 | return 0 # true 26 | else 27 | _error "$_destination not valid" 28 | fi 29 | } 30 | 31 | _make_temp_destination() 32 | { 33 | local _proot 34 | _proot="$1" 35 | mktemp -d "$_proot/tmp/copy-out${POT_MKTEMP_SUFFIX}" 36 | } 37 | 38 | _mount_destination_into_potroot() 39 | { 40 | local _destination _mountpoint 41 | _destination="$1" 42 | _mountpoint="$2" 43 | if ! mount_nullfs "$_destination" "$_mountpoint" ; then 44 | _error "Failed to mount destination inside the pot" 45 | return 1 46 | fi 47 | } 48 | 49 | pot-copy-out() 50 | { 51 | local _pname _source _destination _to_be_umount _rc _force _proot _cp_opt _destination_mountpoint 52 | OPTIND=1 53 | _pname= 54 | _destination= 55 | _force= 56 | _cp_opt="-a" 57 | while getopts "hvs:d:p:F" _o ; do 58 | case "$_o" in 59 | h) 60 | copy-out-help 61 | return 0 62 | ;; 63 | F) 64 | _force="YES" 65 | ;; 66 | v) 67 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 68 | _cp_opt="-va" 69 | ;; 70 | s) 71 | _source="$OPTARG" 72 | ;; 73 | p) 74 | _pname="$OPTARG" 75 | ;; 76 | d) 77 | _destination="$OPTARG" 78 | ;; 79 | *) 80 | copy-out-help 81 | return 1 82 | ;; 83 | esac 84 | done 85 | 86 | if [ -z "$_pname" ]; then 87 | _error "A pot name is mandatory" 88 | copy-out-help 89 | return 1 90 | fi 91 | if [ -z "$_source" ]; then 92 | _error "A source is mandatory" 93 | copy-out-help 94 | return 1 95 | fi 96 | if [ -z "$_destination" ]; then 97 | _error "A destination is mandatory" 98 | copy-out-help 99 | return 1 100 | fi 101 | if ! _is_absolute_path "$_source" ; then 102 | _error "The source has to be an absolute pathname" 103 | return 1 104 | fi 105 | 106 | if ! _is_pot "$_pname" ; then 107 | _error "pot $_pname is not valid" 108 | copy-out-help 109 | return 1 110 | fi 111 | if ! _is_uid0 ; then 112 | return 1 113 | fi 114 | if ! _destination_validation "$_destination" ; then 115 | copy-out-help 116 | return 1 117 | fi 118 | if _is_pot_running "$_pname" ; then 119 | if [ "$_force" != "YES" ]; then 120 | _error "Copying files from a running pot is discouraged, it can partially expose the host file system to the jail" 121 | _info "Using the -F flag, the operation can be executed anyway, but we disagree" 122 | return 1 123 | else 124 | _debug "Copying files from a running pot allowed, because of the -F flag" 125 | fi 126 | else 127 | _pot_mount "$_pname" 128 | _to_be_umount=1 129 | fi 130 | _proot=${POT_FS_ROOT}/jails/$_pname/m 131 | if ! _destination_mountpoint="$( _make_temp_destination "$_proot" )" ; then 132 | _error "Failed to build a temporary folder in the pot /tmp" 133 | if [ "$_to_be_umount" = "1" ]; then 134 | _pot_umount "$_pname" 135 | fi 136 | return 1 137 | fi 138 | if ! _mount_destination_into_potroot "$_destination" "$_destination_mountpoint" ; then 139 | if [ "$_to_be_umount" = "1" ]; then 140 | _pot_umount "$_pname" 141 | fi 142 | return 1 143 | fi 144 | _cp_destination="/tmp/$( basename "$_destination_mountpoint" )" 145 | if _is_pot_running "$_pname" ; then 146 | if jexec "$_pname" /bin/cp "$_cp_opt" "$_source" "$_cp_destination" ; then 147 | _debug "Source $_source copied from the pot $_pname" 148 | _rc=0 149 | else 150 | _error "Source $_source NOT copied because of an error" 151 | _rc=1 152 | fi 153 | else 154 | if jail -c path="$_proot" command=/bin/cp "$_cp_opt" "$_source" "$_cp_destination" ; then 155 | _debug "Source $_source copied from the pot $_pname" 156 | _rc=0 157 | else 158 | _error "Source $_source NOT copied because of an error" 159 | _rc=1 160 | fi 161 | fi 162 | 163 | if ! umount -f "$_destination_mountpoint" ; then 164 | _error "Failed to unmount the source tmp folder from the pot" 165 | _rc=1 166 | fi 167 | if [ "$_to_be_umount" = "1" ]; then 168 | _pot_umount "$_pname" 169 | else 170 | rmdir "$_destination_mountpoint" 171 | fi 172 | return $_rc 173 | } 174 | -------------------------------------------------------------------------------- /share/pot/create-base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | # supported releases are defined in common.sh 6 | 7 | create-base-help() 8 | { 9 | cat <<-EOH 10 | pot create-base [-h] [-r RELEASE] [-b basename] 11 | -h print this help 12 | -v verbose 13 | -r RELEASE : supported release are: $( _get_valid_releases ) 14 | $( _get_valid_releases | xargs -n1 echo " +" | sort) 15 | -b basename : optional, (default: the release) 16 | EOH 17 | } 18 | 19 | # $1 base name 20 | _cb_zfs() 21 | { 22 | local _bname _dset _mnt 23 | _bname=$1 24 | _dset="${POT_ZFS_ROOT}/bases/${_bname}" 25 | _mnt="${POT_FS_ROOT}/bases/${_bname}" 26 | _info "Create the zfs datasets for base release $_dset" 27 | if ! _zfs_exist "${_dset}" "${_mnt}" ; then 28 | if ! zfs create "$_dset" ; then 29 | return 1 30 | fi 31 | fi 32 | 33 | if ! _zfs_exist "${_dset}/usr.local" "${_mnt}/usr/local" ; then 34 | if ! zfs create -o mountpoint="${_mnt}/usr/local" "$_dset/usr.local" ; then 35 | return 1 36 | fi 37 | fi 38 | 39 | if ! _zfs_exist "${_dset}/custom" "${_mnt}/opt/custom" ; then 40 | if ! zfs create -o mountpoint="${_mnt}/opt/custom" "$_dset/custom" ; then 41 | return 1 42 | fi 43 | fi 44 | return 0 45 | } 46 | 47 | # $1 release 48 | # $2 base name 49 | _cb_tar_dir() 50 | { 51 | local _rel _bname _mnt 52 | if echo "$1" | grep -q "RC" ; then 53 | _rel="$1" 54 | else 55 | _rel="$1"-RELEASE 56 | fi 57 | _bname=$2 58 | _mnt="${POT_FS_ROOT}/bases/${_bname}" 59 | ( 60 | set -e 61 | cd "$_mnt" 62 | tar xkf "${POT_CACHE}/${_rel}"_base.txz 63 | # add release information 64 | echo "$_rel" > .osrelease 65 | cp -a root opt/custom/ 66 | cp -a etc opt/custom/ 67 | cp -a var opt/custom/ 68 | mkdir -p opt/custom/usr.local.etc 69 | mkdir -p opt/custom/usr.home 70 | # they could be part of flavor 71 | mkdir -p usr/ports 72 | 73 | # remove duplicated dirs 74 | chflags -R noschg var/empty 75 | rm -rf etc/ root/ var/ 76 | 77 | # create links 78 | ln -s opt/custom/etc etc 79 | ln -s opt/custom/root root 80 | ln -s opt/custom/var var 81 | if [ ! -e home ]; then 82 | ln -s opt/custom/usr.home home 83 | fi 84 | cd usr 85 | ln -s ../opt/custom/usr.home home 86 | cd local 87 | ln -s ../../opt/custom/usr.local.etc etc 88 | mkdir -p var.db.pkg 89 | cd ../../opt/custom/var/db 90 | rm -rf pkg 91 | ln -s ../../../../usr/local/var.db.pkg pkg 92 | ) 93 | } 94 | 95 | # $1 base name 96 | _cb_base_pot() 97 | { 98 | local _bname _pname _tmp 99 | _bname=$1 100 | _tmp=$(echo "$_bname" | sed 's/\./_/') 101 | _pname="base-$_tmp" 102 | _info "Create the related pot [$_pname]" 103 | if ! _is_pot "$_pname" quiet ; then 104 | pot-cmd create -l 0 -b "$_bname" -p "$_pname" -f fbsd-update 105 | fi 106 | _debug "Taking a snapshot fo $_pname" 107 | _pot_zfs_snap_full "$_pname" 108 | } 109 | 110 | pot-create-base() 111 | { 112 | local _rel _bname 113 | OPTIND=1 114 | while getopts "hr:b:v" _o ; do 115 | case "$_o" in 116 | h) 117 | create-base-help 118 | ${EXIT} 0 119 | ;; 120 | v) 121 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 122 | ;; 123 | r) 124 | if ! _is_valid_release "$OPTARG" ; then 125 | _error "$OPTARG is not a supported release" 126 | create-base-help 127 | ${EXIT} 1 128 | fi 129 | _rel=$OPTARG 130 | ;; 131 | b) 132 | if _is_base "$OPTARG" quiet ; then 133 | _error "$OPTARG is already a base" 134 | ${EXIT} 1 135 | fi 136 | _bname="$OPTARG" 137 | ;; 138 | *) 139 | create-base-help 140 | ${EXIT} 1 141 | ;; 142 | esac 143 | 144 | done 145 | 146 | if [ -z "$_rel" ]; then 147 | _error "option -r is mandatory" 148 | create-base-help 149 | ${EXIT} 1 150 | fi 151 | if [ -z "$_bname" ]; then 152 | _bname=$_rel 153 | _info "Automatically use $_rel as base name" 154 | fi 155 | if [ "$_bname" != "$_rel" ] && _is_valid_release "$_bname" ; then 156 | _error "$_bname has the name of another valid release and that's forbidden" 157 | create-base-help 158 | ${EXIT} 1 159 | fi 160 | if _is_base "$_bname" quiet ; then 161 | _error "$_bname already exist" 162 | ${EXIT} 1 163 | fi 164 | if ! _is_uid0 ; then 165 | ${EXIT} 1 166 | fi 167 | if ! _is_init ; then 168 | ${EXIT} 1 169 | fi 170 | _info "Create a base with release $_rel" 171 | # fetch binaries 172 | if ! _fetch_freebsd "${_rel}" ; then 173 | _error "fetch of ${_rel} RELEASE failed" 174 | ${EXIT} 1 175 | fi 176 | # create zfs dataset 177 | if ! _cb_zfs "${_bname}" ; then 178 | _error "zfs dataset of ${_bname} failed" 179 | ${EXIT} 1 180 | fi 181 | # move binaries to the dataset and create linkx 182 | _cb_tar_dir "${_rel}" "${_bname}" 183 | # create jail level 0 184 | _cb_base_pot "${_bname}" 185 | } 186 | -------------------------------------------------------------------------------- /share/pot/create-fscomp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | create-fscomp-help() 6 | { 7 | cat <<-"EOH" 8 | pot create-fscomp [-hv] -f name 9 | -h print this help 10 | -v verbose 11 | -f name : the fs component name (mandatory) 12 | EOH 13 | } 14 | 15 | pot-create-fscomp() 16 | { 17 | local _dset 18 | _dset= 19 | OPTIND=1 20 | while getopts "hvf:" _o ; do 21 | case "$_o" in 22 | h) 23 | create-fscomp-help 24 | ${EXIT} 0 25 | ;; 26 | v) 27 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 28 | ;; 29 | f) 30 | _dset="${POT_ZFS_ROOT}/fscomp/$OPTARG" 31 | ;; 32 | ?) 33 | create-fscomp-help 34 | ${EXIT} 1 35 | esac 36 | done 37 | 38 | if [ -z "$_dset" ]; then 39 | _error "fs component name is missing" 40 | create-fscomp-help 41 | ${EXIT} 1 42 | fi 43 | if ! _is_init ; then 44 | ${EXIT} 1 45 | fi 46 | if ! _zfs_dataset_valid "$_dset" ; then 47 | if ! _is_uid0 ; then 48 | ${EXIT} 1 49 | fi 50 | if ! zfs create "$_dset" ; then 51 | _error "fs component $_dset creation failed" 52 | ${EXIT} 1 53 | fi 54 | else 55 | _info "fs component $_dset already exists" 56 | fi 57 | return 0 58 | } 59 | -------------------------------------------------------------------------------- /share/pot/create-private-bridge.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | create-private-bridge-help() 6 | { 7 | cat <<-"EOH" 8 | pot create-private-bridge [-hv] [-B name] [-S size] 9 | -h print this help 10 | -v verbose 11 | -B bridge name 12 | -S bridge size (number of host expected) 13 | EOH 14 | } 15 | 16 | # $1 bridge-name 17 | # $2 bridge-size 18 | create-bridge() 19 | { 20 | local _bconf _bname _bsize 21 | _bname=$1 22 | _bsize=$2 23 | _bconf="${POT_FS_ROOT}/bridges/$_bname" 24 | if potnet new-net -s "$_bsize" > "$_bconf" ; then 25 | echo "name=$_bname" >> "$_bconf" 26 | else 27 | rm -f "$_bconf" 28 | _error "Not able to get a valid network with size $_bsize" 29 | ${EXIT} 1 30 | fi 31 | } 32 | 33 | pot-create-private-bridge() 34 | { 35 | local _bname _host_amount 36 | OPTIND=1 37 | while getopts "hvB:S:" _o ; do 38 | case "$_o" in 39 | h) 40 | create-private-bridge-help 41 | ${EXIT} 0 42 | ;; 43 | v) 44 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 45 | ;; 46 | B) 47 | _bname="$OPTARG" 48 | ;; 49 | S) 50 | _host_amount="$OPTARG" 51 | ;; 52 | ?) 53 | create-private-bridge-help 54 | ${EXIT} 1 55 | esac 56 | done 57 | 58 | if [ -z "$_bname" ]; then 59 | _error "A bridge name is mandatory (-B option)" 60 | ${EXIT} 1 61 | fi 62 | if [ -z "$_host_amount" ]; then 63 | _error "The amount of host is mandatory (-S option)" 64 | ${EXIT} 1 65 | fi 66 | if ! _is_potnet_available ; then 67 | _error "potnet is not available! It's needed - cannot proceed" 68 | ${EXIT} 1 69 | fi 70 | if _is_bridge "$_bname" quiet ; then 71 | _error "A bridge with name $_bname already exists" 72 | ${EXIT} 1 73 | fi 74 | if ! _is_uid0 ; then 75 | ${EXIT} 1 76 | fi 77 | mkdir -p "${POT_FS_ROOT}/bridges" 78 | create-bridge "$_bname" "$_host_amount" 79 | } 80 | -------------------------------------------------------------------------------- /share/pot/de-init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | de-init-help() 6 | { 7 | cat <<-"EOH" 8 | pot de-init [-hmvf] [-p pf_file] 9 | -f force : stop all running pots 10 | -p pf_file : remove anchors to this file (empty to skip), 11 | defaults to result of `sysrc -n pf_rules` 12 | -h print this help 13 | -m minimal modifications (alias for `-p ''`) 14 | WARNING: Still destroys POT_ZFS_ROOT 15 | -v verbose 16 | EOH 17 | } 18 | 19 | pot-de-init() 20 | { 21 | local _pots _p _force _zopt _pf_file 22 | _force= 23 | _zopt= 24 | _pf_file="$(sysrc -n pf_rules)" 25 | OPTIND=1 26 | while getopts "fhmvp:" _o ; do 27 | case "$_o" in 28 | f) 29 | _force="force" 30 | ;; 31 | h) 32 | de-init-help 33 | ${EXIT} 0 34 | ;; 35 | m) 36 | _pf_file="" 37 | ;; 38 | p) 39 | _pf_file="$OPTARG" 40 | ;; 41 | v) 42 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 43 | _zopt="-v" 44 | ;; 45 | ?) 46 | de-init-help 47 | ${EXIT} 1 48 | ;; 49 | esac 50 | done 51 | _pots=_get_pot_list 52 | if ! _is_uid0 ; then 53 | ${EXIT} 1 54 | fi 55 | for _p in $_pots ; do 56 | if _is_pot_running "$_p" ; then 57 | if [ -n "$_force" ]; then 58 | _debug "Stop the pot $_p" 59 | pot-cmd stop "$_p" 60 | else 61 | _error "At least on pot is still running. Use -f to force the stop of all pots" 62 | ${EXIT} 1 63 | fi 64 | fi 65 | done 66 | # Remove pot dataset 67 | if ! _zfs_dataset_valid "${POT_ZFS_ROOT}" ; then 68 | _info "no root dataset found ($POT_ZFS_ROOT)" 69 | else 70 | _info "Deinstall pot ($POT_ZFS_ROOT)" 71 | zfs destroy -r $_zopt "${POT_ZFS_ROOT}" 72 | fi 73 | echo "zfs datasets have been removed" 74 | # Remove pf entries if needed 75 | if [ -n "$_pf_file" ]; then 76 | sed -i '' '/^nat-anchor pot-nat$/d' "$_pf_file" 77 | sed -i '' '/^rdr-anchor "pot-rdr\/\*"$/d' "$_pf_file" 78 | echo "pf configuration file should be clean" 79 | echo " - please check $_pf_file and reload it" 80 | fi 81 | # Final message 82 | echo "check your rc.conf for potential leftovers variable like:" 83 | echo ' syslogd_flags' 84 | echo ' pot_enable' 85 | echo "Please, consider to write a feedback email to pizzamig at FreeBSD dot org" 86 | echo "It gives us the opportunity to learn and improve" 87 | } 88 | -------------------------------------------------------------------------------- /share/pot/exec.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | exec-help() 6 | { 7 | cat <<-"EOH" 8 | pot exec [-hvdt] [-e var=value] [-u username] [-U username] 9 | -p pot COMMAND 10 | -h print this help 11 | -v verbose 12 | -d detach, run in background 13 | -t allocate pty 14 | -e var=value : set environment variable, can be repeated 15 | -u username: The username from the host environment as whom the 16 | command should run 17 | -U username: The username from the pot environment as whom the 18 | command should run 19 | -p pot : the pot image 20 | 21 | COMMAND is the command to execute and will be executed in the 22 | username's $HOME 23 | EOH 24 | } 25 | 26 | # Actually send signal to process inside pot 27 | # $1 pot name 28 | # $2 detach 29 | # $3 env (encoded with save_params) 30 | # $4 alloc_pty 31 | # $5 user_host 32 | # $6 user_pot 33 | # $7-$n command/args 34 | _exec_cmd() 35 | { 36 | local _pname _detach _env _alloc_pty _user_host _user_pot 37 | local _cmd 38 | 39 | _pname=$1 40 | _detach=$2 41 | _env=$3 42 | _alloc_pty=$4 43 | _user_host=$5 44 | _user_pot=$6 45 | shift 6 # $@ contains command/args now 46 | 47 | _debug "Exec in $_pname, cmd: $*" 48 | 49 | # assemble command 50 | _cmd= 51 | if [ "$_alloc_pty" = "YES" ]; then 52 | _cmd="$_cmd"$(_save_params "script" "-q" "/dev/null") 53 | fi 54 | _cmd="$_cmd"$(_save_params "jexec" "-l") 55 | if [ -n "$_user_host" ]; then 56 | _cmd="$_cmd"$(_save_params "-u" "$_user_host") 57 | elif [ -n "$_user_pot" ]; then 58 | _cmd="$_cmd"$(_save_params "-U" "$_user_pot") 59 | fi 60 | _cmd="$_cmd"$(_save_params "$_pname") 61 | _cmd="$_cmd$_env"$(_save_params "$@") 62 | 63 | # execute command 64 | eval "set -- $_cmd" 65 | if [ "$_detach" = "YES" ]; then 66 | nohup "$@" >/dev/null 2>&1 & 67 | else 68 | "$@" 69 | fi 70 | _ret=$? 71 | 72 | return "$_ret" 73 | } 74 | 75 | pot-exec() 76 | { 77 | local _pname _detach _env _alloc_pty _user_host _user_pot _ret 78 | _pname= 79 | _detach="NO" 80 | _env=$(_save_params "env") 81 | _alloc_pty="NO" 82 | _user_host= 83 | _user_pot= 84 | OPTIND=1 85 | while getopts "hvdtp:e:u:U:" _o ; do 86 | case "$_o" in 87 | h) 88 | exec-help 89 | ${EXIT} 0 90 | ;; 91 | v) 92 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 93 | ;; 94 | 95 | d) 96 | _detach="YES" 97 | ;; 98 | t) 99 | _alloc_pty="YES" 100 | ;; 101 | e) 102 | if [ "$OPTARG" = "${OPTARG#*=}" ]; then 103 | # the argument doesn't have an equal sign 104 | _error "$OPTARG not in a valid form" 105 | _error "VARIABLE=value is accetped" 106 | exec-help 107 | ${EXIT} 1 108 | fi 109 | _env="$_env"$(_save_params "$OPTARG") 110 | ;; 111 | u) 112 | _user_host="$OPTARG" 113 | ;; 114 | U) 115 | _user_pot="$OPTARG" 116 | ;; 117 | p) 118 | _pname="$OPTARG" 119 | ;; 120 | *) 121 | exec-help 122 | ${EXIT} 1 123 | esac 124 | done 125 | 126 | shift $((OPTIND-1)) 127 | 128 | if [ "$#" -eq 0 ]; then 129 | _error "A command is mandatory" 130 | ${EXIT} 1 131 | fi 132 | 133 | if [ -z "$_pname" ]; then 134 | _error "A pot name is mandatory" 135 | exec-help 136 | ${EXIT} 1 137 | fi 138 | 139 | if [ -n "$_user_host" ] && [ -n "$_user_pot" ]; then 140 | _error "Parameters -u and -U are mutually exclusive" 141 | ${EXIT} 1 142 | fi 143 | 144 | if ! _is_pot_running "$_pname" ; then 145 | _error "The pot is not running" 146 | ${EXIT} 1 147 | fi 148 | 149 | if ! _is_uid0 ; then 150 | ${EXIT} 1 151 | fi 152 | 153 | _exec_cmd "$_pname" "$_detach" "$_env" \ 154 | "$_alloc_pty" "$_user_host" "$_user_pot" "$@" 155 | } 156 | -------------------------------------------------------------------------------- /share/pot/export-ports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | export-ports-help() 6 | { 7 | cat <<-"EOH" 8 | pot export-ports configure exported ports - public-bridge only 9 | pot export-ports [-hv] -p pot [-S] -e [proto:]port[:pot_port] ... 10 | -h print this help 11 | -v verbose 12 | -p pot : the working pot 13 | -e [proto:]port[:pot_port] : port(s) to export 14 | proto can be tcp (default) or udp 15 | port is the port to export 16 | pot_port : a static port to NAT to inside the pot 17 | dynamically allocated by default 18 | This option can be repeated to export multiple ports. 19 | 20 | Examples: 21 | -e 80 export proto tcp port 80 to a dynamic port 22 | -e 80:30000 export proto tcp port 80 to pot_port 30000 23 | -e tcp:80:30000 export proto tcp port 80 to pot_port 30000 24 | -e udp:53:30053 export proto udp port 53 to pot_port 30053 25 | EOH 26 | } 27 | 28 | # $1 pot 29 | # $2 port list 30 | _export_ports() 31 | { 32 | local _pname _ports _cdir 33 | _pname="$1" 34 | _ports="$2" 35 | _cdir=$POT_FS_ROOT/jails/$_pname/conf 36 | sed -i '' -e "/pot.export.ports=.*/d" "$_cdir/pot.conf" 37 | echo "pot.export.ports=$_ports" >> "$_cdir/pot.conf" 38 | } 39 | 40 | pot-export-ports() 41 | { 42 | local _pname _ports 43 | _pname= 44 | _ports= 45 | OPTIND=1 46 | 47 | while getopts "hvp:e:" _o ; do 48 | case "$_o" in 49 | h) 50 | export-ports-help 51 | return 0 52 | ;; 53 | v) 54 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 55 | ;; 56 | p) 57 | _pname="$OPTARG" 58 | ;; 59 | e) 60 | if ! _is_export_port_valid "${OPTARG}" ; then 61 | _error "$OPTARG is not a valid port number" 62 | export-ports-help 63 | return 1 64 | fi 65 | if [ -z "$_ports" ]; then 66 | _ports="$OPTARG" 67 | else 68 | _ports="$_ports $OPTARG" 69 | fi 70 | ;; 71 | *) 72 | export-ports-help 73 | return 1 74 | ;; 75 | esac 76 | done 77 | 78 | if [ -z "$_pname" ]; then 79 | _error "A pot name is mandatory" 80 | export-ports-help 81 | return 1 82 | fi 83 | if ! _is_pot "$_pname" ; then 84 | _error "$_pname is not a valid pot name" 85 | export-ports-help 86 | return 1 87 | fi 88 | if [ -z "${_ports}" ]; then 89 | _error "One port has to be specified" 90 | export-ports-help 91 | return 1 92 | fi 93 | if [ "$(_get_pot_network_type "$_pname")" != "public-bridge" ] && 94 | [ "$(_get_pot_network_type "$_pname")" != "private-bridge" ] ; then 95 | _info "Only public-bridge and private-bridge network type can export ports - this setting will be ignored during start" 96 | fi 97 | if [ "$( _get_pot_network_stack "$_pname" )" = "ipv6" ]; then 98 | _info "Only ipv4 can export ports, on ipv6 the pot has already a unique address - this setting will be ignored during start" 99 | fi 100 | _debug "Exporting the following ports: $_ports" 101 | if ! _is_uid0 ; then 102 | return 1 103 | fi 104 | _export_ports "$_pname" "$_ports" 105 | } 106 | -------------------------------------------------------------------------------- /share/pot/get-attribute.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | get-attribute-help() 6 | { 7 | cat <<-EOH 8 | pot get-attribute [-hvq] -p pot -A attribute 9 | -h print this help 10 | -v verbose 11 | -q quiet 12 | -p pot : the working pot 13 | -A attribute : get value of attribute, one of 14 | $(echo "$_POT_RW_ATTRIBUTES $_POT_RO_ATTRIBUTES \ 15 | $_POT_JAIL_RW_ATTRIBUTES" | xargs -n1 echo " +" | sort) 16 | EOH 17 | } 18 | 19 | pot-get-attribute() 20 | { 21 | local _pname _attr _value _quiet 22 | _pname= 23 | _attr= 24 | _value= 25 | _quiet="no" 26 | OPTIND=1 27 | while getopts "hvqp:A:V:" _o ; do 28 | case "$_o" in 29 | h) 30 | get-attribute-help 31 | ${EXIT} 0 32 | ;; 33 | v) 34 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 35 | ;; 36 | q) 37 | _quiet="quiet" 38 | ;; 39 | p) 40 | _pname="$OPTARG" 41 | ;; 42 | A) 43 | _attr="$OPTARG" 44 | ;; 45 | *) 46 | get-attribute-help 47 | ${EXIT} 1 48 | esac 49 | done 50 | 51 | if [ -z "$_pname" ]; then 52 | _error "A pot name is mandatory" 53 | get-attribute-help 54 | ${EXIT} 1 55 | fi 56 | if [ -z "$_attr" ]; then 57 | _error "Option -A is mandatory" 58 | get-attribute-help 59 | ${EXIT} 1 60 | fi 61 | if ! _is_pot "$_pname" "$_quiet" ; then 62 | if [ "$_quiet" != "quiet" ]; then 63 | _error "$_pname is not a valid pot" 64 | get-attribute-help 65 | fi 66 | ${EXIT} 1 67 | fi 68 | # shellcheck disable=SC2086 69 | if ! _is_in_list "$_attr" $_POT_RW_ATTRIBUTES $_POT_RO_ATTRIBUTES $_POT_JAIL_RW_ATTRIBUTES ; then 70 | _error "$_attr is not a valid attribute" 71 | get-attribute-help 72 | ${EXIT} 1 73 | fi 74 | _value=$(_get_conf_var "$_pname" "pot.attr.$_attr") 75 | if [ "$_quiet" = "quiet" ]; then 76 | echo "$_value" 77 | else 78 | if [ -z "$_value" ]; then 79 | _info "The attribute $_attr is not set for the pot $_pname" 80 | else 81 | _info "$_attr: $_value" 82 | fi 83 | fi 84 | return 0 85 | } 86 | -------------------------------------------------------------------------------- /share/pot/get-rss.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | get-rss-help() 6 | { 7 | cat <<-"EOH" 8 | pot get-rss [-h] -p pot 9 | -h print this help 10 | -v verbose 11 | -p pot : the working pot 12 | -J : output in JSON format 13 | EOH 14 | } 15 | 16 | # $1 pot name 17 | # $2 json format 18 | print_rss() 19 | { 20 | local _rss _pname _json _pcpu _mem _cputime _vmem _clockrate _cputimecounter _swap 21 | _pname=$1 22 | _json=$2 23 | _clockrate="$( sysctl -n hw.clockrate )" 24 | _rss="$( rctl -u jail:"$_pname" )" 25 | _pcpu="$( echo "$_rss" | grep ^pcpu | cut -d'=' -f 2 )" 26 | _cputimecounter="$( echo "$_rss" | grep ^cputime | cut -d'=' -f 2 )" 27 | _mem="$( echo "$_rss" | grep ^memoryuse | cut -d'=' -f 2 )" 28 | _vmem="$( echo "$_rss" | grep ^vmemoryuse | cut -d'=' -f 2 )" 29 | _swap="$( echo "$_rss" | grep ^swapuse | cut -d'=' -f 2 )" 30 | _cputime="$( printf "scale=3\n %s * %s / 100\n" "$_clockrate" "$_pcpu" | bc )" 31 | if [ "$_json" = "YES" ]; then 32 | echo "{ \"ResourceUsage\": { \"MemoryStats\": { \"RSS\" : $_mem, \"Swap\" : $_swap }, \"CpuStats\": { \"TotalTicks\": $_cputime, \"Percent\": $_pcpu } } } " 33 | else 34 | echo "Resource usage by the pot $_pname" 35 | printf "\\tcpu time (ticks spent) : %s\\n" "$_cputimecounter" 36 | printf "\\tcpu time (MHz) : %s\\n" "$_cputime" 37 | printf "\\tpcpu (%%) : %s\\n" "$_pcpu" 38 | printf "\\tvirtual memory : %s\\n" "$_vmem" 39 | printf "\\tphysical memory : %s\\n" "$_mem" 40 | printf "\\tswap memory : %s\\n" "$_swap" 41 | fi 42 | } 43 | 44 | pot-get-rss() 45 | { 46 | local _pname _o _json 47 | _pname= 48 | _json= 49 | OPTIND=1 50 | while getopts "hvp:J" _o ; do 51 | case "$_o" in 52 | h) 53 | get-rss-help 54 | ${EXIT} 0 55 | ;; 56 | v) 57 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 58 | ;; 59 | p) 60 | _pname="$OPTARG" 61 | ;; 62 | J) 63 | _json="YES" 64 | ;; 65 | *) 66 | get-rss-help 67 | ${EXIT} 1 68 | esac 69 | done 70 | if [ -z "$_pname" ]; then 71 | _error "A pot name is mandatory" 72 | get-rss-help 73 | ${EXIT} 1 74 | fi 75 | if ! _is_pot_running "$_pname" ; then 76 | _error "The pot $_pname is not running" 77 | ${EXIT} 1 78 | fi 79 | if ! _is_uid0 ; then 80 | ${EXIT} 1 81 | fi 82 | if ! _is_rctl_available ; then 83 | _error "To get resource usage, rctl has to be enabled" 84 | ${EXIT} 1 85 | fi 86 | print_rss "$_pname" "$_json" 87 | ${EXIT} 0 88 | } 89 | -------------------------------------------------------------------------------- /share/pot/help.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | 4 | pot-help() 5 | { 6 | local _cmd _func 7 | _cmd=$1 8 | shift 9 | case "${_cmd}" in 10 | ls) 11 | _cmd=list 12 | ;; 13 | rollback) 14 | _cmd=revert 15 | ;; 16 | run) 17 | _cmd=term 18 | ;; 19 | snap) 20 | _cmd=snapshot 21 | ;; 22 | set-attr) 23 | _cmd=set-attribute 24 | ;; 25 | get-attr) 26 | _cmd=get-attribute 27 | ;; 28 | esac 29 | if [ ! -r "${_POT_INCLUDE}/${_cmd}.sh" ]; then 30 | _error "Command ${_cmd} unkown" 31 | exit 1 32 | fi 33 | # shellcheck disable=SC1090 34 | . "${_POT_INCLUDE}/${_cmd}.sh" 35 | _func=${_cmd}-help 36 | $_func "$@" 37 | } 38 | -------------------------------------------------------------------------------- /share/pot/last-run-stats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | last-run-stats-help() 6 | { 7 | cat <<-"EOH" 8 | pot last-run-stats [-hv] [-p pname] 9 | -h print this help 10 | -v verbose 11 | -p pname : pot name 12 | EOH 13 | } 14 | 15 | pot-last-run-stats() 16 | { 17 | local _pname 18 | _pname="" 19 | OPTIND=1 20 | while getopts "hvp:" _o ; do 21 | case "$_o" in 22 | h) 23 | last-run-stats-help 24 | ${EXIT} 0 25 | ;; 26 | v) 27 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 28 | ;; 29 | p) 30 | _pname="$OPTARG" 31 | ;; 32 | *) 33 | last-run-stats-help 34 | ${EXIT} 1 35 | ;; 36 | esac 37 | done 38 | if [ -z "$_pname" ]; then 39 | _error "A pot name is mandatory" 40 | last-run-stats-help 41 | ${EXIT} 1 42 | fi 43 | if ! _is_pot "$_pname"; then 44 | _error "$_pname is not a pot" 45 | ${EXIT} 1 46 | fi 47 | _confdir="${POT_FS_ROOT}/jails/$_pname/conf" 48 | cat "$_confdir/.last_run_stats" 2>/dev/null || echo "{}" 49 | } 50 | -------------------------------------------------------------------------------- /share/pot/mount-out.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | mount-out-help() 6 | { 7 | cat <<-"EOH" 8 | pot mount-out [-hvwr] -p pot -m mnt 9 | -h print this help 10 | -v verbose 11 | -p pot : the working pot 12 | -m mnt : the mount point inside the pot 13 | EOH 14 | } 15 | 16 | # $1 pot 17 | # $2 mount point 18 | _is_mountpoint_used() 19 | { 20 | local _pname _mnt_p _proot 21 | _pname="$1" 22 | _mnt_p="${2}" 23 | _conf=$POT_FS_ROOT/jails/$_pname/conf/fscomp.conf 24 | _proot=$POT_FS_ROOT/jails/$_pname/m 25 | ## spaces in this sequences of grep have been introduced to detect exact matches only 26 | ## a pattern like /mnt/test would match /mnt/test and /mnt/test2 27 | ## with those spaces we try be more precise in detecting the exact match 28 | if grep -q " $_mnt_p$" "$_conf" || 29 | grep -q " $_mnt_p " "$_conf" ; then 30 | # mount point already used 31 | return 0 # true 32 | fi 33 | if grep -q "$_proot/$_mnt_p " "$_conf" ; then 34 | # mountpoint used as source directory ?? wtf 35 | _error "The mountpoint is already used as source directory mount-out" 36 | return 0 # true 37 | fi 38 | return 1 # false, mountpoint not used 39 | } 40 | 41 | # $1 pot 42 | # $2 mount point 43 | _mountpoint_validation() 44 | { 45 | local _pname _mnt_p _mpdir _mounted _real_mnt 46 | _pname="$1" 47 | _mnt_p="$2" 48 | _mpdir=$POT_FS_ROOT/jails/$_pname/m 49 | _mounted=false # false 50 | if ! _is_pot_running "$_pname" ; then 51 | _mounted=true # true 52 | if ! _pot_mount "$_pname" >/dev/null ; then 53 | _error "Pot $_pname failed to mount" 54 | return 1 # false 55 | fi 56 | fi 57 | _real_mnt=$( chroot "$_mpdir" /bin/realpath "$_mnt_p") 58 | if eval $_mounted ; then 59 | _pot_umount "$_pname" >/dev/null 60 | fi 61 | if ! _is_mountpoint_used "$_pname" "$_real_mnt" ; then 62 | _error "The mount point $_mnt_p is not in use" 63 | return 1 # false 64 | fi 65 | echo "$_real_mnt" 66 | return 0 # true 67 | } 68 | 69 | # $1 pot 70 | # $2 mount point 71 | _umount_mnt_p() 72 | { 73 | local _pname _mnt_p _pdir 74 | _pname="$1" 75 | # Removing the trailing / 76 | _mnt_p="${2#/}" 77 | _pdir=$POT_FS_ROOT/jails/$_pname 78 | # absolute pathname of the mount point with escape character 79 | _sed_string="$(echo "$_pdir/m/$_mnt_p" | sed 's#/#\\/#g')" 80 | _debug "umount_mnt_p: mnt_p:$_pdir/m/$_mnt_p" 81 | ${SED} -E -i '' " $_sed_string$| $_sed_string /d" "$_pdir/conf/fscomp.conf" 82 | 83 | if _is_pot_running "$_pname" ; then 84 | if _umount "$_pdir/m/$_mnt_p" ; then 85 | _debug "Umounted $_mnt_p on $_pname" 86 | else 87 | _error "Error umounting $_mnt_p on $_pname" 88 | fi 89 | fi 90 | } 91 | 92 | pot-mount-out() 93 | { 94 | local _pname _mnt_p _real_mnt_p 95 | OPTIND=1 96 | _pname= 97 | _mnt_p= 98 | logger -t pot -p local0.debug -- "mount-out: $*" 99 | while getopts "hvp:m:" _o ; do 100 | case "$_o" in 101 | h) 102 | mount-out-help 103 | return 0 104 | ;; 105 | v) 106 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 107 | ;; 108 | p) 109 | _pname="$OPTARG" 110 | ;; 111 | m) 112 | _mnt_p="$OPTARG" 113 | ;; 114 | *) 115 | mount-out-help 116 | return 1 117 | ;; 118 | esac 119 | done 120 | 121 | if [ -z "$_pname" ]; then 122 | _error "A pot name is mandatory" 123 | mount-out-help 124 | return 1 125 | fi 126 | if [ -z "$_mnt_p" ]; then 127 | _error "A mount point is mandatory" 128 | mount-out-help 129 | return 1 130 | fi 131 | if ! _is_absolute_path "$_mnt_p" ; then 132 | _error "The mount point has to be an absolute pathname" 133 | return 1 134 | fi 135 | if [ "${_mnt_p}" = "/" ]; then 136 | _error "/ is not a valid mount point" 137 | return 1 138 | fi 139 | 140 | if ! _is_pot "$_pname" ; then 141 | _error "pot $_pname is not valid" 142 | mount-out-help 143 | return 1 144 | fi 145 | if ! _is_uid0 ; then 146 | return 1 147 | fi 148 | if ! _real_mnt_p="$(_mountpoint_validation "$_pname" "$_mnt_p" )" ; then 149 | echo "$_real_mnt_p" 150 | _error "The mountpoint is not valid!" 151 | return 1 152 | fi 153 | _umount_mnt_p "$_pname" "$_real_mnt_p" 154 | return $? 155 | } 156 | -------------------------------------------------------------------------------- /share/pot/prune.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | 4 | prune-help() 5 | { 6 | cat <<-"EOH" 7 | pot prune [-hvq] 8 | -h print this help 9 | -v verbose 10 | -q quite - prune with no output 11 | -g grace_period - do not prune pots that just finished executing 12 | -n dry-run - do not destroy anything 13 | EOH 14 | } 15 | 16 | # $1 pot name 17 | _prune_pot() 18 | { 19 | local _pname _quiet _dry_run _grace_period _confdir 20 | _pname=$1 21 | _dry_run=$2 22 | _quiet=$3 23 | _grace_period=$4 24 | _confdir="${POT_FS_ROOT}/jails/$_pname/conf" 25 | 26 | if ! _is_pot_running "$_pname" ; then 27 | if ! _is_pot_prunable "$_pname" ; then 28 | return 29 | fi 30 | if [ "$( _get_conf_var "$_pname" "pot.attr.to-be-pruned" )" != "YES" ]; then 31 | return 32 | fi 33 | if [ "$_grace_period" = "YES" ]; then 34 | # check if just finished running 35 | if find "$_confdir/.last_run_stats" -mtime -1m 2>/dev/null | \ 36 | grep -q "."; then 37 | return 38 | fi 39 | 40 | sleep 2 # give pot-start a chance to write .last_run_stats 41 | 42 | # check again if just finished running 43 | if find "$_confdir/.last_run_stats" -mtime -1m 2>/dev/null | \ 44 | grep -q "."; then 45 | return 46 | fi 47 | 48 | if _is_pot_running "$_pname" ; then 49 | return 50 | fi 51 | fi 52 | 53 | _info "Pruning $_pname" 54 | if [ "$_dry_run" = "YES" ]; then 55 | return 56 | fi 57 | if _is_pot_running "$_pname" ; then 58 | pot-cmd stop "$_pname" 59 | fi 60 | if ! pot-cmd destroy -p "$_pname" ; then 61 | _qerror "$_quiet" "Error while pruning $_pname" 62 | else 63 | _info "Pruned $_pname" 64 | fi 65 | fi 66 | } 67 | 68 | _prune_pots() 69 | { 70 | local _pots _dry_run _quiet _grace_period _p 71 | _dry_run="$1" 72 | _quiet="$2" 73 | _grace_period="$3" 74 | _pots="$( _get_pot_list )" 75 | for _p in $_pots; do 76 | _prune_pot "$_p" "$_dry_run" "$_quiet" "$_grace_period" 77 | done 78 | } 79 | 80 | pot-prune() 81 | { 82 | local _quiet _dry_run 83 | _quiet= 84 | _grace_period="NO" 85 | _dry_run="NO" 86 | OPTIND=1 87 | while getopts "hvqgn" _o ; do 88 | case "$_o" in 89 | h) 90 | prune-help 91 | ${EXIT} 0 92 | ;; 93 | v) 94 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 95 | ;; 96 | q) 97 | _quiet="quiet" 98 | ;; 99 | g) 100 | _grace_period="YES" 101 | ;; 102 | n) 103 | _dry_run="YES" 104 | ;; 105 | *) 106 | prune-help 107 | ${EXIT} 1 108 | ;; 109 | esac 110 | done 111 | if ! _is_uid0 ; then 112 | ${EXIT} 1 113 | fi 114 | _prune_pots "$_dry_run" "$_quiet" "$_grace_period" 115 | } 116 | -------------------------------------------------------------------------------- /share/pot/ps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | 4 | ps-help() 5 | { 6 | cat <<-"EOH" 7 | pot ps [-hvq] 8 | -h print this help 9 | -v verbose 10 | -q quiet : only print pot names 11 | EOH 12 | } 13 | 14 | # $1 pot name 15 | _ps_pot() 16 | { 17 | local _pname _quiet 18 | _pname=$1 19 | _quiet=$2 20 | if _is_pot_running "$_pname" ; then 21 | if [ "$_quiet" = "quiet" ]; then 22 | echo "$_pname" 23 | return 24 | fi 25 | echo "$_pname" 26 | fi 27 | } 28 | 29 | _ps_pots() 30 | { 31 | local _pots _quiet _p 32 | _quiet="$1" 33 | _pots="$( _get_pot_list )" 34 | for _p in $_pots ; do 35 | _ps_pot "$_p" "$_quiet" 36 | done 37 | } 38 | 39 | pot-ps() 40 | { 41 | local _quiet 42 | _quiet= 43 | OPTIND=1 44 | while getopts "hvq" _o ; do 45 | case "$_o" in 46 | h) 47 | ps-help 48 | ${EXIT} 0 49 | ;; 50 | v) 51 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 52 | ;; 53 | q) 54 | _quiet="quiet" 55 | ;; 56 | *) 57 | ps-help 58 | ${EXIT} 1 59 | ;; 60 | esac 61 | done 62 | if [ -z "$_quiet" ]; then 63 | if ! _is_uid0 quiet ; then 64 | _info "Need privileges to read internal network status" 65 | elif _is_vnet_up ; then 66 | _info "Internal network up" 67 | else 68 | _info "Internal network down" 69 | fi 70 | fi 71 | _ps_pots "$_quiet" 72 | } 73 | -------------------------------------------------------------------------------- /share/pot/purge-snapshots.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | purge-snapshots-help() 6 | { 7 | cat <<-"EOH" 8 | pot purge-snapshots [-hva] -p potname|-f fscomp 9 | -h print this help 10 | -v verbose 11 | -p potname : the pot target of the purge-snapshots 12 | -f fscomp : the fs component target of the purge-snapshots 13 | -a remove all snapshot, including the latest one 14 | EOH 15 | } 16 | 17 | # $1 zfs dataset 18 | _zfs_old_snapshots() 19 | { 20 | local _dset 21 | _output="$(zfs list -d 1 -H -t snap "$_dset" | sort -r | sed '1d' | sort | cut -d'@' -f2 | cut -f1 )" 22 | echo "$_output" 23 | } 24 | 25 | # $1 zfs dataset 26 | _zfs_all_snapshots() 27 | { 28 | local _dset 29 | _output="$(zfs list -d 1 -H -t snap "$_dset" | sort | cut -d'@' -f2 | cut -f1 )" 30 | echo "$_output" 31 | } 32 | 33 | _purge_dset() 34 | { 35 | local _dset _snaps _all_snap 36 | _dset=$1 37 | _all_snap=${2:-"NO"} 38 | if [ "$_all_snap" = "YES" ]; then 39 | _snaps="$(_zfs_all_snapshots "$_dset")" 40 | else 41 | _snaps="$(_zfs_old_snapshots "$_dset")" 42 | fi 43 | if [ -z "$_snaps" ]; then 44 | return 45 | fi 46 | for _s in $_snaps ; do 47 | zfs destroy -r "${_dset}@${_s}" 48 | done 49 | } 50 | 51 | pot-purge-snapshots() 52 | { 53 | local _obj _objname _all_snap 54 | _all_snap="NO" 55 | _obj="" 56 | OPTIND=1 57 | while getopts "hvp:f:a" _o ; do 58 | case "$_o" in 59 | h) 60 | purge-snapshots-help 61 | ${EXIT} 0 62 | ;; 63 | v) 64 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 65 | ;; 66 | p) 67 | if [ -z "$_obj" ]; then 68 | _obj="pot" 69 | _objname="$OPTARG" 70 | else 71 | _error "-p|-f are exclusive" 72 | purge-snapshots-help 73 | ${EXIT} 1 74 | fi 75 | ;; 76 | f) 77 | if [ -z "$_obj" ]; then 78 | _obj="fscomp" 79 | _objname="$OPTARG" 80 | else 81 | _error "-p|-f are exclusive" 82 | purge-snapshots-help 83 | ${EXIT} 1 84 | fi 85 | ;; 86 | a) 87 | _all_snap="YES" 88 | ;; 89 | *) 90 | purge-snapshots-help 91 | ${EXIT} 1 92 | ;; 93 | esac 94 | done 95 | if [ -z "$_obj" ]; then 96 | _error "one of -p|-f has to be used" 97 | purge-snapshots-help 98 | return 1 99 | fi 100 | if [ -z "$_objname" ]; then 101 | _error "-p|-f options need an argument" 102 | purge-snapshots-help 103 | return 1 104 | fi 105 | case $_obj in 106 | "pot") 107 | if ! _is_pot "$_objname" ; then 108 | _error "$_objname is not a pot!" 109 | purge-snapshots-help 110 | return 1 111 | fi 112 | _purge_dset "${POT_ZFS_ROOT}/jails/$_objname" "$_all_snap" 113 | ;; 114 | "fscomp") 115 | if ! _zfs_exist "${POT_ZFS_ROOT}/fscomp/$_objname" "${POT_FS_ROOT}/fscomp/$_objname" ; then 116 | _error "$_objname is not a valid fscomp" 117 | purge-snapshots-help 118 | return 1 119 | fi 120 | if ! _is_uid0 ; then 121 | return 1 122 | fi 123 | _purge_dset "${POT_ZFS_ROOT}/fscomp/$_objname" "$_all_snap" 124 | ;; 125 | esac 126 | return 0 127 | } 128 | -------------------------------------------------------------------------------- /share/pot/revert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | revert-help() 6 | { 7 | cat <<-"EOH" 8 | pot revert [-hv] -p potname|-f fscomp 9 | -h print this help 10 | -v verbose 11 | -p potname : the pot target of the revert 12 | -f fscomp : the fs component target of the revert 13 | EOH 14 | } 15 | 16 | # $1 pot name 17 | _pot_zfs_rollback() 18 | { 19 | local _pname _pdset _snap 20 | _pname=$1 21 | _pdset=${POT_ZFS_ROOT}/jails/$_pname 22 | for _dset in $( zfs list -o name -H -r "$_pdset" | sort -r | tr '\n' ' ') ; do 23 | _snap="$( _zfs_last_snap "$_dset")" 24 | if [ -z "$_snap" ]; then 25 | _info "$_dset has not snapshot - no possible rollback" 26 | continue 27 | fi 28 | zfs rollback "$_dset"@"$_snap" 29 | done 30 | } 31 | 32 | _fscomp_zfs_rollback() 33 | { 34 | local _fscomp _fdset _snap 35 | _fscomp=$1 36 | _fdset=${POT_ZFS_ROOT}/fscomp/$_fscomp 37 | for _dset in $( zfs list -o name -H -r "$_fdset" | sort -r | tr '\n' ' ') ; do 38 | _snap="$( _zfs_last_snap "$_dset")" 39 | if [ -z "$_snap" ]; then 40 | _info "$_dset has not snapshot - no possible rollback" 41 | continue 42 | fi 43 | zfs rollback "$_dset@$_snap" 44 | done 45 | } 46 | 47 | pot-revert() 48 | { 49 | local _obj 50 | _obj= 51 | OPTIND=1 52 | while getopts "hvp:f:" _o ; do 53 | case "$_o" in 54 | h) 55 | revert-help 56 | ${EXIT} 0 57 | ;; 58 | v) 59 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 60 | ;; 61 | p) 62 | if [ -z "$_obj" ]; then 63 | _obj="pot" 64 | _objname="$OPTARG" 65 | else 66 | _error "-p|-f are exclusive" 67 | revert-help 68 | ${EXIT} 1 69 | fi 70 | ;; 71 | f) 72 | if [ -z "$_obj" ]; then 73 | _obj="fscomp" 74 | _objname="$OPTARG" 75 | else 76 | _error "-p|-f are exclusive" 77 | revert-help 78 | ${EXIT} 1 79 | fi 80 | ;; 81 | ?) 82 | revert-help 83 | ${EXIT} 1 84 | ;; 85 | esac 86 | done 87 | if [ -z "$_obj" ]; then 88 | _error "one of -p|-f has to be used" 89 | revert-help 90 | $EXIT 1 91 | fi 92 | if [ -z "$_objname" ]; then 93 | _error "-p|-f options need an argument" 94 | revert-help 95 | ${EXIT} 1 96 | fi 97 | case $_obj in 98 | "pot") 99 | if ! _is_pot "$_objname" ; then 100 | _error "$_objname is not a pot!" 101 | revert-help 102 | ${EXIT} 1 103 | fi 104 | if _is_pot_running "$_objname" ; then 105 | _error "The pot $_objname is still running. Revert is possible only for stopped pots" 106 | ${EXIT} 1 107 | fi 108 | if ! _is_uid0 ; then 109 | ${EXIT} 1 110 | fi 111 | _pot_zfs_rollback "$_objname" 112 | ;; 113 | "fscomp") 114 | if ! _zfs_exist "${POT_ZFS_ROOT}/fscomp/$_objname" "${POT_FS_ROOT}/fscomp/$_objname" ; then 115 | _error "$_objname is not a valid fscomp" 116 | revert-help 117 | ${EXIT} 1 118 | fi 119 | if ! _is_uid0 ; then 120 | ${EXIT} 1 121 | fi 122 | _fscomp_zfs_rollback "$_objname" 123 | ;; 124 | esac 125 | } 126 | -------------------------------------------------------------------------------- /share/pot/set-cmd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | set-cmd-help() { 6 | cat <<-"EOH" 7 | pot set-cmd [-hv] -p pot -c cmd 8 | -h print this help 9 | -v verbose 10 | -p pot : the working pot 11 | -c cmd : the command line to start the container 12 | EOH 13 | } 14 | 15 | pot-set-cmd() 16 | { 17 | local _pname _cmd 18 | _cmd= 19 | _pname= 20 | OPTIND=1 21 | while getopts "hvp:c:" _o ; do 22 | case "$_o" in 23 | h) 24 | set-cmd-help 25 | return 0 26 | ;; 27 | v) 28 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 29 | ;; 30 | c) 31 | _cmd="$OPTARG" 32 | ;; 33 | p) 34 | _pname="$OPTARG" 35 | ;; 36 | *) 37 | set-cmd-help 38 | return 1 39 | esac 40 | done 41 | 42 | if [ -z "$_pname" ]; then 43 | _error "A pot name is mandatory" 44 | set-cmd-help 45 | return 1 46 | fi 47 | if [ -z "$_cmd" ]; then 48 | _error "A command is mandatory" 49 | set-cmd-help 50 | return 1 51 | fi 52 | if ! _is_pot "$_pname" ; then 53 | _error "pot $_pname is not valid" 54 | set-cmd-help 55 | return 1 56 | fi 57 | if ! _is_uid0 ; then 58 | return 1 59 | fi 60 | _set_command "$_pname" "$_cmd" 61 | } 62 | -------------------------------------------------------------------------------- /share/pot/set-env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | set-env-help() { 6 | cat <<-"EOH" 7 | pot set-env [-hv] -p pot -E env 8 | -h print this help 9 | -v verbose 10 | -p pot : the working pot 11 | -E var=value : the variable and the value to be added 12 | this option can be repeated more than once 13 | EOH 14 | } 15 | 16 | # $1 pot 17 | # $2 env 18 | _set_environment() 19 | { 20 | local _pname _tmpfile _cfile 21 | _pname="$1" 22 | _tmpfile="$2" 23 | _cfile=$POT_FS_ROOT/jails/$_pname/conf/pot.conf 24 | ${SED} -i '' -e "/^pot.env=.*/d" "$_cfile" 25 | sed 's/.*/pot.env=&/g' "$_tmpfile" >> "$_cfile" 26 | } 27 | 28 | pot-set-env() 29 | { 30 | local _pname _env _tmpfile 31 | _env= 32 | _pname= 33 | if ! _is_pot_tmp_dir ; then 34 | _error "Failed to create the POT_TMP directory" 35 | return 1 36 | fi 37 | _tmpfile="$(mktemp "${POT_TMP:-/tmp}/pot-set-env${POT_MKTEMP_SUFFIX}")" || exit 1 38 | OPTIND=1 39 | while getopts "hvp:E:" _o ; do 40 | case "$_o" in 41 | h) 42 | set-env-help 43 | rm -f "$_tmpfile" 44 | return 0 45 | ;; 46 | v) 47 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 48 | ;; 49 | E) 50 | if [ "$OPTARG" = "${OPTARG#*=}" ]; then 51 | # the argument doesn't have an equal sign 52 | _error "$OPTARG not in a valid form" 53 | _error "VARIABLE=value is accetped" 54 | set-env-help 55 | rm -f "$_tmpfile" 56 | return 1 57 | fi 58 | _tmp="$( echo "$OPTARG" | sed 's%"%\\"%g' )" 59 | echo "\"$_tmp\"" >> "$_tmpfile" 60 | _env=1 61 | ;; 62 | p) 63 | _pname="$OPTARG" 64 | ;; 65 | ?) 66 | set-env-help 67 | rm -f "$_tmpfile" 68 | return 1 69 | esac 70 | done 71 | 72 | if [ -z "$_pname" ]; then 73 | _error "A pot name is mandatory" 74 | set-env-help 75 | rm -f "$_tmpfile" 76 | return 1 77 | fi 78 | if [ -z "$_env" ]; then 79 | _error "A command is mandatory" 80 | set-env-help 81 | rm -f "$_tmpfile" 82 | return 1 83 | fi 84 | if ! _is_pot "$_pname" ; then 85 | _error "pot $_pname is not valid" 86 | set-env-help 87 | rm -f "$_tmpfile" 88 | return 1 89 | fi 90 | if ! _is_uid0 ; then 91 | rm -f "$_tmpfile" 92 | return 1 93 | fi 94 | _set_environment "$_pname" "$_tmpfile" 95 | rm -f "$_tmpfile" 96 | } 97 | -------------------------------------------------------------------------------- /share/pot/set-hook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | set-hook-help() { 6 | cat <<-"EOH" 7 | pot set-hook [-hv] -p pot [-s hook] 8 | -h print this help 9 | -v verbose 10 | -p pot : the working pot 11 | -s hook : the pre-start hook 12 | -S hook : the post-start hook 13 | -t hook : the pre-stop hook 14 | -T hook : the post-stop hook 15 | EOH 16 | } 17 | 18 | # $1 pot 19 | # $2 script name 20 | # $3 hook type 21 | _set_hook() 22 | { 23 | local _pname _script 24 | _pname="$1" 25 | _script="$2" 26 | _hooktype="$3" 27 | cp "$_script" "$POT_FS_ROOT/jails/$_pname/conf/${_hooktype}.sh" 28 | } 29 | 30 | # $1 hook script 31 | _is_valid_hook() 32 | { 33 | if [ -x "$1" ]; then 34 | return 0 # true 35 | fi 36 | _error "$1 not a valid hook" 37 | return 1 # false 38 | } 39 | 40 | pot-set-hook() 41 | { 42 | local _pname _prestart _poststart _prestop _poststop 43 | _pname= 44 | _prestart= 45 | _poststart= 46 | _prestop= 47 | _poststop= 48 | OPTIND=1 49 | while getopts "hvp:s:S:t:T:" _o ; do 50 | case "$_o" in 51 | h) 52 | set-hook-help 53 | return 0 54 | ;; 55 | v) 56 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 57 | ;; 58 | s) 59 | if _is_valid_hook "${OPTARG}" ; then 60 | _prestart="${OPTARG}" 61 | fi 62 | ;; 63 | S) 64 | if _is_valid_hook "${OPTARG}" ; then 65 | _poststart="${OPTARG}" 66 | fi 67 | ;; 68 | t) 69 | if _is_valid_hook "${OPTARG}" ; then 70 | _prestop="${OPTARG}" 71 | fi 72 | ;; 73 | T) 74 | if _is_valid_hook "${OPTARG}" ; then 75 | _poststop="${OPTARG}" 76 | fi 77 | ;; 78 | p) 79 | _pname="$OPTARG" 80 | ;; 81 | ?) 82 | set-hook-help 83 | return 1 84 | esac 85 | done 86 | 87 | if [ -z "$_pname" ]; then 88 | _error "A pot name is mandatory" 89 | set-hook-help 90 | return 1 91 | fi 92 | if ! _is_pot "$_pname" ; then 93 | _error "pot $_pname is not valid" 94 | set-hook-help 95 | return 1 96 | fi 97 | if [ -z "$_prestart" ] && [ -z "$_poststart" ] && 98 | [ -z "$_prestop" ] && [ -z "$_poststop" ]; then 99 | _error "No hooks provided - at least one hook as to be set" 100 | set-hook-help 101 | return 1 102 | fi 103 | if ! _is_uid0 ; then 104 | return 1 105 | fi 106 | if [ -n "$_prestart" ]; then 107 | _set_hook "$_pname" "$_prestart" "prestart" 108 | fi 109 | if [ -n "$_poststart" ]; then 110 | _set_hook "$_pname" "$_poststart" "poststart" 111 | fi 112 | if [ -n "$_prestop" ]; then 113 | _set_hook "$_pname" "$_prestop" "prestop" 114 | fi 115 | if [ -n "$_poststop" ]; then 116 | _set_hook "$_pname" "$_poststop" "poststop" 117 | fi 118 | } 119 | -------------------------------------------------------------------------------- /share/pot/set-hosts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | set-hosts-help() { 6 | cat <<-"EOH" 7 | pot set-hosts [-hv] -p pot -H hostname:IP 8 | -h print this help 9 | -v verbose 10 | -p pot : the working pot 11 | -H hostname:IP : hostname-to-IP resolution to be added 12 | to /etc/hosts, can be used multiple times 13 | EOH 14 | } 15 | 16 | # $1 pot 17 | # $2 hostfile 18 | _set_hosts() 19 | { 20 | local _pname _tmpfile _cfile 21 | _pname="$1" 22 | _tmpfile="$2" 23 | _cfile=$POT_FS_ROOT/jails/$_pname/conf/pot.conf 24 | ${SED} -i '' -e "/^pot.hosts=.*/d" "$_cfile" 25 | sed 's/.*/pot.hosts=&/g' "$_tmpfile" >> "$_cfile" 26 | } 27 | 28 | pot-set-hosts() 29 | { 30 | local _pname _tmpfile _ip _hostname 31 | _pname= 32 | if ! _is_pot_tmp_dir ; then 33 | _error "Failed to create the POT_TMP directory" 34 | return 1 35 | fi 36 | _tmpfile="$(mktemp "${POT_TMP:-/tmp}/pot-set-hosts${POT_MKTMP_SUFFIX}")" || exit 1 37 | OPTIND=1 38 | while getopts "hvp:H:" _o ; do 39 | case "$_o" in 40 | h) 41 | set-hosts-help 42 | rm -f "$_tmpfile" 43 | return 0 44 | ;; 45 | v) 46 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 47 | ;; 48 | H) 49 | if [ "$OPTARG" = "${OPTARG#*:}" ]; then 50 | # the argument doesn't have an equal sign 51 | _error "$OPTARG not in a valid form" 52 | _error "hostname:IP is accepted" 53 | set-hosts-help 54 | rm -f "$_tmpfile" 55 | return 1 56 | fi 57 | # validate IP address 58 | _ip="${OPTARG#*:}" 59 | _hostname="${OPTARG%%:*}" 60 | if [ -z "$_ip" ] || [ -z "$_hostname" ]; then 61 | _error "Submitted ip or hostname are empty" 62 | set-hosts-help 63 | rm -f "$_tmpfile" 64 | return 1 65 | fi 66 | if ! potnet ipcheck -H "$_ip" ; then 67 | _error "Submitted ip $_ip is not a valid one" 68 | set-hosts-help 69 | rm -f "$_tmpfile" 70 | return 1 71 | fi 72 | echo "$_ip $_hostname" >> "$_tmpfile" 73 | ;; 74 | p) 75 | _pname="$OPTARG" 76 | ;; 77 | ?) 78 | set-hosts-help 79 | rm -f "$_tmpfile" 80 | return 1 81 | esac 82 | done 83 | 84 | if [ -z "$_pname" ]; then 85 | _error "A pot name is mandatory" 86 | set-hosts-help 87 | rm -f "$_tmpfile" 88 | return 1 89 | fi 90 | if ! _is_pot "$_pname" ; then 91 | _error "pot $_pname is not valid" 92 | set-hosts-help 93 | rm -f "$_tmpfile" 94 | return 1 95 | fi 96 | if ! _is_uid0 ; then 97 | rm -f "$_tmpfile" 98 | return 1 99 | fi 100 | _set_hosts "$_pname" "$_tmpfile" 101 | rm -f "$_tmpfile" 102 | } 103 | -------------------------------------------------------------------------------- /share/pot/set-rss.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | set-rss-help() 6 | { 7 | cat <<-"EOH" 8 | pot set-rss [-hv] -p pot [-C cpus] [-M memory] 9 | -h print this help 10 | -v verbose 11 | -p pot : the working pot 12 | -C cpus : the max amount of CPUs 13 | -M memory : max memory usable (integer values) 14 | EOH 15 | } 16 | 17 | # $1 pot 18 | # $2 rss name 19 | # $3 rss limit 20 | _set_rss() 21 | { 22 | local _rssname _rsslimit _pname _cdir 23 | _pname="$1" 24 | _rssname="$2" 25 | _rsslimit="$3" 26 | _cdir=$POT_FS_ROOT/jails/$_pname/conf 27 | ${SED} -i '' -e "/^pot.rss.$_rssname=.*/d" "$_cdir/pot.conf" 28 | echo "pot.rss.$_rssname=$_rsslimit" >> "$_cdir/pot.conf" 29 | } 30 | 31 | # $1 the amount of memory 32 | _memory_validation() 33 | { 34 | : # Implement 35 | local _number 36 | if ! echo "$1" | grep -q -E '^[0-9]+[bBkKmMgG]?$' ; then 37 | _error "$1 is not a valid memory constraint" 38 | return 1 39 | fi 40 | _number="$( echo "$1" | sed 's/[bBkKmMgG]$//')" 41 | if ! echo "$_number" | grep -q -E '^[0-9]+' ; then 42 | _error "$1 has wrong suffix or format" 43 | return 1 44 | fi 45 | if echo "$_number" | grep -q '^00*$' ; then 46 | _error "Memory constraint has to be greater than zero" 47 | return 1 48 | fi 49 | return 0 50 | } 51 | # $1 pot 52 | # $2 cpus amount 53 | _set_cpu() 54 | { 55 | local _pname _cpus 56 | _pname=$1 57 | _cpus=$2 58 | if _is_natural_number "$_cpus" ; then 59 | if [ "$_cpus" -gt 0 ]; then 60 | _set_rss "$_pname" cpus "$_cpus" 61 | return 0 # true 62 | fi 63 | fi 64 | return 1 # false 65 | } 66 | 67 | _set_memory() 68 | { 69 | local _pname _memory 70 | _pname=$1 71 | _memory=$2 72 | _set_rss "$_pname" memory "$_memory" 73 | } 74 | 75 | pot-set-rss() 76 | { 77 | local _pname _cpus _memory 78 | _pname= 79 | _cpus= 80 | _memory= 81 | OPTIND=1 82 | while getopts "hvp:C:M:" _o ; do 83 | case "$_o" in 84 | h) 85 | set-rss-help 86 | return 0 87 | ;; 88 | v) 89 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 90 | ;; 91 | p) 92 | _pname="$OPTARG" 93 | ;; 94 | C) 95 | _cpus="$OPTARG" 96 | ;; 97 | M) 98 | if _memory_validation "$OPTARG" ; then 99 | _memory="$OPTARG" 100 | else 101 | set-rss-help 102 | return 1 103 | fi 104 | ;; 105 | *) 106 | set-rss-help 107 | return 1 108 | ;; 109 | esac 110 | done 111 | if [ -z "$_pname" ]; then 112 | _error "A pot name is mandatory" 113 | set-rss-help 114 | return 1 115 | fi 116 | if ! _is_pot "$_pname" ; then 117 | _error "$_pname is not a valid pot name" 118 | set-rss-help 119 | return 1 120 | fi 121 | if [ -z "${_cpus}${_memory}" ]; then 122 | _error "One resource has to be specified (-C or -M)" 123 | set-rss-help 124 | return 1 125 | fi 126 | if ! _is_uid0 ; then 127 | return 1 128 | fi 129 | if [ -n "$_cpus" ]; then 130 | if ! _set_cpu "$_pname" "$_cpus" ; then 131 | _error "$_cpus is a not valid amount of CPUs!" 132 | return 1 133 | fi 134 | fi 135 | if [ -n "$_memory" ]; then 136 | _set_memory "$_pname" "$_memory" 137 | fi 138 | } 139 | -------------------------------------------------------------------------------- /share/pot/set-status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | : "${_POT_INTERNAL_STATUS:="starting doa started stopping stopped"}" 6 | 7 | set-status-help() 8 | { 9 | cat <<-EOH 10 | Internal command, DO NOT USE IF YOU DON'T KNOW WHAT YOU ARE DOING! 11 | This command is meant to be invoked using lockf 12 | pot set-status [-hv] [-p pname] [-s status] 13 | -h print this help 14 | -v verbose 15 | -i interface(s) : network interface (epaira) 16 | -p pname : pot name 17 | -s status : the status [$_POT_INTERNAL_STATUS] 18 | EOH 19 | } 20 | 21 | # $1 pot name 22 | _get_status() 23 | { 24 | local _pname _status_file _uptime _mod_time 25 | _pname="$1" 26 | _status_file="${POT_TMP:-/tmp}/pot_status_${_pname}" 27 | 28 | if [ ! -e "$_status_file" ]; then 29 | return 30 | fi 31 | 32 | _mod_time=$(stat -f "%m" "$_status_file") 33 | _uptime=$(_get_system_uptime) 34 | 35 | if [ "$_uptime" -gt "$_mod_time" ]; then 36 | >&2 _debug "Ignoring outdated status file $_status_file of pot $_pname" 37 | return 38 | fi 39 | 40 | _value="$(grep "^pot.status=" "$_status_file" | tail -n 1 \ 41 | |tr -d ' \t"' | cut -f2 -d'=' )" 42 | echo "$_value" 43 | } 44 | 45 | # $1 pot name 46 | # $2 new status 47 | _set_status() 48 | { 49 | local _pname _status_file _new_status 50 | _pname="$1" 51 | _new_status="$2" 52 | _status_file="${POT_TMP:-/tmp}/pot_status_${_pname}" 53 | 54 | echo "pot.status=$_new_status" >> "$_status_file" 55 | # remove first (and outdated) occurrence of pot.status 56 | if [ "$(grep -c "^pot\.status=" "$_status_file")" -gt 1 ]; then 57 | ${SED} -i '' -n -e ":a" \ 58 | -e '/^pot\.status=/{n;bc' -e ':c' -e 'p;n;bc' -e '}' \ 59 | -e "p;n;ba" "$_status_file" 60 | fi 61 | } 62 | 63 | pot-set-status() 64 | { 65 | local _pname _new_status _tmp _current_status _current_ifnames _conf 66 | local _ifnames 67 | _ifnames="" 68 | _pname="" 69 | _new_status="" 70 | OPTIND=1 71 | while getopts "hvp:i:s:" _o ; do 72 | case "$_o" in 73 | h) 74 | set-status-help 75 | return 0 76 | ;; 77 | v) 78 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 79 | ;; 80 | p) 81 | _pname="$OPTARG" 82 | ;; 83 | i) 84 | _ifnames="$OPTARG" 85 | ;; 86 | s) 87 | # shellcheck disable=SC2086 88 | if _is_in_list "$OPTARG" $_POT_INTERNAL_STATUS ; then 89 | _new_status="$OPTARG" 90 | else 91 | _error "$OPTARG is not a valid status" 92 | fi 93 | ;; 94 | *) 95 | set-status-help 96 | return 1 97 | ;; 98 | esac 99 | done 100 | if [ -z "$_pname" ]; then 101 | _error "A pot name is mandatory" 102 | set-status-help 103 | return 1 104 | fi 105 | if ! _is_pot "$_pname"; then 106 | _error "$_pname is not a pot" 107 | return 1 108 | fi 109 | 110 | _tmp=$(_get_status "$_pname") 111 | _current_status=$(echo "$_tmp" | cut -d, -f1) 112 | _current_ifnames=$(echo "$_tmp" | cut -d, -f2) 113 | # if current status is equal to new status, it means that some other pot command is 114 | # taking care of the execution of the transition and an exit code 2 is returned 115 | if [ "$_current_status" = "$_new_status" ]; then 116 | return 2 117 | fi 118 | # new status can only be accepted from a specific current status 119 | # any other case, the command return an exit code 1 120 | case "$_new_status" in 121 | "starting") 122 | if [ -n "$_current_status" ] && [ "$_current_status" != "stopped" ]; then 123 | return 1 124 | fi 125 | _ifnames="" 126 | ;; 127 | "started" | "doa") 128 | if [ "$_current_status" != "starting" ]; then 129 | return 1 130 | fi 131 | ;; 132 | "stopping") 133 | # you can always stop a stopped pot (for cleanup reasons) 134 | if [ "$_current_status" != "started" ] && \ 135 | [ "$_current_status" != "doa" ] && 136 | [ "$_current_status" != "stopped" ]; then 137 | return 1 138 | fi 139 | _ifnames="$_current_ifnames" 140 | echo "$_ifnames" 141 | ;; 142 | "stopped") 143 | if [ "$_current_status" != "stopping" ]; then 144 | return 1 145 | fi 146 | _ifnames="" 147 | ;; 148 | esac 149 | _set_status "$_pname" "$_new_status,$_ifnames" 150 | } 151 | -------------------------------------------------------------------------------- /share/pot/snapshot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | snapshot-help() 6 | { 7 | cat <<-"EOH" 8 | pot snapshot [-hv] -p potname|-f fscomp 9 | -h print this help 10 | -v verbose 11 | -r replace the oldest available snapshot with the new one 12 | -p potname : the pot target of the snapshot 13 | -f fscomp : the fs component target of the snapshot 14 | EOH 15 | } 16 | 17 | pot-snapshot() 18 | { 19 | local _full_pot _obj _objname 20 | _full_pot="NO" 21 | _obj="" 22 | _objname= 23 | _replace= 24 | OPTIND=1 25 | while getopts "hvp:f:r" _o ; do 26 | case "$_o" in 27 | h) 28 | snapshot-help 29 | return 0 30 | ;; 31 | v) 32 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 33 | ;; 34 | r) 35 | _replace="YES" 36 | ;; 37 | p) 38 | if [ -z "$_obj" ]; then 39 | _obj="pot" 40 | _objname="$OPTARG" 41 | else 42 | _error "-p|-f are exclusive" 43 | snapshot-help 44 | return 1 45 | fi 46 | ;; 47 | f) 48 | if [ -z "$_obj" ]; then 49 | _obj="fscomp" 50 | _objname="$OPTARG" 51 | else 52 | _error "-p|-f are exclusive" 53 | snapshot-help 54 | return 1 55 | fi 56 | ;; 57 | *) 58 | snapshot-help 59 | return 1 60 | ;; 61 | esac 62 | done 63 | if [ -z "$_obj" ]; then 64 | _error "one of -p|-f has to be used" 65 | snapshot-help 66 | return 1 67 | fi 68 | if [ -z "$_objname" ]; then 69 | _error "-p|-f options need an argument" 70 | snapshot-help 71 | return 1 72 | fi 73 | case $_obj in 74 | "pot") 75 | if ! _is_pot "$_objname" ; then 76 | _error "$_objname is not a pot!" 77 | snapshot-help 78 | return 1 79 | fi 80 | if _is_pot_running "$_objname" ; then 81 | _error "The pot $_objname is still running. Snapshot is possible only for stopped pots" 82 | return 1 83 | fi 84 | if ! _is_uid0 ; then 85 | return 1 86 | fi 87 | 88 | if [ "$_full_pot" = "YES" ]; then 89 | _pot_zfs_snap_full "$_objname" 90 | else 91 | if [ "$_replace" = "YES" ]; then 92 | _remove_oldest_pot_snap "$_objname" 93 | fi 94 | _pot_zfs_snap "$_objname" 95 | fi 96 | ;; 97 | "fscomp") 98 | if ! _zfs_exist "${POT_ZFS_ROOT}/fscomp/$_objname" "${POT_FS_ROOT}/fscomp/$_objname" ; then 99 | _error "$_objname is not a valid fscomp" 100 | snapshot-help 101 | return 1 102 | fi 103 | if ! _is_uid0 ; then 104 | return 1 105 | fi 106 | if [ "$_replace" = "YES" ]; then 107 | _remove_oldest_fscomp_snap "$_objname" 108 | fi 109 | _fscomp_zfs_snap "$_objname" 110 | ;; 111 | esac 112 | return 0 113 | } 114 | -------------------------------------------------------------------------------- /share/pot/term.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | term-help() 6 | { 7 | cat <<-"EOH" 8 | pot term [-hvf] -p potname [pname] 9 | pot run [-hv] -p potname [pname] 10 | -h print this help 11 | -v verbose 12 | -f : start the pot if it is not running 13 | -p potname : the pot to open terminal in 14 | 15 | pname : pot to open terminal in if "-p potname" not given 16 | EOH 17 | } 18 | 19 | # TODO a configurable shell or a login shell 20 | # $1 pot name 21 | _term() 22 | { 23 | local _pname 24 | _pname="$1" 25 | jexec -l -U root "$_pname" 26 | # This would perform a login (poudriere approach) 27 | # jexec "$_pname" env -i TERM="$TERM" /usr/bin/login -fp root 28 | } 29 | 30 | pot-term() 31 | { 32 | local _pname _force 33 | _pname= 34 | _force= 35 | 36 | OPTIND=1 37 | while getopts "hvfp:" _o; do 38 | case "$_o" in 39 | h) 40 | term-help 41 | ${EXIT} 0 42 | ;; 43 | v) 44 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 45 | ;; 46 | f) 47 | _force="YES" 48 | ;; 49 | p) 50 | _pname="$OPTARG" 51 | ;; 52 | ?) 53 | break 54 | ;; 55 | esac 56 | done 57 | if [ -z "$_pname" ]; then 58 | _pname="$(eval echo \$$OPTIND)" 59 | fi 60 | if [ -z "$_pname" ]; then 61 | _error "A pot name is mandatory" 62 | term-help 63 | ${EXIT} 1 64 | fi 65 | # shellcheck disable=2086 66 | if ! _is_pot_running $_pname ; then 67 | if [ "$_force" = "YES" ]; then 68 | if ! _is_uid0 ; then 69 | ${EXIT} 1 70 | fi 71 | 72 | pot-cmd start "$_pname" 73 | if ! _is_pot_running "$_pname" ; then 74 | _error "The pot $_pname doesn't start" 75 | ${EXIT} 1 76 | fi 77 | else 78 | _error "The pot $_pname is not running" 79 | ${EXIT} 1 80 | fi 81 | fi 82 | if ! _is_uid0 ; then 83 | ${EXIT} 1 84 | fi 85 | 86 | _term "$_pname" 87 | } 88 | -------------------------------------------------------------------------------- /share/pot/top.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | top-help() 6 | { 7 | cat <<-"EOH" 8 | pot top [-h] -p pot 9 | -h print this help 10 | -p pot : the working pot 11 | EOH 12 | } 13 | 14 | pot-top() 15 | { 16 | local _pname _o 17 | _pname= 18 | OPTIND=1 19 | while getopts "hp:" _o ; do 20 | case "$_o" in 21 | h) 22 | top-help 23 | ${EXIT} 0 24 | ;; 25 | p) 26 | _pname="$OPTARG" 27 | ;; 28 | *) 29 | top-help 30 | ${EXIT} 1 31 | esac 32 | done 33 | 34 | if [ -z "$_pname" ]; then 35 | _error "A pot name is mandatory" 36 | top-help 37 | ${EXIT} 1 38 | fi 39 | if ! _is_pot "$_pname" ; then 40 | _error "pot $_pname is not valid" 41 | top-help 42 | ${EXIT} 1 43 | fi 44 | if ! _is_pot_running "$_pname" ; then 45 | _error "pot $_pname is not in execution" 46 | top-help 47 | ${EXIT} 1 48 | fi 49 | top -J "$_pname" 50 | } 51 | -------------------------------------------------------------------------------- /share/pot/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3033,SC3040,SC3043 3 | : 4 | 5 | version-help() 6 | { 7 | cat <<-"EOH" 8 | pot version [-hvq] 9 | -h print this help 10 | -v verbose 11 | -q quiet 12 | EOH 13 | } 14 | 15 | 16 | pot-version() 17 | { 18 | local _quiet 19 | _quiet="NO" 20 | OPTIND=1 21 | while getopts "hvq" _o ; do 22 | case "$_o" in 23 | h) 24 | version-help 25 | ${EXIT} 0 26 | ;; 27 | v) 28 | _POT_VERBOSITY=$(( _POT_VERBOSITY + 1)) 29 | ;; 30 | q) 31 | _quiet="YES" 32 | ;; 33 | ?) 34 | version-help 35 | ${EXIT} 1 36 | ;; 37 | *) 38 | ;; 39 | esac 40 | done 41 | 42 | if [ "$_quiet" = "YES" ]; then 43 | ${ECHO} "${_POT_VERSION}" 44 | ${EXIT} 0 45 | fi 46 | echo "pot version: $_POT_VERSION" 47 | } 48 | -------------------------------------------------------------------------------- /tests/CI/resolv.conf-dual: -------------------------------------------------------------------------------- 1 | nameserver 1.1.1.1 2 | nameserver 1.0.0.1 3 | nameserver 2606:4700:4700::1111 4 | nameserver 2606:4700:4700::1001 5 | 6 | -------------------------------------------------------------------------------- /tests/CI/resolv.conf-ipv4: -------------------------------------------------------------------------------- 1 | nameserver 1.1.1.1 2 | nameserver 1.0.0.1 3 | 4 | -------------------------------------------------------------------------------- /tests/CI/resolv.conf-ipv6: -------------------------------------------------------------------------------- 1 | nameserver 2606:4700:4700::1111 2 | nameserver 2606:4700:4700::1001 3 | 4 | -------------------------------------------------------------------------------- /tests/add-dep1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/add-dep.sh 7 | 8 | # common stubs 9 | . common-stub.sh 10 | 11 | # app specific stubs 12 | add-dep-help() 13 | { 14 | __monitor HELP "$@" 15 | } 16 | 17 | _add_dependency() 18 | { 19 | __monitor ADDDEP "$@" 20 | } 21 | 22 | test_pot_add_dep_001() 23 | { 24 | pot-add-dep 25 | assertEquals "Exit rc" "1" "$?" 26 | assertEqualsMon "Help calls" "1" HELP_CALLS 27 | assertEqualsMon "Error calls" "1" ERROR_CALLS 28 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 29 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 30 | 31 | setUp 32 | pot-add-dep -vb 33 | assertEquals "Exit rc" "1" "$?" 34 | assertEqualsMon "Help calls" "1" HELP_CALLS 35 | assertEqualsMon "Error calls" "0" ERROR_CALLS 36 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 37 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 38 | 39 | setUp 40 | pot-add-dep -b bb 41 | assertEquals "Exit rc" "1" "$?" 42 | assertEqualsMon "Help calls" "1" HELP_CALLS 43 | assertEqualsMon "Error calls" "0" ERROR_CALLS 44 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 45 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 46 | 47 | setUp 48 | pot-add-dep -h 49 | assertEquals "Exit rc" "0" "$?" 50 | assertEqualsMon "Help calls" "1" HELP_CALLS 51 | assertEqualsMon "Error calls" "0" ERROR_CALLS 52 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 53 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 54 | } 55 | 56 | test_pot_add_dep_002() 57 | { 58 | pot-add-dep -p test-pot 59 | assertEquals "Exit rc" "1" "$?" 60 | assertEqualsMon "Help calls" "1" HELP_CALLS 61 | assertEqualsMon "Error calls" "1" ERROR_CALLS 62 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 63 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 64 | 65 | setUp 66 | pot-add-dep -P test-pot 67 | assertEquals "Exit rc" "1" "$?" 68 | assertEqualsMon "Help calls" "1" HELP_CALLS 69 | assertEqualsMon "Error calls" "1" ERROR_CALLS 70 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 71 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 72 | 73 | setUp 74 | pot-add-dep -P test-pot -p test-no-pot 75 | assertEquals "Exit rc" "1" "$?" 76 | assertEqualsMon "Help calls" "1" HELP_CALLS 77 | assertEqualsMon "Error calls" "1" ERROR_CALLS 78 | assertEqualsMon "_is_pot calls" "1" ISPOT_CALLS 79 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 80 | 81 | setUp 82 | pot-add-dep -p test-pot -P test-no-pot 83 | assertEquals "Exit rc" "1" "$?" 84 | assertEqualsMon "Help calls" "1" HELP_CALLS 85 | assertEqualsMon "Error calls" "1" ERROR_CALLS 86 | assertEqualsMon "_is_pot calls" "2" ISPOT_CALLS 87 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 88 | 89 | setUp 90 | pot-add-dep -P test-pot -p test-pot 91 | assertEquals "Exit rc" "1" "$?" 92 | assertEqualsMon "Help calls" "1" HELP_CALLS 93 | assertEqualsMon "Error calls" "1" ERROR_CALLS 94 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 95 | assertEqualsMon "_add_dependency calls" "0" ADDDEP_CALLS 96 | } 97 | 98 | test_pot_add_dep_020() 99 | { 100 | pot-add-dep -P test-pot -p test-pot-2 101 | assertEquals "Exit rc" "0" "$?" 102 | assertEqualsMon "Help calls" "0" HELP_CALLS 103 | assertEqualsMon "Error calls" "0" ERROR_CALLS 104 | assertEqualsMon "_is_pot calls" "2" ISPOT_CALLS 105 | assertEqualsMon "_add_dependency calls" "1" ADDDEP_CALLS 106 | assertEqualsMon "pot name " "test-pot-2" ADDDEP_CALL1_ARG1 107 | assertEqualsMon "run time dependency" "test-pot" ADDDEP_CALL1_ARG2 108 | } 109 | 110 | setUp() 111 | { 112 | common_setUp 113 | } 114 | 115 | . shunit/shunit2 116 | -------------------------------------------------------------------------------- /tests/clone-fscomp1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/clone-fscomp.sh 7 | 8 | # common stubs 9 | . common-stub.sh 10 | 11 | _zfs_dataset_valid() 12 | { 13 | __monitor ZDSET "$@" 14 | if [ "$1" = "/fscomp/test-fscomp" ]; then 15 | return 0 # true 16 | fi 17 | if [ "$1" = "/fscomp/test-fscomp2" ]; then 18 | return 0 # true 19 | fi 20 | return 1 # false 21 | } 22 | 23 | # app specific stubs 24 | clone-fscomp-help() 25 | { 26 | __monitor HELP "$@" 27 | } 28 | 29 | _cf_zfs() 30 | { 31 | __monitor CFZFS "$@" 32 | return 0 # true 33 | } 34 | 35 | test_pot_add_fscomp_001() 36 | { 37 | pot-clone-fscomp 38 | assertEquals "Exit rc" "1" "$?" 39 | assertEqualsMon "Help calls" "1" HELP_CALLS 40 | assertEqualsMon "Error calls" "1" ERROR_CALLS 41 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 42 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 43 | 44 | setUp 45 | pot-clone-fscomp -vb 46 | assertEquals "Exit rc" "1" "$?" 47 | assertEqualsMon "Help calls" "1" HELP_CALLS 48 | assertEqualsMon "Error calls" "0" ERROR_CALLS 49 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 50 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 51 | 52 | setUp 53 | pot-clone-fscomp -b bb 54 | assertEquals "Exit rc" "1" "$?" 55 | assertEqualsMon "Help calls" "1" HELP_CALLS 56 | assertEqualsMon "Error calls" "0" ERROR_CALLS 57 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 58 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 59 | 60 | setUp 61 | pot-clone-fscomp -h 62 | assertEquals "Exit rc" "0" "$?" 63 | assertEqualsMon "Help calls" "1" HELP_CALLS 64 | assertEqualsMon "Error calls" "0" ERROR_CALLS 65 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 66 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 67 | } 68 | 69 | test_pot_add_fscomp_002() 70 | { 71 | pot-clone-fscomp -f new-fscomp 72 | assertEquals "Exit rc" "1" "$?" 73 | assertEqualsMon "Help calls" "1" HELP_CALLS 74 | assertEqualsMon "Error calls" "1" ERROR_CALLS 75 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 76 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 77 | assertEqualsMon "_cf_zfs calls" "0" CFZFS_CALLS 78 | 79 | setUp 80 | pot-clone-fscomp -F test-fscomp 81 | assertEquals "Exit rc" "1" "$?" 82 | assertEqualsMon "Help calls" "1" HELP_CALLS 83 | assertEqualsMon "Error calls" "1" ERROR_CALLS 84 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 85 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 86 | assertEqualsMon "_cf_zfs calls" "0" CFZFS_CALLS 87 | } 88 | 89 | test_pot_add_fscomp_003() 90 | { 91 | pot-clone-fscomp -f new-fscomp -F test-no-fscomp 92 | assertEquals "Exit rc" "1" "$?" 93 | assertEqualsMon "Help calls" "0" HELP_CALLS 94 | assertEqualsMon "Error calls" "1" ERROR_CALLS 95 | assertEqualsMon "_zfs_dataset_valid calls" "2" ZDSET_CALLS 96 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 97 | assertEqualsMon "_cf_zfs calls" "0" CFZFS_CALLS 98 | 99 | setUp 100 | pot-clone-fscomp -f test-fscomp2 -F test-fscomp 101 | assertEquals "Exit rc" "1" "$?" 102 | assertEqualsMon "Help calls" "0" HELP_CALLS 103 | assertEqualsMon "Error calls" "1" ERROR_CALLS 104 | assertEqualsMon "_zfs_dataset_valid calls" "1" ZDSET_CALLS 105 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 106 | assertEqualsMon "_cf_zfs calls" "0" CFZFS_CALLS 107 | } 108 | 109 | test_pot_add_fscomp_020() 110 | { 111 | pot-clone-fscomp -f new-fscomp -F test-fscomp 112 | assertEquals "Exit rc" "0" "$?" 113 | assertEqualsMon "Help calls" "0" HELP_CALLS 114 | assertEqualsMon "Error calls" "0" ERROR_CALLS 115 | assertEqualsMon "_zfs_dataset_valid calls" "2" ZDSET_CALLS 116 | assertEqualsMon "_is_uid0 calls" "1" ISUID0_CALLS 117 | assertEqualsMon "_cf_zfs calls" "1" CFZFS_CALLS 118 | assertEqualsMon "_cf_zfs arg1" "new-fscomp" CFZFS_CALL1_ARG1 119 | assertEqualsMon "_cf_zfs arg2" "test-fscomp" CFZFS_CALL1_ARG2 120 | } 121 | 122 | setUp() 123 | { 124 | common_setUp 125 | } 126 | 127 | . shunit/shunit2 128 | -------------------------------------------------------------------------------- /tests/common-flv1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | . monitor.sh 5 | 6 | # UUT 7 | . ../share/pot/common-flv.sh 8 | 9 | # app specific stubs 10 | 11 | _get_flavour_cmd_file() 12 | { 13 | case "$1" in 14 | test) 15 | echo test ;; 16 | testnoscript) 17 | echo testnoscript ;; 18 | *) 19 | ;; 20 | esac 21 | } 22 | 23 | _get_flavour_script() 24 | { 25 | case "$1" in 26 | test) 27 | echo test.sh ;; 28 | testnocmd) 29 | echo testnocmd.sh ;; 30 | *) 31 | ;; 32 | esac 33 | } 34 | 35 | test_is_cmd_flavorable_01() 36 | { 37 | _is_cmd_flavorable 38 | assertNotEquals "$?" "0" 39 | 40 | _is_cmd_flavorable help 41 | assertNotEquals "$?" "0" 42 | 43 | _is_cmd_flavorable help create 44 | assertNotEquals "$?" "0" 45 | 46 | _is_cmd_flavorable create -p help 47 | assertNotEquals "$?" "0" 48 | 49 | _is_cmd_flavorable add-fscomp 50 | assertNotEquals "$?" "0" 51 | 52 | _is_cmd_flavorable add-file 53 | assertNotEquals "$?" "0" 54 | } 55 | 56 | test_is_cmd_flavorable_02() 57 | { 58 | _is_cmd_flavorable add-dep 59 | assertEquals "$?" "0" 60 | 61 | _is_cmd_flavorable add-dep -v -p me -P you 62 | assertEquals "$?" "0" 63 | 64 | _is_cmd_flavorable set-rss 65 | assertEquals "$?" "0" 66 | 67 | _is_cmd_flavorable copy-in 68 | assertEquals "$?" "0" 69 | 70 | _is_cmd_flavorable mount-in 71 | assertEquals "$?" "0" 72 | } 73 | 74 | test_is_flavour_001() 75 | { 76 | assertTrue "_is_flavour test" 77 | assertTrue "_is_flavour testnoscript" 78 | assertTrue "_is_flavour testnocmd" 79 | assertFalse "_is_flavour notest" 80 | } 81 | 82 | setUp() 83 | { 84 | __mon_init 85 | _POT_VERBOSITY=1 86 | } 87 | 88 | tearDown() 89 | { 90 | __mon_tearDown 91 | } 92 | 93 | . shunit/shunit2 94 | -------------------------------------------------------------------------------- /tests/common-zfs1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | zfs() 6 | { 7 | if [ "$2" = "zfs-dataset" ]; then 8 | return 0 # true 9 | fi 10 | if [ "$2" = "-H" ]; then 11 | if [ "$5" = "zfs-dataset" ]; then 12 | echo "/path/to/mnt" 13 | return 0 # true 14 | fi 15 | fi 16 | if [ "$2" = "-o" ]; then 17 | case "$5" in 18 | zfs-dataset) 19 | echo zfs-dataset 20 | ;; 21 | /path/to/mnt) 22 | echo zfs-dataset 23 | ;; 24 | esac 25 | fi 26 | return 1 # false 27 | } 28 | 29 | # UUT 30 | . ../share/pot/common.sh 31 | 32 | # app specific stubs 33 | 34 | test_zfs_exist_001() 35 | { 36 | _zfs_exist 37 | assertNotEquals "0" "$?" 38 | 39 | _zfs_exist zfs-nodataset 40 | assertNotEquals "0" "$?" 41 | 42 | _zfs_exist zfs-dataset 43 | assertNotEquals "0" "$?" 44 | } 45 | 46 | test_zfs_exist_002() 47 | { 48 | _zfs_exist zfs-nodataset /path/to/mnt 49 | assertNotEquals "0" "$?" 50 | 51 | _zfs_exist zfs-dataset /path/to/chaos 52 | assertNotEquals "0" "$?" 53 | 54 | _zfs_exist zfs-dataset /path/to/mnt 55 | assertEquals "0" "$?" 56 | } 57 | 58 | test_zfs_dataset_valid_001() 59 | { 60 | _zfs_dataset_valid 61 | assertNotEquals "0" "$?" 62 | 63 | _zfs_dataset_valid zfs-nodataset 64 | assertNotEquals "0" "$?" 65 | 66 | _zfs_dataset_valid /path/to/mnt 67 | assertNotEquals "0" "$?" 68 | } 69 | 70 | test_zfs_dataset_valid_002() 71 | { 72 | _zfs_dataset_valid zfs-dataset 73 | assertEquals "0" "$?" 74 | } 75 | 76 | . shunit/shunit2 77 | -------------------------------------------------------------------------------- /tests/common-zfs2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . monitor.sh 4 | # system utilities stubs 5 | 6 | zfs() 7 | { 8 | __monitor ZFS "$@" 9 | } 10 | 11 | date() 12 | { 13 | echo "123454321" 14 | } 15 | 16 | # UUT 17 | . ../share/pot/common.sh 18 | 19 | # app specific stubs 20 | 21 | test_fscomp_zfs_snap_001() 22 | { 23 | _fscomp_zfs_snap fscomp_name 24 | assertEqualsMon "zfs calls" "1" ZFS_CALLS 25 | assertEqualsMon "zfs args" "/zroot/fscomp/fscomp_name@123454321" ZFS_CALL1_ARG2 26 | } 27 | 28 | test_fscomp_zfs_snap_002() 29 | { 30 | # the argument "new_snap" is ignored 31 | _fscomp_zfs_snap fscomp_name new_snap 32 | assertEqualsMon "zfs calls" "1" ZFS_CALLS 33 | assertEqualsMon "zfs arg1" "snapshot" ZFS_CALL1_ARG1 34 | assertEqualsMon "zfs arg2" "/zroot/fscomp/fscomp_name@123454321" ZFS_CALL1_ARG2 35 | } 36 | 37 | setUp() 38 | { 39 | __mon_init 40 | POT_ZFS_ROOT=/zroot 41 | } 42 | 43 | tearDown() 44 | { 45 | __mon_tearDown 46 | } 47 | 48 | . shunit/shunit2 49 | -------------------------------------------------------------------------------- /tests/common2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | if [ "$(uname)" = "Linux" ]; then 6 | TEST=/usr/bin/[ 7 | else 8 | TEST=/bin/[ 9 | fi 10 | 11 | [() 12 | { 13 | if ${TEST} "$1" = "!" ]; then 14 | if ${TEST} "$2" = "-d" ]; then 15 | if ${TEST} "$3" = "/jails/pot-test" ]; then 16 | return 1 # false 17 | elif ${TEST} "$3" = "/jails/pot-test-single" ]; then 18 | return 1 # false 19 | elif ${TEST} "$3" = "/jails/pot-test-nodset" ]; then 20 | return 1 # false 21 | elif ${TEST} "$3" = "/jails/pot-test-noconf" ]; then 22 | return 1 # false 23 | elif ${TEST} "$3" = "/jails/pot-test/m" ]; then 24 | return 1 # false 25 | elif ${TEST} "$3" = "/jails/pot-test-single/m" ]; then 26 | return 1 # false 27 | elif ${TEST} "$3" = "/bases/base-test" ]; then 28 | return 1 # false 29 | elif ${TEST} "$3" = "/bases/base-test-nodset" ]; then 30 | return 1 # false 31 | elif ${TEST} "$3" = "/fscomp/fscomp-test" ]; then 32 | return 1 # false 33 | elif ${TEST} "$3" = "/fscomp/fscomp-test-nodset" ]; then 34 | return 1 # false 35 | else 36 | return 0 # true 37 | fi 38 | fi 39 | if ${TEST} "$2" = "-r" ]; then 40 | if ${TEST} "$3" = "/jails/pot-test/conf/pot.conf" ]; then 41 | return 1 # false 42 | elif ${TEST} "$3" = "/jails/pot-test/conf/fscomp.conf" ]; then 43 | return 1 # false 44 | elif ${TEST} "$3" = "/jails/pot-test-single/conf/pot.conf" ]; then 45 | return 1 # false 46 | elif ${TEST} "$3" = "/jails/pot-test-single/conf/fscomp.conf" ]; then 47 | return 0 # true 48 | else 49 | return 0 50 | fi 51 | fi 52 | fi 53 | ${TEST} "$@" 54 | return $? 55 | } 56 | 57 | 58 | # UUT 59 | . ../share/pot/common.sh 60 | 61 | # app specific stubs 62 | POT_FS_ROOT= 63 | POT_ZFS_ROOT= 64 | 65 | _error() 66 | { 67 | : 68 | } 69 | 70 | _zfs_dataset_valid() 71 | { 72 | if ${TEST} "$1" = "/jails/pot-test" ]; then 73 | return 0 # true 74 | elif ${TEST} "$1" = "/jails/pot-test-single" ]; then 75 | return 0 # true 76 | elif ${TEST} "$1" = "/jails/pot-test-noconf" ]; then 77 | return 0 # true 78 | fi 79 | if ${TEST} "$1" = "/bases/base-test" ]; then 80 | return 0 81 | fi 82 | if ${TEST} "$1" = "/fscomp/fscomp-test" ]; then 83 | return 0 84 | fi 85 | return 1 # false 86 | } 87 | 88 | _get_pot_type() 89 | { 90 | if ${TEST} "$1" = "pot-test" ]; then 91 | echo "multi" 92 | fi 93 | if ${TEST} "$1" = "pot-test-single" ]; then 94 | echo "single" 95 | fi 96 | } 97 | 98 | test_is_pot() 99 | { 100 | _is_pot 101 | assertEquals "1" "$?" 102 | 103 | _is_pot nopot 104 | assertEquals "1" "$?" 105 | 106 | _is_pot pot-test-nodset 107 | assertEquals "2" "$?" 108 | 109 | _is_pot pot-test-noconf 110 | assertEquals "3" "$?" 111 | 112 | _is_pot pot-test 113 | assertEquals "0" "$?" 114 | 115 | _is_pot pot-test-single 116 | assertEquals "0" "$?" 117 | } 118 | 119 | test_is_base() 120 | { 121 | _is_base 122 | assertEquals "1" "$?" 123 | 124 | _is_base nobase 125 | assertEquals "1" "$?" 126 | 127 | _is_base base-test-nodset 128 | assertEquals "2" "$?" 129 | 130 | _is_base base-test 131 | assertEquals "0" "$?" 132 | } 133 | 134 | test_is_fscomp() 135 | { 136 | _is_fscomp 137 | assertEquals "1" "$?" 138 | 139 | _is_fscomp nofscomp 140 | assertEquals "1" "$?" 141 | 142 | _is_fscomp fscomp-test-nodset 143 | assertEquals "2" "$?" 144 | 145 | _is_fscomp fscomp-test 146 | assertEquals "0" "$?" 147 | } 148 | 149 | . shunit/shunit2 150 | -------------------------------------------------------------------------------- /tests/common4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/common.sh 7 | 8 | # common stubs 9 | . ./monitor.sh 10 | 11 | _qerror() 12 | { 13 | __monitor QERR $* 14 | } 15 | 16 | _zfs_exist() 17 | { 18 | if [ "$1" = "zpot" ] && [ "$2" = "/opt" ]; then 19 | return 0 # true 20 | fi 21 | return 1 22 | } 23 | 24 | _zfs_dataset_valid() 25 | { 26 | return 0 27 | } 28 | 29 | # app specific stubs 30 | 31 | test_is_init_001() 32 | { 33 | POT_ZFS_ROOT= 34 | _is_init quiet 35 | assertEquals "1" "$?" 36 | } 37 | 38 | test_is_init_002() 39 | { 40 | POT_FS_ROOT= 41 | _is_init quiet 42 | assertEquals "1" "$?" 43 | } 44 | 45 | test_is_init_003() 46 | { 47 | POT_FS_ROOT=/usr/local/pot 48 | _is_init quiet 49 | assertEquals "1" "$?" 50 | } 51 | 52 | test_is_init_004() 53 | { 54 | POT_ZFS_ROOT=zroot 55 | _is_init quiet 56 | assertEquals "1" "$?" 57 | } 58 | 59 | test_is_init_020() 60 | { 61 | _is_init quiet 62 | assertEquals "0" "$?" 63 | } 64 | 65 | setUp() 66 | { 67 | __mon_init 68 | POT_ZFS_ROOT=zpot 69 | POT_FS_ROOT=/opt 70 | POT_GROUP="$(id -ng)" 71 | } 72 | 73 | tearDown() 74 | { 75 | __mon_tearDown 76 | } 77 | 78 | . shunit/shunit2 79 | -------------------------------------------------------------------------------- /tests/common6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/common.sh 7 | 8 | # common stubs 9 | . conf-stub.sh 10 | 11 | test_get_conf_vnet_001() 12 | { 13 | rc=$(_get_conf_var test-pot-vnet-ip4 vnet ) 14 | assertEquals "vnet value" "true" "$rc" 15 | } 16 | 17 | test_is_pot_vnet() 18 | { 19 | _is_pot_vnet test-pot-vnet-ip4 20 | rc=$? 21 | assertEquals "is_pot_vnet" "0" "$rc" 22 | } 23 | 24 | setUp() 25 | { 26 | conf_setUp 27 | } 28 | 29 | tearDown() 30 | { 31 | conf_tearDown 32 | } 33 | . shunit/shunit2 34 | -------------------------------------------------------------------------------- /tests/common7.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | find() 6 | { 7 | cat << MANIFEST-EOF 8 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-12.0-RELEASE 9 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-10.0-RELEASE 10 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-10.4-RELEASE 11 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-11.0-RELEASE 12 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-9.1-RELEASE 13 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-9.0-RELEASE 14 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-10.1-RELEASE 15 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-11.1-RELEASE 16 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-9.2-RELEASE 17 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-10.3-RELEASE 18 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-11.2-RELEASE 19 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-10.2-RELEASE 20 | /usr/local/share/freebsd/MANIFESTS/amd64-amd64-9.3-RELEASE 21 | MANIFEST-EOF 22 | } 23 | 24 | sysctl() 25 | { 26 | if [ "$2" = "hw.machine_arch" ]; then 27 | echo "$__arch" 28 | elif [ "$2" = "hw.machine" ]; then 29 | echo "$__machine" 30 | else 31 | return 1 # failure 32 | fi 33 | } 34 | 35 | hostname() 36 | { 37 | echo "test-host" 38 | } 39 | 40 | # UUT 41 | . ../share/pot/common.sh 42 | 43 | # common stubs 44 | . ./monitor.sh 45 | 46 | # app specific stubs 47 | 48 | 49 | test_get_arch_001() 50 | { 51 | result="$(_get_arch)" 52 | assertEquals "amd64-amd64" "$result" 53 | 54 | __machine="i386" 55 | __arch="i386" 56 | result="$(_get_arch)" 57 | assertEquals "i386-i386" "$result" 58 | 59 | __machine="arm64" 60 | __arch="aarch64" 61 | result="$(_get_arch)" 62 | assertEquals "arm64-aarch64" "$result" 63 | } 64 | 65 | test_get_valid_releases_001() 66 | { 67 | result="$( _get_valid_releases )" 68 | assertEquals "9.0 9.1 9.2 9.3 10.0 10.1 10.2 10.3 10.4 11.0 11.1 11.2 12.0 " "$result" 69 | } 70 | 71 | test_is_valid_release_001() 72 | { 73 | # valid release 74 | _is_valid_release 11.0 75 | assertEquals "0" "$?" 76 | } 77 | 78 | test_is_valid_release_002() 79 | { 80 | # invalid release 81 | _is_valid_release 10.8 82 | assertEquals "1" "$?" 83 | 84 | # invalid call 85 | _is_valid_release 86 | assertEquals "1" "$?" 87 | } 88 | 89 | test_get_usable_hostname_001() 90 | { 91 | result="$( _get_usable_hostname pot-short-name )" 92 | assertEquals "pot-short-name.test-host" "$result" 93 | 94 | } 95 | 96 | test_get_usable_hostname_002() 97 | { 98 | result="$( _get_usable_hostname pot-long-name-01234567890123456789012345678901234567890123456789 )" 99 | assertEquals "pot-long-name-01234567890123456789012345678901234567890123456789" "$result" 100 | } 101 | 102 | test_get_usable_hostname_003() 103 | { 104 | result="$( _get_usable_hostname pot-long-name-012345678901234567890123456789012345678901234567890123456789 )" 105 | assertEquals "pot-long-name-01234567890123456789012345678901234567890123456789" "$result" 106 | } 107 | 108 | test_get_usable_hostname_004() 109 | { 110 | export POT_HOSTNAME_MAX_LENGTH=62 111 | result="$( _get_usable_hostname pot-long-name-012345678901234567890123456789012345678901234567890123456789 )" 112 | assertEquals "pot-long-name-012345678901234567890123456789012345678901234567" "$result" 113 | } 114 | 115 | setUp() 116 | { 117 | __mon_init 118 | __machine="amd64" 119 | __arch="amd64" 120 | } 121 | 122 | tearDown() 123 | { 124 | __mon_tearDown 125 | } 126 | 127 | . shunit/shunit2 128 | -------------------------------------------------------------------------------- /tests/common8.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/common.sh 7 | 8 | test_is_natural_number_001() 9 | { 10 | _is_natural_number 123 11 | assertTrue "number is not a number" "$?" 12 | } 13 | 14 | test_contains_spaces_001() 15 | { 16 | _contains_spaces "no-spaces" 17 | assertFalse "found spaces in a string with no spaces" "$?" 18 | } 19 | 20 | test_contains_spaces_002() 21 | { 22 | _contains_spaces "with spaces" 23 | assertTrue "not found spaces in a string with spaces" "$?" 24 | 25 | _contains_spaces "/mnt/with space" 26 | assertTrue "not found spaces in a string with spaces" "$?" 27 | 28 | _contains_spaces "/mnt/space " 29 | assertTrue "not found spaces in a string with spaces" "$?" 30 | } 31 | . shunit/shunit2 32 | -------------------------------------------------------------------------------- /tests/conf-stub.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | conf_setUp() 4 | { 5 | POT_FS_ROOT=/tmp 6 | POT_ZFS_ROOT=zpot 7 | 8 | /bin/mkdir -p /tmp/jails/test-pot/conf 9 | { 10 | echo "zpot/bases/11.1 /tmp/jails/test-pot/m ro" 11 | echo "zpot/jails/test-pot/usr.local /tmp/jails/test-pot/m/usr/local zfs-remount" 12 | echo "zpot/jails/test-pot/custom /tmp/jails/test-pot/m/opt/custom zfs-remount" 13 | } > /tmp/jails/test-pot/conf/fscomp.conf 14 | { 15 | echo "host.hostname=\"test-pot.test\"" 16 | echo "pot.potbase=" 17 | } > /tmp/jails/test-pot/conf/pot.conf 18 | 19 | /bin/mkdir -p /tmp/jails/test-pot-2/conf 20 | { 21 | echo "zpot/bases/11.1 /tmp/jails/test-pot-2/m ro" 22 | echo "zpot/jails/test-pot/usr.local /tmp/jails/test-pot-2/m/usr/local ro" 23 | echo "zpot/jails/test-pot-2/custom /tmp/jails/test-pot-2/m/opt/custom zfs-remount" 24 | } > /tmp/jails/test-pot-2/conf/fscomp.conf 25 | { 26 | echo "host.hostname=\"test-pot-2.test\"" 27 | echo "pot.potbase=test-pot" 28 | } > /tmp/jails/test-pot-2/conf/pot.conf 29 | 30 | /bin/mkdir -p /tmp/jails/test-pot-nosnap/conf 31 | { 32 | echo "zpot/bases/11.1 /tmp/jails/test-pot-nosnap/m ro" 33 | echo "zpot/jails/test-pot-nosnap/usr.local /tmp/jails/test-pot-nosnap/m/usr/local zfs-remount" 34 | echo "zpot/jails/test-pot-nosnap/custom /tmp/jails/test-pot-nosnap/m/opt/custom zfs-remount" 35 | } > /tmp/jails/test-pot-nosnap/conf/fscomp.conf 36 | { 37 | echo "host.hostname=\"test-pot-nosnap.test\"" 38 | echo "pot.potbase=" 39 | echo "pot.depend=test-pot" 40 | } > /tmp/jails/test-pot-nosnap/conf/pot.conf 41 | 42 | /bin/mkdir -p /tmp/jails/test-pot-single/conf 43 | touch /tmp/jails/test-pot-single/conf/fscomp.conf 44 | { 45 | echo "host.hostname=\"test-pot-single.test\"" 46 | echo "pot.potbase=" 47 | } > /tmp/jails/test-pot-single/conf/pot.conf 48 | 49 | /bin/mkdir -p /tmp/jails/test-pot-single-run/conf 50 | { 51 | echo "zpot/fscomp/examples /tmp/jails/test-pot-single-run/m/tmp/examples ro" 52 | } > /tmp/jails/test-pot-single-run/conf/fscomp.conf 53 | { 54 | echo "host.hostname=\"test-pot-single-run.test\"" 55 | echo "pot.potbase=" 56 | } > /tmp/jails/test-pot-single-run/conf/pot.conf 57 | 58 | /bin/mkdir -p /tmp/jails/test-pot-vnet-ip4/conf 59 | touch /tmp/jails/test-pot-vnet-ip4/conf/fscomp.conf 60 | { 61 | echo "pot.level=0" 62 | echo "pot.type=single" 63 | echo "pot.base=12.0" 64 | echo "pot.potbase=" 65 | echo "pot.dns=inherit" 66 | echo "pot.cmd=sh /etc/rc" 67 | echo "host.hostname=\"test-pot-vnet-ip4.test\"" 68 | echo "0" 69 | echo "osrelease=\"12.0-RELEASE\"" 70 | echo "ip=10.192.0.3" 71 | echo "network_type=public-network" 72 | echo "vnet=true" 73 | echo "pot.export.ports=80 443" 74 | } > /tmp/jails/test-pot-vnet-ip4/conf/pot.conf 75 | } 76 | 77 | conf_tearDown() 78 | { 79 | rm -rf /tmp/jails 80 | } 81 | 82 | -------------------------------------------------------------------------------- /tests/config1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/config.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | . common-stub.sh 11 | 12 | # app specific stubs 13 | config-help() 14 | { 15 | __monitor HELP "$@" 16 | } 17 | 18 | _config_echo() 19 | { 20 | __monitor CONFECHO "$@" 21 | } 22 | 23 | test_pot_config_001() 24 | { 25 | pot-config 26 | assertEquals "Exit rc" "1" "$?" 27 | assertEqualsMon "Help calls" "1" HELP_CALLS 28 | assertEqualsMon "Error calls" "1" ERROR_CALLS 29 | assertEqualsMon "config_echo calls" "0" CONFECHO_CALLS 30 | 31 | setUp 32 | pot-config -k bb 33 | assertEquals "Exit rc" "1" "$?" 34 | assertEqualsMon "Help calls" "1" HELP_CALLS 35 | assertEqualsMon "Error calls" "0" ERROR_CALLS 36 | assertEqualsMon "config_echo calls" "0" CONFECHO_CALLS 37 | 38 | setUp 39 | pot-config -h 40 | assertEquals "Exit rc" "0" "$?" 41 | assertEqualsMon "Help calls" "1" HELP_CALLS 42 | assertEqualsMon "Error calls" "0" ERROR_CALLS 43 | assertEqualsMon "config_echo calls" "0" CONFECHO_CALLS 44 | } 45 | 46 | test_pot_config_002() 47 | { 48 | pot-config -q 49 | assertEquals "Exit rc" "1" "$?" 50 | assertEqualsMon "Help calls" "0" HELP_CALLS 51 | assertEqualsMon "Error calls" "0" ERROR_CALLS 52 | assertEqualsMon "config_echo calls" "0" CONFECHO_CALLS 53 | } 54 | 55 | test_pot_config_010() 56 | { 57 | pot-config -g noname 58 | assertEquals "Exit rc" "1" "$?" 59 | assertEqualsMon "Help calls" "1" HELP_CALLS 60 | assertEqualsMon "Error calls" "1" ERROR_CALLS 61 | assertEqualsMon "config_echo calls" "0" CONFECHO_CALLS 62 | } 63 | 64 | test_pot_config_020() 65 | { 66 | pot-config -g gateway 67 | assertEquals "Exit rc" "0" "$?" 68 | assertEqualsMon "Help calls" "0" HELP_CALLS 69 | assertEqualsMon "Error calls" "0" ERROR_CALLS 70 | assertEqualsMon "config_echo calls" "1" CONFECHO_CALLS 71 | assertEqualsMon "config_echo arg" "NO" CONFECHO_CALL1_ARG1 72 | assertEqualsMon "config_echo arg" "gateway" CONFECHO_CALL1_ARG2 73 | assertEqualsMon "config_echo arg" "10.1.2.3" CONFECHO_CALL1_ARG3 74 | } 75 | 76 | setUp() 77 | { 78 | common_setUp 79 | POT_GATEWAY="10.1.2.3" 80 | } 81 | 82 | . shunit/shunit2 83 | -------------------------------------------------------------------------------- /tests/create-fscomp1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | zfs() 5 | { 6 | __monitor ZFS "$@" 7 | return 0 # true 8 | } 9 | 10 | # UUT 11 | . ../share/pot/create-fscomp.sh 12 | 13 | # common stubs 14 | . common-stub.sh 15 | 16 | _zfs_dataset_valid() 17 | { 18 | __monitor ZDSET "$@" 19 | if [ "$1" = "/fscomp/test-fscomp" ]; then 20 | return 0 # true 21 | fi 22 | return 1 # false 23 | } 24 | 25 | _is_init() 26 | { 27 | return 0 # true 28 | } 29 | 30 | # app specific stubs 31 | create-fscomp-help() 32 | { 33 | __monitor HELP "$@" 34 | } 35 | 36 | test_pot_create_fscomp_001() 37 | { 38 | pot-create-fscomp 39 | assertEquals "Exit rc" "1" "$?" 40 | assertEqualsMon "Help calls" "1" HELP_CALLS 41 | assertEqualsMon "Error calls" "1" ERROR_CALLS 42 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 43 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 44 | 45 | setUp 46 | pot-create-fscomp -vb 47 | assertEquals "Exit rc" "1" "$?" 48 | assertEqualsMon "Help calls" "1" HELP_CALLS 49 | assertEqualsMon "Error calls" "0" ERROR_CALLS 50 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 51 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 52 | 53 | setUp 54 | pot-create-fscomp -b bb 55 | assertEquals "Exit rc" "1" "$?" 56 | assertEqualsMon "Help calls" "1" HELP_CALLS 57 | assertEqualsMon "Error calls" "0" ERROR_CALLS 58 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 59 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 60 | 61 | setUp 62 | pot-create-fscomp -h 63 | assertEquals "Exit rc" "0" "$?" 64 | assertEqualsMon "Help calls" "1" HELP_CALLS 65 | assertEqualsMon "Error calls" "0" ERROR_CALLS 66 | assertEqualsMon "_zfs_dataset_valid calls" "0" ZDSET_CALLS 67 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 68 | } 69 | 70 | test_pot_create_fscomp_002() 71 | { 72 | pot-create-fscomp -f test-fscomp 73 | assertEquals "Exit rc" "0" "$?" 74 | assertEqualsMon "Help calls" "0" HELP_CALLS 75 | assertEqualsMon "Error calls" "0" ERROR_CALLS 76 | assertEqualsMon "_zfs_dataset_valid calls" "1" ZDSET_CALLS 77 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 78 | assertEqualsMon "zfs calls" "0" ZFS_CALLS 79 | } 80 | 81 | test_pot_create_fscomp_020() 82 | { 83 | pot-create-fscomp -f new-fscomp 84 | assertEquals "Exit rc" "0" "$?" 85 | assertEqualsMon "Help calls" "0" HELP_CALLS 86 | assertEqualsMon "Error calls" "0" ERROR_CALLS 87 | assertEqualsMon "_zfs_dataset_valid calls" "1" ZDSET_CALLS 88 | assertEqualsMon "_is_uid0 calls" "1" ISUID0_CALLS 89 | assertEqualsMon "zfs calls" "1" ZFS_CALLS 90 | assertEqualsMon "zfs arg1" "create" ZFS_CALL1_ARG1 91 | assertEqualsMon "zfs arg2" "/fscomp/new-fscomp" ZFS_CALL1_ARG2 92 | } 93 | 94 | setUp() 95 | { 96 | common_setUp 97 | } 98 | 99 | . shunit/shunit2 100 | -------------------------------------------------------------------------------- /tests/create-private-bridge1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | mkdir() 5 | { 6 | __monitor MKDIR "$@" 7 | } 8 | 9 | # UUT 10 | . ../share/pot/create-private-bridge.sh 11 | 12 | # common stubs 13 | . common-stub.sh 14 | 15 | _is_potnet_available() 16 | { 17 | return 0 # true 18 | } 19 | 20 | _is_bridge() 21 | { 22 | if [ "$1" = "test-bridge" ]; then 23 | return 0 # true 24 | fi 25 | return 1 26 | } 27 | 28 | # app specific stubs 29 | 30 | create-private-bridge-help() 31 | { 32 | __monitor HELP "$@" 33 | } 34 | 35 | create-bridge() 36 | { 37 | __monitor CB "$@" 38 | } 39 | 40 | test_create_private_bridge_001() 41 | { 42 | pot-create-private-bridge 43 | assertEquals "Exit rc" "1" "$?" 44 | assertEqualsMon "Error calls" "1" ERROR_CALLS 45 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 46 | 47 | setUp 48 | pot-create-private-bridge -vL 49 | assertEquals "Exit rc" "1" "$?" 50 | assertEqualsMon "Help calls" "1" HELP_CALLS 51 | assertEqualsMon "Error calls" "0" ERROR_CALLS 52 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 53 | 54 | setUp 55 | pot-create-private-bridge -L bb 56 | assertEquals "Exit rc" "1" "$?" 57 | assertEqualsMon "Help calls" "1" HELP_CALLS 58 | assertEqualsMon "Error calls" "0" ERROR_CALLS 59 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 60 | 61 | setUp 62 | pot-create-private-bridge -h 63 | assertEquals "Exit rc" "0" "$?" 64 | assertEqualsMon "Help calls" "1" HELP_CALLS 65 | assertEqualsMon "Error calls" "0" ERROR_CALLS 66 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 67 | } 68 | 69 | test_create_private_bridge_002() 70 | { 71 | pot-create-private-bridge -B test-bridge 72 | assertEquals "Exit rc" "1" "$?" 73 | assertEqualsMon "Error calls" "1" ERROR_CALLS 74 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 75 | assertEqualsMon "_create_bridge calls" "0" CB_CALLS 76 | } 77 | 78 | test_create_private_bridge_003() 79 | { 80 | pot-create-private-bridge -S 5 81 | assertEquals "Exit rc" "1" "$?" 82 | assertEqualsMon "Error calls" "1" ERROR_CALLS 83 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 84 | assertEqualsMon "_create_bridge calls" "0" CB_CALLS 85 | } 86 | 87 | test_create_private_bridge_010() 88 | { 89 | # bridge already exists 90 | pot-create-private-bridge -B test-bridge -S 5 91 | assertEquals "Exit rc" "1" "$?" 92 | assertEqualsMon "Error calls" "1" ERROR_CALLS 93 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 94 | assertEqualsMon "_create_bridge calls" "0" CB_CALLS 95 | } 96 | 97 | test_create_private_bridge_020() 98 | { 99 | pot-create-private-bridge -B new-test-bridge -S 5 100 | assertEquals "Exit rc" "0" "$?" 101 | assertEqualsMon "Help calls" "0" HELP_CALLS 102 | assertEqualsMon "Error calls" "0" ERROR_CALLS 103 | assertEqualsMon "_is_uid0 calls" "1" ISUID0_CALLS 104 | assertEqualsMon "_create_bridge calls" "1" CB_CALLS 105 | assertEqualsMon "_create_bridge arg1" "new-test-bridge" CB_CALL1_ARG1 106 | assertEqualsMon "_create_bridge arg2" "5" CB_CALL1_ARG2 107 | } 108 | 109 | setUp() 110 | { 111 | common_setUp 112 | } 113 | 114 | . shunit/shunit2 115 | -------------------------------------------------------------------------------- /tests/get-rss1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/get-rss.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | . common-stub.sh 11 | 12 | # app specific stubs 13 | get-rss-help() 14 | { 15 | __monitor HELP "$@" 16 | } 17 | 18 | _is_rctl_available() 19 | { 20 | return 0 # true 21 | } 22 | 23 | print_rss() 24 | { 25 | __monitor PRINT "$@" 26 | } 27 | 28 | test_pot_get_rss_001() 29 | { 30 | pot-get-rss 31 | assertEquals "Exit rc" "1" "$?" 32 | assertEqualsMon "Help calls" "1" HELP_CALLS 33 | assertEqualsMon "Error calls" "1" ERROR_CALLS 34 | assertEqualsMon "print_rss calls" "0" PRINT_CALLS 35 | 36 | setUp 37 | pot-get-rss -b bb 38 | assertEquals "Exit rc" "1" "$?" 39 | assertEqualsMon "Help calls" "1" HELP_CALLS 40 | assertEqualsMon "Error calls" "0" ERROR_CALLS 41 | assertEqualsMon "print_rss calls" "0" PRINT_CALLS 42 | 43 | setUp 44 | pot-get-rss -h 45 | assertEquals "Exit rc" "0" "$?" 46 | assertEqualsMon "Help calls" "1" HELP_CALLS 47 | assertEqualsMon "Error calls" "0" ERROR_CALLS 48 | assertEqualsMon "print_rss calls" "0" PRINT_CALLS 49 | } 50 | 51 | test_pot_get_rss_002() 52 | { 53 | pot-get-rss -p test-no-pot 54 | assertEquals "Exit rc" "1" "$?" 55 | assertEqualsMon "Help calls" "0" HELP_CALLS 56 | assertEqualsMon "Error calls" "1" ERROR_CALLS 57 | assertEqualsMon "print_rss calls" "0" PRINT_CALLS 58 | } 59 | 60 | test_pot_get_rss_020() 61 | { 62 | pot-get-rss -p test-pot-run 63 | assertEquals "Exit rc" "0" "$?" 64 | assertEqualsMon "Help calls" "0" HELP_CALLS 65 | assertEqualsMon "Error calls" "0" ERROR_CALLS 66 | assertEqualsMon "print_rss calls" "1" PRINT_CALLS 67 | assertEqualsMon "print_rss arg1" "test-pot-run" PRINT_CALL1_ARG1 68 | assertEqualsMon "print_rss arg2" "" PRINT_CALL1_ARG2 69 | } 70 | 71 | test_pot_get_rss_021() 72 | { 73 | pot-get-rss -p test-pot-run-2 -J 74 | assertEquals "Exit rc" "0" "$?" 75 | assertEqualsMon "Help calls" "0" HELP_CALLS 76 | assertEqualsMon "Error calls" "0" ERROR_CALLS 77 | assertEqualsMon "print_rss calls" "1" PRINT_CALLS 78 | assertEqualsMon "print_rss arg1" "test-pot-run-2" PRINT_CALL1_ARG1 79 | assertEqualsMon "print_rss arg2" "YES" PRINT_CALL1_ARG2 80 | } 81 | 82 | setUp() 83 | { 84 | common_setUp 85 | } 86 | 87 | . shunit/shunit2 88 | -------------------------------------------------------------------------------- /tests/info2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/info.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | 11 | _get_pot_network_stack() 12 | { 13 | 14 | echo "${_TEST_STACK:-"dual"}" 15 | } 16 | 17 | _get_pot_network_type() 18 | { 19 | case "$1" in 20 | test-pot-alias*) 21 | echo "alias" 22 | ;; 23 | *) 24 | echo "inherit" 25 | ;; 26 | esac 27 | } 28 | 29 | _get_ip_var() 30 | { 31 | case "$1" in 32 | test-pot-alias) 33 | echo "em0|192.168.0.1 em0|fe80::0" 34 | ;; 35 | *) 36 | echo "" 37 | ;; 38 | esac 39 | } 40 | 41 | _get_alias_ipv4() 42 | { 43 | if [ "$_TEST_STACK" = "ipv6" ]; then 44 | return 45 | fi 46 | case "$1" in 47 | test-pot-alias) 48 | echo "em0|192.168.0.1" 49 | ;; 50 | *) 51 | echo "" 52 | ;; 53 | esac 54 | } 55 | 56 | _get_alias_ipv6() 57 | { 58 | if [ "$_TEST_STACK" = "ipv4" ]; then 59 | return 60 | fi 61 | case "$1" in 62 | test-pot-alias) 63 | echo "em0|fe80::0" 64 | ;; 65 | *) 66 | echo "" 67 | ;; 68 | esac 69 | } 70 | 71 | # app specific stubs 72 | 73 | test_info_pot_env_001() 74 | { 75 | assertEquals "inherit has IP" "export _POT_IP=" "$(_info_pot_env test-pot-inherit | grep _POT_IP= )" 76 | } 77 | 78 | test_info_pot_env_020() 79 | { 80 | assertEquals "alias has wrong IP" "export _POT_IP=192.168.0.1" "$( _info_pot_env test-pot-alias | grep _POT_IP= )" 81 | assertEquals "alias has wrong IP LIST" "$( _info_pot_env test-pot-alias | grep _POT_IP_LIST= )" "export _POT_IP_LIST=_POT_IP_0\ _POT_IP_1" 82 | assertEquals "alias has wrong NIC LIST" "$( _info_pot_env test-pot-alias | grep _POT_NIC_LIST= )" "export _POT_NIC_LIST=_POT_NIC_0\ _POT_NIC_1" 83 | assertEquals "alias has wrong IP 0" "$( _info_pot_env test-pot-alias | grep _POT_IP_0= )" "export _POT_IP_0=192.168.0.1" 84 | assertEquals "alias has wrong IP 1" "$( _info_pot_env test-pot-alias | grep _POT_IP_1= )" "export _POT_IP_1=fe80::0" 85 | assertEquals "alias has wrong NIC 0" "$( _info_pot_env test-pot-alias | grep _POT_NIC_0= )" "export _POT_NIC_0=em0" 86 | assertEquals "alias has wrong NIC 1" "$( _info_pot_env test-pot-alias | grep _POT_NIC_1= )" "export _POT_NIC_1=em0" 87 | } 88 | 89 | test_info_pot_env_021() 90 | { 91 | _TEST_STACK="ipv4" 92 | assertEquals "alias has wrong IP" "$( _info_pot_env test-pot-alias | grep _POT_IP= )" "export _POT_IP=192.168.0.1" 93 | assertEquals "alias has wrong IP LIST" "$( _info_pot_env test-pot-alias | grep _POT_IP_LIST= )" "export _POT_IP_LIST=_POT_IP_0" 94 | assertEquals "alias has wrong NIC LIST" "$( _info_pot_env test-pot-alias | grep _POT_NIC_LIST= )" "export _POT_NIC_LIST=_POT_NIC_0" 95 | assertEquals "alias has wrong IP 0" "$( _info_pot_env test-pot-alias | grep _POT_IP_0= )" "export _POT_IP_0=192.168.0.1" 96 | assertEquals "alias has wrong NIC 0" "$( _info_pot_env test-pot-alias | grep _POT_NIC_0= )" "export _POT_NIC_0=em0" 97 | } 98 | 99 | test_info_pot_env_022() 100 | { 101 | _TEST_STACK="ipv6" 102 | assertEquals "alias has wrong IP" "$( _info_pot_env test-pot-alias | grep _POT_IP= )" "export _POT_IP=fe80::0" 103 | assertEquals "alias has wrong IP LIST" "$( _info_pot_env test-pot-alias | grep _POT_IP_LIST= )" "export _POT_IP_LIST=_POT_IP_0" 104 | assertEquals "alias has wrong NIC LIST" "$( _info_pot_env test-pot-alias | grep _POT_NIC_LIST= )" "export _POT_NIC_LIST=_POT_NIC_0" 105 | assertEquals "alias has wrong IP 0" "$( _info_pot_env test-pot-alias | grep _POT_IP_0= )" "export _POT_IP_0=fe80::0" 106 | assertEquals "alias has wrong NIC 0" "$( _info_pot_env test-pot-alias | grep _POT_NIC_0= )" "export _POT_NIC_0=em0" 107 | } 108 | . shunit/shunit2 109 | -------------------------------------------------------------------------------- /tests/list2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/list.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | . common-stub.sh 11 | 12 | # app specific stubs 13 | zfs() 14 | { 15 | if [ "$1" = "list" ]; then 16 | if [ "$6" = "zroot/pot1/fscomp" ]; then 17 | echo "zroot/pot1/fscomp" 18 | echo "zroot/pot1/fscomp/fscomp1" 19 | elif [ "$6" = "zroot/pot2/fscomp" ]; then 20 | echo "zroot/pot1/fscomp" 21 | echo "zroot/pot2/fscomp/fscomp1" 22 | echo "zroot/pot2/fscomp/fscomp2" 23 | elif [ "$6" = "zroot/pot3/fscomp" ]; then 24 | echo "zroot/pot1/fscomp" 25 | echo "zroot/pot3/fscomp/fscomp1" 26 | echo "zroot/pot3/fscomp/fscomp2" 27 | echo "zroot/pot3/fscomp/fscomp3" 28 | else 29 | echo "error2" 30 | fi 31 | else 32 | echo "error" 33 | fi 34 | } 35 | 36 | test_pot_list_fscomp001() 37 | { 38 | POT_ZFS_ROOT=zroot/pot1 39 | rc=$( _ls_fscomp ) 40 | assertEquals "rc" "fscomp: fscomp1" "$rc" 41 | } 42 | 43 | test_pot_list_fscomp002() 44 | { 45 | POT_ZFS_ROOT=zroot/pot2 46 | rc=$( _ls_fscomp | tr '\n' ' ') 47 | assertEquals "rc" "fscomp: fscomp1 fscomp: fscomp2 " "$rc" 48 | } 49 | 50 | test_pot_list_fscomp003() 51 | { 52 | POT_ZFS_ROOT=zroot/pot3 53 | rc=$( _ls_fscomp | tr '\n' ' ') 54 | assertEquals "rc" "fscomp: fscomp1 fscomp: fscomp2 fscomp: fscomp3 " "$rc" 55 | } 56 | 57 | setUp() 58 | { 59 | common_setUp 60 | } 61 | 62 | . shunit/shunit2 63 | -------------------------------------------------------------------------------- /tests/monitor.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # shellcheck disable=SC3043 3 | 4 | if [ -z "$POT_MONITOR_TMP" ]; then 5 | if [ "$(command uname)" = "Linux" ]; then 6 | POT_MONITOR_TMP=/dev/shm 7 | else 8 | POT_MONITOR_TMP="${TMPDIR:-/tmp}" 9 | fi 10 | POT_MONITOR_TMP=$(command mktemp -d \ 11 | "${POT_MONITOR_TMP}/pot-monitor.XXXXXX") || exit 1 12 | export POT_MONITOR_TMP 13 | fi 14 | 15 | __mon_put() 16 | { 17 | local k v 18 | k="$1" 19 | shift 20 | v="$*" 21 | printf %s "$v" >"$POT_MONITOR_TMP/$k" 22 | } 23 | 24 | __mon_get() 25 | { 26 | local k d r 27 | k="$1" 28 | d="$2" 29 | 30 | if [ -e "$POT_MONITOR_TMP/$k" ]; then 31 | r=$(command cat "$POT_MONITOR_TMP/$k") 32 | fi 33 | 34 | if [ -n "$r" ]; then 35 | echo "$r" 36 | elif [ -n "$d" ]; then 37 | echo "$d" 38 | fi 39 | } 40 | 41 | __mon_export() 42 | { 43 | local k v 44 | 45 | for k in "$POT_MONITOR_TMP"/*; do 46 | v=$(command cat "$k") 47 | export "$k"="$v" 48 | done 49 | } 50 | 51 | __mon_init() 52 | { 53 | command mkdir -p "$POT_MONITOR_TMP" || exit 1 54 | command rm -f "$POT_MONITOR_TMP"/* || exit 1 55 | } 56 | 57 | __monitor_int() 58 | { 59 | local M i C 60 | i=0 61 | M=$1 62 | shift 63 | C="$(__mon_get "${M}_CALLS" 0)" 64 | C=$(( C + 1 )) 65 | __mon_put "${M}_CALLS" "$C" 66 | while [ -n "$1" ] || [ -n "$2" ] || [ -n "$3" ]; do 67 | i=$(( i + 1 )) 68 | __mon_put "${M}_CALL${C}_ARG${i}" "$1" 69 | shift 70 | done 71 | } 72 | 73 | __monitor() 74 | { 75 | # requires "pkg install flock" on FreebSD 76 | ( 77 | command flock -x -w 10 9 78 | __monitor_int "$@" 79 | ) 9>"$POT_MONITOR_TMP.lock" 80 | } 81 | 82 | __mon_tearDown() 83 | { 84 | if [ -e "$POT_MONITOR_TMP" ]; then 85 | command rm -rf "$POT_MONITOR_TMP" 86 | fi 87 | if [ -e "$POT_MONITOR_TMP.lock" ]; then 88 | command rm "$POT_MONITOR_TMP.lock" 89 | fi 90 | } 91 | 92 | # $1 name 93 | # $2 left hand 94 | # $3 key of right hand mon var 95 | # $4 default value to compare to 96 | # "" defaults to 0 in case key ends on "_CALLS" 97 | assertEqualsMon() 98 | { 99 | local n l k d 100 | n="$1" 101 | l="$2" 102 | k="$3" 103 | d="$4" 104 | if [ -z "$d" ] && [ "$k" != "${k%%_CALLS}" ]; then 105 | d="0" 106 | fi 107 | assertEquals "$n" "$l" "$(__mon_get "$k" "$d")" 108 | } 109 | 110 | # $1 name 111 | # $2 left hand 112 | # $3 key of right hand mon var 113 | # $4 default value to compare to 114 | # "" defaults to 0 in case key ends on "_CALLS" 115 | assertNotEqualsMon() 116 | { 117 | local n l k d 118 | n="$1" 119 | l="$2" 120 | k="$3" 121 | d="$4" 122 | if [ -z "$d" ] && [ "$k" != "${k%%_CALLS}" ]; then 123 | d="0" 124 | fi 125 | assertNotEquals "$n" "$l" "$(__mon_get "$k" "$d")" 126 | } 127 | -------------------------------------------------------------------------------- /tests/mount-out1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | if [ "$(uname)" = "Linux" ]; then 6 | TEST=/usr/bin/[ 7 | else 8 | TEST=/bin/[ 9 | fi 10 | 11 | [() 12 | { 13 | if ${TEST} "$1" = "!" ]; then 14 | if ${TEST} "$2" = "-d" ]; then 15 | if ${TEST} "$3" = "test-dir" ]; then 16 | return 1 # false 17 | fi 18 | fi 19 | fi 20 | ${TEST} "$@" 21 | return $? 22 | } 23 | 24 | realpath() 25 | { 26 | __monitor REALPATH "$@" 27 | if [ "$2" = "test-dir" ]; then 28 | echo "/home/test-dir" 29 | return 0 # true 30 | fi 31 | return 1 # false 32 | } 33 | 34 | logger() 35 | { 36 | : 37 | } 38 | 39 | # UUT 40 | . ../share/pot/mount-out.sh 41 | 42 | # common stubs 43 | . common-stub.sh 44 | 45 | # app specific stubs 46 | mount-out-help() 47 | { 48 | __monitor HELP "$@" 49 | return 0 # true 50 | } 51 | 52 | _mountpoint_validation() 53 | { 54 | __monitor MPVALID "$@" 55 | echo "$2" 56 | } 57 | 58 | _umount_mnt_p() 59 | { 60 | __monitor UMNT_P "$@" 61 | } 62 | 63 | test_pot_mount_in_001() 64 | { 65 | pot-mount-out 66 | assertEquals "Exit rc" "1" "$?" 67 | assertEqualsMon "Help calls" "1" HELP_CALLS 68 | assertEqualsMon "Error calls" "1" ERROR_CALLS 69 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 70 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 71 | assertEqualsMon "_umount_mnt_p calls" "0" UMNT_P_CALLS 72 | 73 | setUp 74 | pot-mount-out -vb 75 | assertEquals "Exit rc" "1" "$?" 76 | assertEqualsMon "Help calls" "1" HELP_CALLS 77 | assertEqualsMon "Error calls" "0" ERROR_CALLS 78 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 79 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 80 | assertEqualsMon "_umount_mnt_p calls" "0" UMNT_P_CALLS 81 | 82 | setUp 83 | pot-mount-out -b bb 84 | assertEqualsMon "Help calls" "1" HELP_CALLS 85 | assertEqualsMon "Error calls" "0" ERROR_CALLS 86 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 87 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 88 | assertEqualsMon "_umount_mnt_p calls" "0" UMNT_P_CALLS 89 | 90 | setUp 91 | pot-mount-out -h 92 | assertEquals "Exit rc" "0" "$?" 93 | assertEqualsMon "Help calls" "1" HELP_CALLS 94 | assertEqualsMon "Error calls" "0" ERROR_CALLS 95 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 96 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 97 | assertEqualsMon "_umount_mnt_p calls" "0" UMNT_P_CALLS 98 | } 99 | 100 | test_pot_mount_in_002() 101 | { 102 | pot-mount-out -p test-pot 103 | assertEquals "Exit rc" "1" "$?" 104 | assertEqualsMon "Help calls" "1" HELP_CALLS 105 | assertEqualsMon "Error calls" "1" ERROR_CALLS 106 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 107 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 108 | assertEqualsMon "_umount_mnt_p calls" "0" UMNT_P_CALLS 109 | 110 | setUp 111 | pot-mount-out -m /test-mnt 112 | assertEquals "Exit rc" "1" "$?" 113 | assertEqualsMon "Help calls" "1" HELP_CALLS 114 | assertEqualsMon "Error calls" "1" ERROR_CALLS 115 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 116 | assertEqualsMon "_is_uid0 calls" "0" ISUID0_CALLS 117 | assertEqualsMon "_umount_mnt_p calls" "0" UMNT_P_CALLS 118 | } 119 | 120 | test_pot_mount_in_020() 121 | { 122 | pot-mount-out -p test-pot -m /test-mnt 123 | assertEquals "Exit rc" "0" "$?" 124 | assertEqualsMon "Help calls" "0" HELP_CALLS 125 | assertEqualsMon "Error calls" "0" ERROR_CALLS 126 | assertEqualsMon "_is_pot calls" "1" ISPOT_CALLS 127 | assertEqualsMon "_is_uid0 calls" "1" ISUID0_CALLS 128 | assertEqualsMon "_umount_mnt_p calls" "1" UMNT_P_CALLS 129 | assertEqualsMon "_umount_mnt_p arg" "test-pot" UMNT_P_CALL1_ARG1 130 | assertEqualsMon "_umount_mnt_p arg" "/test-mnt" UMNT_P_CALL1_ARG2 131 | } 132 | 133 | setUp() 134 | { 135 | common_setUp 136 | POT_FS_ROOT=/tmp 137 | POT_ZFS_ROOT=zpot 138 | } 139 | 140 | . shunit/shunit2 141 | -------------------------------------------------------------------------------- /tests/pipefail-stub.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | _set_pipefail() 4 | { 5 | local _major _version 6 | if [ "$(uname)" = "Linux" ]; then 7 | set -o pipefail 8 | return 9 | fi 10 | _major="$(sysctl -n kern.osrelease | cut -f 1 -d '.')" 11 | _version="$(sysctl -n kern.osrelease | cut -f 1 -d '-')" 12 | if [ "$_major" -ge "13" ]; then 13 | set -o pipefail 14 | return 15 | fi 16 | case "$_version" in 17 | "12.1") 18 | set -o pipefail 19 | ;; 20 | esac 21 | } 22 | 23 | -------------------------------------------------------------------------------- /tests/ps1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/ps.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | . common-stub.sh 11 | 12 | # app specific stubs 13 | ps-help() 14 | { 15 | __monitor HELP "$@" 16 | } 17 | 18 | _ps_pots() 19 | { 20 | __monitor PSPOTS "$@" 21 | } 22 | 23 | _is_vnet_up() 24 | { 25 | return 0 # true 26 | } 27 | 28 | test_pot_ps_001() 29 | { 30 | pot-ps -b bb 31 | assertEquals "Exit rc" "1" "$?" 32 | assertEqualsMon "Help calls" "1" HELP_CALLS 33 | assertEqualsMon "Error calls" "0" ERROR_CALLS 34 | assertEqualsMon "ps_pots calls" "0" PSPOTS_CALLS 35 | 36 | setUp 37 | pot-ps -h 38 | assertEquals "Exit rc" "0" "$?" 39 | assertEqualsMon "Help calls" "1" HELP_CALLS 40 | assertEqualsMon "Error calls" "0" ERROR_CALLS 41 | assertEqualsMon "ps_pots calls" "0" PSPOTS_CALLS 42 | } 43 | 44 | test_pot_ps_020() 45 | { 46 | pot-ps -q 47 | assertEquals "Exit rc" "0" "$?" 48 | assertEqualsMon "Help calls" "0" HELP_CALLS 49 | assertEqualsMon "Error calls" "0" ERROR_CALLS 50 | assertEqualsMon "ps_pots calls" "1" PSPOTS_CALLS 51 | assertEqualsMon "ps_pots arg1" "quiet" PSPOTS_CALL1_ARG1 52 | } 53 | 54 | test_pot_ps_021() 55 | { 56 | pot-ps 57 | assertEquals "Exit rc" "0" "$?" 58 | assertEqualsMon "Help calls" "0" HELP_CALLS 59 | assertEqualsMon "Error calls" "0" ERROR_CALLS 60 | assertEqualsMon "ps_pots calls" "1" PSPOTS_CALLS 61 | assertEqualsMon "ps_pots arg1" "" PSPOTS_CALL1_ARG1 62 | } 63 | 64 | setUp() 65 | { 66 | common_setUp 67 | } 68 | 69 | . shunit/shunit2 70 | -------------------------------------------------------------------------------- /tests/rename2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | SED=sed_stub 5 | sed_stub() 6 | { 7 | if [ "$(uname)" = "Linux" ]; then 8 | sed -i'' "$3" "$4" "$5" 9 | else 10 | sed "$@" 11 | fi 12 | } 13 | 14 | # UUT 15 | . ../share/pot/rename.sh 16 | 17 | # common stubs 18 | . common-stub.sh 19 | . conf-stub.sh 20 | 21 | # app specific stubs 22 | hostname() 23 | { 24 | echo "test" 25 | } 26 | 27 | test_rn_conf_001() 28 | { 29 | _rn_conf test-pot new-pot 30 | assertEquals "fscomp args1" "zpot/bases/11.1 /tmp/jails/new-pot/m ro" "$(sed '1!d' /tmp/jails/test-pot/conf/fscomp.conf)" 31 | assertEquals "fscomp args2" "zpot/jails/new-pot/usr.local /tmp/jails/new-pot/m/usr/local zfs-remount" "$(sed '2!d' /tmp/jails/test-pot/conf/fscomp.conf)" 32 | assertEquals "fscomp args3" "zpot/jails/new-pot/custom /tmp/jails/new-pot/m/opt/custom zfs-remount" "$(sed '3!d' /tmp/jails/test-pot/conf/fscomp.conf)" 33 | assertEquals "host.hostname" "host.hostname=\"new-pot.test\"" "$(grep ^host.hostname /tmp/jails/test-pot/conf/pot.conf)" 34 | } 35 | 36 | setUp() 37 | { 38 | common_setUp 39 | conf_setUp 40 | } 41 | 42 | tearDown() 43 | { 44 | common_tearDown 45 | conf_tearDown 46 | } 47 | . shunit/shunit2 48 | -------------------------------------------------------------------------------- /tests/rename4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | ls() 5 | { 6 | cat << LS_EOL 7 | /opt/pot/jails/test-pot/ 8 | /opt/pot/jails/test-pot-2/ 9 | /opt/pot/jails/test-pot-nosnap/ 10 | LS_EOL 11 | } 12 | 13 | SED=sed_stub 14 | sed_stub() 15 | { 16 | if [ "$(uname)" = "Linux" ]; then 17 | sed -i'' "$3" "$4" "$5" 18 | else 19 | sed "$@" 20 | fi 21 | } 22 | 23 | # UUT 24 | . ../share/pot/rename.sh 25 | 26 | # common stubs 27 | . common-stub.sh 28 | . conf-stub.sh 29 | 30 | # app specific stubs 31 | 32 | test_rn_recursive_001() 33 | { 34 | _rn_recursive test-pot new-pot 35 | assertEquals "fscomp base" "zpot/bases/11.1 /tmp/jails/test-pot-2/m ro" "$(sed '1!d' /tmp/jails/test-pot-2/conf/fscomp.conf)" 36 | assertEquals "fscomp usr.local" "zpot/jails/new-pot/usr.local /tmp/jails/test-pot-2/m/usr/local ro" "$(sed '2!d' /tmp/jails/test-pot-2/conf/fscomp.conf)" 37 | assertEquals "fscomp custom" "zpot/jails/test-pot-2/custom /tmp/jails/test-pot-2/m/opt/custom zfs-remount" "$(sed '3!d' /tmp/jails/test-pot-2/conf/fscomp.conf)" 38 | assertEquals "pot.conf potbase" "pot.potbase=new-pot" "$(grep ^pot.potbase= /tmp/jails/test-pot-2/conf/pot.conf)" 39 | assertEquals "pot.conf depende" "pot.depend=new-pot" "$(grep ^pot.depend= /tmp/jails/test-pot-nosnap/conf/pot.conf)" 40 | } 41 | 42 | setUp() 43 | { 44 | common_setUp 45 | conf_setUp 46 | } 47 | 48 | tearDown() 49 | { 50 | common_tearDown 51 | conf_tearDown 52 | } 53 | 54 | . shunit/shunit2 55 | -------------------------------------------------------------------------------- /tests/set-attr2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/set-attribute.sh 7 | 8 | # common stubs 9 | . common-stub.sh 10 | 11 | # app specific stubs 12 | set-attribute-help() 13 | { 14 | __monitor HELP "$@" 15 | } 16 | 17 | test_normalize_true_false_1() 18 | { 19 | local rc 20 | if rc=$(_normalize_true_false YES) ; then 21 | assertEquals "YES" "$rc" 22 | else 23 | fail "it shouldn't be here" 24 | fi 25 | } 26 | 27 | test_normalize_true_false_2() 28 | { 29 | local rc 30 | if rc=$(_normalize_true_false NO) ; then 31 | assertEquals "NO" "$rc" 32 | else 33 | fail "it shouldn't be here" 34 | fi 35 | } 36 | 37 | test_normalize_true_false_3() 38 | { 39 | local rc 40 | if rc=$(_normalize_true_false asdfasdf) ; then 41 | fail "it shouldn't be here" 42 | else 43 | assertEquals "" "$rc" 44 | fi 45 | } 46 | 47 | setUp() 48 | { 49 | common_setUp 50 | } 51 | 52 | . shunit/shunit2 53 | -------------------------------------------------------------------------------- /tests/set-cmd1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/set-cmd.sh 7 | 8 | # common stubs 9 | . common-stub.sh 10 | 11 | # app specific stubs 12 | set-cmd-help() 13 | { 14 | __monitor HELP "$@" 15 | } 16 | 17 | _set_command() 18 | { 19 | __monitor SETCMD "$@" 20 | } 21 | 22 | test_pot_set_cmd_001() 23 | { 24 | pot-set-cmd 25 | assertEquals "Exit rc" "1" "$?" 26 | assertEqualsMon "Help calls" "1" HELP_CALLS 27 | assertEqualsMon "Error calls" "1" ERROR_CALLS 28 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 29 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 30 | 31 | setUp 32 | pot-set-cmd -bv 33 | assertEquals "Exit rc" "1" "$?" 34 | assertEqualsMon "Help calls" "1" HELP_CALLS 35 | assertEqualsMon "Error calls" "0" ERROR_CALLS 36 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 37 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 38 | 39 | setUp 40 | pot-set-cmd -b bb 41 | assertEquals "Exit rc" "1" "$?" 42 | assertEqualsMon "Help calls" "1" HELP_CALLS 43 | assertEqualsMon "Error calls" "0" ERROR_CALLS 44 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 45 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 46 | 47 | setUp 48 | pot-set-cmd -h 49 | assertEquals "Exit rc" "0" "$?" 50 | assertEqualsMon "Help calls" "1" HELP_CALLS 51 | assertEqualsMon "Error calls" "0" ERROR_CALLS 52 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 53 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 54 | } 55 | 56 | test_pot_set_cmd_002() 57 | { 58 | pot-set-cmd -p test-pot 59 | assertEquals "Exit rc" "1" "$?" 60 | assertEqualsMon "Help calls" "1" HELP_CALLS 61 | assertEqualsMon "Error calls" "1" ERROR_CALLS 62 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 63 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 64 | 65 | setUp 66 | pot-set-cmd -c sh 67 | assertEquals "Exit rc" "1" "$?" 68 | assertEqualsMon "Help calls" "1" HELP_CALLS 69 | assertEqualsMon "Error calls" "1" ERROR_CALLS 70 | assertEqualsMon "_is_pot calls" "0" ISPOT_CALLS 71 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 72 | } 73 | 74 | test_pot_set_cmd_020() 75 | { 76 | pot-set-cmd -p test-no-pot -c "sh /etc/rc" 77 | assertEquals "Exit rc" "1" "$?" 78 | assertEqualsMon "Help calls" "1" HELP_CALLS 79 | assertEqualsMon "Error calls" "1" ERROR_CALLS 80 | assertEqualsMon "_is_pot calls" "1" ISPOT_CALLS 81 | assertEqualsMon "_set_command calls" "0" SETCMD_CALLS 82 | } 83 | 84 | test_pot_set_cmd_040() 85 | { 86 | pot-set-cmd -p test-pot -c "/echo Hello World" 87 | assertEquals "Exit rc" "0" "$?" 88 | assertEqualsMon "Help calls" "0" HELP_CALLS 89 | assertEqualsMon "Error calls" "0" ERROR_CALLS 90 | assertEqualsMon "_is_pot calls" "1" ISPOT_CALLS 91 | assertEqualsMon "_set_command calls" "1" SETCMD_CALLS 92 | assertEqualsMon "_set_command arg1" "test-pot" SETCMD_CALL1_ARG1 93 | assertEqualsMon "_set_command arg2" "/echo Hello World" SETCMD_CALL1_ARG2 94 | } 95 | 96 | setUp() 97 | { 98 | common_setUp 99 | } 100 | 101 | . shunit/shunit2 102 | -------------------------------------------------------------------------------- /tests/set-env2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | SED=sed_stub 5 | sed_stub() 6 | { 7 | if [ "$(uname)" = "Linux" ]; then 8 | sed -i'' "$3" "$4" 9 | else 10 | sed "$@" 11 | fi 12 | } 13 | 14 | # UUT 15 | . ../share/pot/set-env.sh 16 | . ../share/pot/common.sh 17 | 18 | # common stubs 19 | . conf-stub.sh 20 | 21 | test_set_environment_000() 22 | { 23 | cat > /tmp/pot-set-env << EOF_SETENV 24 | "VAR=value" 25 | EOF_SETENV 26 | _set_environment test-pot /tmp/pot-set-env 27 | 28 | assertEquals "pot.env lines" "1" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 29 | assertEquals "pot.env args" 'pot.env="VAR=value"' "$(grep ^pot.env /tmp/jails/test-pot/conf/pot.conf)" 30 | } 31 | 32 | test_set_environment_001() 33 | { 34 | cat > /tmp/pot-set-env << EOF_SETENV 35 | "VAR=value" 36 | "VAR2=value2" 37 | EOF_SETENV 38 | _set_environment test-pot /tmp/pot-set-env 39 | 40 | assertEquals "pot.env lines" "2" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 41 | assertEquals "pot.env args" 'pot.env="VAR=value"' "$(grep "^pot.env=\"VAR=" /tmp/jails/test-pot/conf/pot.conf)" 42 | assertEquals "pot.env args" 'pot.env="VAR2=value2"' "$(grep "^pot.env=\"VAR2=" /tmp/jails/test-pot/conf/pot.conf)" 43 | } 44 | 45 | test_set_environment_002() 46 | { 47 | cat > /tmp/pot-set-env << EOF_SETENV 48 | "VAR=value1 value2" 49 | EOF_SETENV 50 | _set_environment test-pot /tmp/pot-set-env 51 | assertEquals "pot.env lines" "1" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 52 | assertEquals "pot.env args" 'pot.env="VAR=value1 value2"' "$(grep ^pot.env /tmp/jails/test-pot/conf/pot.conf)" 53 | } 54 | 55 | test_set_environment_003() 56 | { 57 | cat > /tmp/pot-set-env << EOF_SETENV 58 | "VAR=value1 value2" 59 | "VAR2=value3" 60 | EOF_SETENV 61 | _set_environment test-pot /tmp/pot-set-env 62 | assertEquals "pot.env lines" "2" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 63 | assertEquals "pot.env args" 'pot.env="VAR=value1 value2"' "$(grep "^pot.env=\"VAR=" /tmp/jails/test-pot/conf/pot.conf)" 64 | assertEquals "pot.env args" 'pot.env="VAR2=value3"' "$(grep "^pot.env=\"VAR2=" /tmp/jails/test-pot/conf/pot.conf)" 65 | } 66 | 67 | test_set_environment_004() 68 | { 69 | cat > /tmp/pot-set-env << EOF_SETENV 70 | "EMPTYVAR=" 71 | EOF_SETENV 72 | _set_environment test-pot /tmp/pot-set-env 73 | assertEquals "pot.env lines" "1" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 74 | assertEquals "pot.env args" 'pot.env="EMPTYVAR="' "$(grep ^pot.env /tmp/jails/test-pot/conf/pot.conf)" 75 | } 76 | 77 | test_set_environment_005() 78 | { 79 | cat > /tmp/pot-set-env << EOF_SETENV 80 | "VAR=12*" 81 | EOF_SETENV 82 | _set_environment test-pot /tmp/pot-set-env 83 | assertEquals "pot.env lines" "1" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 84 | assertEquals "pot.env args" 'pot.env="VAR=12*"' "$(grep ^pot.env /tmp/jails/test-pot/conf/pot.conf)" 85 | } 86 | 87 | test_set_environment_006() 88 | { 89 | cat > /tmp/pot-set-env << EOF_SETENV 90 | "VAR=12*" 91 | "VAR2=?h* " 92 | EOF_SETENV 93 | _set_environment test-pot /tmp/pot-set-env 94 | assertEquals "pot.env lines" "2" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 95 | assertEquals "pot.env args" 'pot.env="VAR=12*"' "$(grep "^pot.env=\"VAR=" /tmp/jails/test-pot/conf/pot.conf)" 96 | assertEquals "pot.env args" 'pot.env="VAR2=?h* "' "$(grep "^pot.env=\"VAR2=" /tmp/jails/test-pot/conf/pot.conf)" 97 | } 98 | 99 | test_set_environment_007() 100 | { 101 | cat > /tmp/pot-set-env << EOF_SETENV 102 | "VAR=value1 \"value2\"" 103 | EOF_SETENV 104 | _set_environment test-pot /tmp/pot-set-env 105 | assertEquals "pot.env lines" "1" "$(grep -c "^pot.env=" /tmp/jails/test-pot/conf/pot.conf)" 106 | assertEquals "pot.env args" 'pot.env="VAR=value1 \"value2\""' "$(grep "^pot.env=\"VAR=" /tmp/jails/test-pot/conf/pot.conf)" 107 | } 108 | 109 | setUp() 110 | { 111 | conf_setUp 112 | } 113 | 114 | tearDown() 115 | { 116 | conf_tearDown 117 | /bin/rm -f /tmp/pot-set-env 118 | } 119 | . shunit/shunit2 120 | -------------------------------------------------------------------------------- /tests/shunit/.gitignore: -------------------------------------------------------------------------------- 1 | # Hidden files generated by macOS. 2 | .DS_Store 3 | ._* 4 | -------------------------------------------------------------------------------- /tests/shunit/.travis.yml: -------------------------------------------------------------------------------- 1 | language: bash 2 | 3 | env: 4 | - SHUNIT_COLOR='always' 5 | 6 | script: 7 | # Execute the unit tests. 8 | - ./test_runner 9 | 10 | os: 11 | - linux 12 | - osx 13 | 14 | addons: 15 | apt: 16 | packages: 17 | - ksh 18 | - zsh 19 | 20 | matrix: 21 | include: 22 | - os: linux 23 | script: 24 | # Run the source through ShellCheck (http://www.shellcheck.net). 25 | - shellcheck shunit2 *_test.sh 26 | - shellcheck -s sh shunit2_test_helpers 27 | - os: linux 28 | # Support Ubuntu Trusty through Apr 2019. 29 | dist: trusty 30 | -------------------------------------------------------------------------------- /tests/shunit/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at kate.ward@forestent.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.0.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.0 2 | =============================== 3 | 4 | This release was branched from shUnit2 2.0.1. It mostly adds new functionality, 5 | but there are couple of bugs fixed from the previous release. 6 | 7 | See the ``CHANGES-2.1.rst`` file for a full list of changes. 8 | 9 | 10 | Tested Platforms 11 | ---------------- 12 | 13 | This list of platforms comes from the latest version of log4sh as shUnit2 is 14 | used in the testing of log4sh on each of these platforms. 15 | 16 | Cygwin 17 | 18 | - bash 3.2.9(10) 19 | - pdksh 5.2.14 20 | 21 | Linux 22 | 23 | - bash 3.1.17(1), 3.2.10(1) 24 | - dash 0.5.3 25 | - ksh 1993-12-28 26 | - pdksh 5.2.14 27 | - zsh 4.3.2 (does not work) 28 | 29 | Mac OS X 10.4.8 (Darwin 8.8) 30 | 31 | - bash 2.05b.0(1) 32 | - ksh 1993-12-28 33 | 34 | Solaris 8 U3 (x86) 35 | 36 | - /bin/sh 37 | - bash 2.03.0(1) 38 | - ksh M-11/16/88i 39 | 40 | Solaris 10 U2 (sparc) 41 | 42 | - /bin/sh 43 | - bash 3.00.16(1) 44 | - ksh M-11/16/88i 45 | 46 | Solaris 10 U2 (x86) 47 | 48 | - /bin/sh 49 | - bash 3.00.16(1) 50 | - ksh M-11/16/88i 51 | 52 | 53 | New Features 54 | ------------ 55 | 56 | Test skipping 57 | 58 | Support added for test "skipping". A skip mode can be enabled so that 59 | subsequent ``assert`` and ``fail`` functions that are called will be recorded 60 | as "skipped" rather than as "passed" or "failed". This functionality can be 61 | used such that when a set of tests makes sense on one platform but not on 62 | another, they can be effectively disabled without altering the total number 63 | of tests. 64 | 65 | One example might be when something is supported under ``bash``, but not 66 | under a standard Bourne shell. 67 | 68 | New functions: ``startSkipping()``, ``endSkipping``, ``isSkipping`` 69 | 70 | 71 | Changes and Enhancements 72 | ------------------------ 73 | 74 | Moving to the use of `reStructured Text 75 | `_ for documentation. It is easy to 76 | read and edit in textual form, but converts nicely to HTML. 77 | 78 | The report format has changed. Rather than including a simple "success" 79 | percentage at the end, a percentage is given for each type of test. 80 | 81 | 82 | Bug Fixes 83 | --------- 84 | 85 | The ``fail()`` function did not output the optional failure message. 86 | 87 | Fixed the ``Makefile`` so that the DocBook XML and XSLT files would be 88 | downloaded before documentation parsing will continue. 89 | 90 | 91 | Deprecated Features 92 | ------------------- 93 | 94 | None. 95 | 96 | 97 | Known Bugs and Issues 98 | --------------------- 99 | 100 | None. 101 | 102 | 103 | .. $Revision$ 104 | .. vim:fileencoding=latin1:spell:syntax=rst:textwidth=80 105 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.1.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.1 2 | =============================== 3 | 4 | This is mainly a bug fix release, but it also incorporates a realignment with 5 | the JUnit 4 code. Asserts now provide better failure messages, and the failure 6 | functions no longer perform tests. 7 | 8 | See the ``CHANGES-2.1.txt`` file for a full list of changes. 9 | 10 | 11 | Tested Platforms 12 | ---------------- 13 | 14 | This list of platforms comes from the latest version of log4sh as shUnit2 is 15 | used in the testing of log4sh on each of these platforms. 16 | 17 | Cygwin 18 | 19 | - bash 3.2.15(13) 20 | - pdksh 5.2.14 21 | 22 | Linux 23 | 24 | - bash 3.1.17(1), 3.2.10(1) 25 | - dash 0.5.3 26 | - ksh 1993-12-28 27 | - pdksh 5.2.14 28 | - zsh 4.3.2 (does not work) 29 | 30 | Mac OS X 10.4.9 (Darwin 8.9.1) 31 | 32 | - bash 2.05b.0(1) 33 | - ksh 1993-12-28 34 | 35 | Solaris 8 U3 (x86) 36 | 37 | - /bin/sh 38 | - bash 2.03.0(1) 39 | - ksh M-11/16/88i 40 | 41 | Solaris 10 U2 (sparc, x86) 42 | 43 | - /bin/sh 44 | - bash 3.00.16(1) 45 | - ksh M-11/16/88i 46 | 47 | 48 | New Features 49 | ------------ 50 | 51 | None. 52 | 53 | 54 | Changes and Enhancements 55 | ------------------------ 56 | 57 | The internal test in ``assertFalse()`` now accepts any non-zero value as false. 58 | 59 | The ``assertTrue()`` and ``assertFalse()`` functions now accept an integer value 60 | for a conditional test. A value of '0' is considered 'true', while any non-zero 61 | value is considered 'false'. 62 | 63 | Self-testing unit tests were added. 64 | 65 | 66 | Bug Fixes 67 | --------- 68 | 69 | The ``fail()`` assert now honors skipping. 70 | 71 | The ``docs-docbook-prep`` target now works properly. 72 | 73 | All asserts now properly unset their variables. 74 | 75 | 76 | Deprecated Features 77 | ------------------- 78 | 79 | None. 80 | 81 | 82 | Known Bugs and Issues 83 | --------------------- 84 | 85 | Functions do not properly test for an invalid number of arguments. 86 | 87 | 88 | .. vim:fileencoding=latin1:ft=rst:spell:textwidth=80 89 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.2.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.2 2 | =============================== 3 | 4 | This release adds initial support for the zsh shell. Due to some differences 5 | with this shell as compared with others, some special checks have been added, 6 | and there are some extra requirements necessary when this shell is to be used. 7 | 8 | To use zsh with shUnit2, the following two requirements must be met: 9 | * The ``shwordsplit`` option must be set. 10 | * The ``function_argzero`` option must be unset. 11 | 12 | Please read the Shell Errata section of the documentation for guidance on how 13 | to meet these requirements. 14 | 15 | 16 | See the ``CHANGES-2.1.txt`` file for a full list of changes. 17 | 18 | 19 | Tested Platforms 20 | ---------------- 21 | 22 | This list of platforms comes from the latest version of log4sh as shUnit2 is 23 | used in the testing of log4sh on each of these platforms. 24 | 25 | Linux 26 | 27 | - bash 3.1.17(1), 3.2.25(1) 28 | - dash 0.5.4 29 | - ksh 1993-12-28 30 | - pdksh 5.2.14 31 | - zsh 4.2.5, 4.3.4 32 | 33 | Mac OS X 10.4.11 (Darwin 8.11.1) 34 | 35 | - bash 2.05b.0(1) 36 | - ksh 1993-12-28 37 | - zsh 4.2.3 38 | 39 | Solaris 10 U3 (x86) 40 | 41 | - /bin/sh 42 | - bash 3.00.16(1) 43 | - ksh M-11/16/88i 44 | - zsh 4.2.1 45 | 46 | 47 | New Features 48 | ------------ 49 | 50 | Support for the zsh shell. 51 | 52 | 53 | Changes and Enhancements 54 | ------------------------ 55 | 56 | Added some argument count checks. 57 | 58 | 59 | Bug Fixes 60 | --------- 61 | 62 | None. 63 | 64 | 65 | Deprecated Features 66 | ------------------- 67 | 68 | None. 69 | 70 | 71 | Known Bugs and Issues 72 | --------------------- 73 | 74 | Functions do not properly test for an invalid number of arguments. 75 | 76 | ksh and pdksh do not pass null arguments (i.e. empty strings as '') properly, 77 | and as such checks do not work properly. 78 | 79 | zsh requires the ``shwordsplit`` option to be set, and the ``function_argzero`` 80 | option to be unset for proper operation. 81 | 82 | 83 | .. vim:fileencoding=latin1:ft=rst:spell:textwidth=80 84 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.3.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.3 2 | =============================== 3 | 4 | This release is minor feature release. It improves support for zsh (although it 5 | still isn't what it could be) and adds automated testing framework support by 6 | returning a non-zero exit when tests fail. 7 | 8 | To use zsh with shUnit2, the following two requirements must be met: 9 | * The ``shwordsplit`` option must be set. 10 | * The ``function_argzero`` option must be unset. 11 | 12 | Please read the Shell Errata section of the documentation for guidance on how 13 | to meet these requirements. 14 | 15 | See the ``CHANGES-2.1.txt`` file for a full list of changes. 16 | 17 | 18 | Tested Platforms 19 | ---------------- 20 | 21 | Cygwin 22 | 23 | - bash 3.2.33(18) 24 | - pdksh 5.2.14 25 | 26 | Linux 27 | 28 | - bash 3.2.33(1) 29 | - dash 0.5.4 30 | - ksh 1993-12-28 31 | - pdksh 5.2.14 32 | - zsh 4.3.4 33 | 34 | Mac OS X 10.5.2 (Darwin 9.2.2) 35 | 36 | - bash 3.2.17(1) 37 | - ksh 1993-12-28 38 | - zsh 4.3.4 39 | 40 | Solaris 11 x86 (Nevada 77) 41 | 42 | - /bin/sh 43 | - bash 3.2.25(1) 44 | - ksh M-11/16/88i 45 | - zsh 4.3.4 46 | 47 | 48 | New Features 49 | ------------ 50 | 51 | None. 52 | 53 | 54 | Changes and Enhancements 55 | ------------------------ 56 | 57 | Support for automated testing frameworks. 58 | 59 | 60 | Bug Fixes 61 | --------- 62 | 63 | Fixed some issues with zsh support. 64 | 65 | 66 | Deprecated Features 67 | ------------------- 68 | 69 | None. 70 | 71 | 72 | Known Bugs and Issues 73 | --------------------- 74 | 75 | Functions do not properly test for an invalid number of arguments. 76 | 77 | ksh and pdksh do not pass null arguments (i.e. empty strings as '') properly, 78 | and as such checks do not work properly. 79 | 80 | zsh requires the ``shwordsplit`` option to be set, and the ``function_argzero`` 81 | option to be unset for proper operation. 82 | 83 | 84 | .. vim:fileencoding=latin1:ft=rst:spell:textwidth=80 85 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.4.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.4 2 | =============================== 3 | 4 | This release contains lots of bug fixes and changes. Mostly, it fixes zsh 5 | support in zsh 3.0, and the handling of null values in ksh. 6 | 7 | To use zsh with shUnit2, the following requirement must be met: 8 | 9 | - The ``shwordsplit`` option must be set. 10 | 11 | Please read the Shell Errata section of the documentation for guidance on how 12 | to meet these requirements. 13 | 14 | See the ``CHANGES-2.1.txt`` file for a full list of changes. 15 | 16 | 17 | Tested Platforms 18 | ---------------- 19 | 20 | Cygwin 21 | 22 | - bash 3.2.39(19) 23 | - pdksh 5.2.14 24 | - zsh 4.3.4 25 | 26 | Linux (Ubuntu Dapper 6.06) 27 | 28 | - bash 3.1.17(1) 29 | - pdksh 5.2.14 30 | - zsh 4.2.5 31 | 32 | Linux (Ubuntu Hardy 8.04) 33 | 34 | - bash 3.2.39(1) 35 | - dash 0.5.4 36 | - ksh 1993-12-28 37 | - pdksh 5.2.14 38 | - zsh 4.3.4 39 | 40 | Mac OS X 10.5.4 (Darwin 9.4.0) 41 | 42 | - bash 3.2.17(1) 43 | - ksh 1993-12-28 44 | - zsh 4.3.4 45 | 46 | Solaris 9 U6 x86 47 | 48 | - /bin/sh 49 | - bash 2.05.0(1) 50 | - ksh M-11/16/88i 51 | - zsh 3.0.8 52 | 53 | Solaris 11 x86 (Nevada 77) 54 | 55 | - /bin/sh 56 | - bash 3.2.25(1) 57 | - ksh M-11/16/88i 58 | - zsh 4.3.4 59 | 60 | 61 | New Features 62 | ------------ 63 | 64 | Support added to output assert source line number as part of assert messages. 65 | 66 | 67 | Changes and Enhancements 68 | ------------------------ 69 | 70 | Support for automated testing frameworks. 71 | 72 | Added argument count error checking to all functions. 73 | 74 | 75 | Bug Fixes 76 | --------- 77 | 78 | Fixed some issues with ksh and zsh support. 79 | 80 | Fixed off-by-one of exit value in trap handler. 81 | 82 | Fixed handling of null values under ksh. 83 | 84 | Fixed bug in last resort temporary directory creation. 85 | 86 | 87 | Deprecated Features 88 | ------------------- 89 | 90 | None. 91 | 92 | 93 | Known Bugs and Issues 94 | --------------------- 95 | 96 | zsh requires the ``shwordsplit`` option to be set. 97 | 98 | Line numbers in assert messages do not work properly with Bash 2.x. 99 | 100 | .. vim:fileencoding=latin1:ft=rst:spell:tw=80 101 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.5.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.5 2 | =============================== 3 | 4 | This release contains several bug fixes and changes. Additionally, it includes 5 | a rewrite of the test output to better match JUnit and PyUnit. 6 | 7 | This version also includes a slightly expanded set of coding standards by which 8 | shUnit2 is coded. It should help anyone reading the code to better understand 9 | it. 10 | 11 | 12 | 13 | Please read the Shell Errata section of the documentation for guidance on how 14 | to meet these requirements. 15 | 16 | See the ``CHANGES-2.1.txt`` file for a full list of changes. 17 | 18 | 19 | Tested Platforms 20 | ---------------- 21 | 22 | Cygwin 23 | 24 | - bash 3.2.39(20) 25 | - ksh (sym-link to pdksh) 26 | - pdksh 5.2.14 27 | - zsh 4.3.4 28 | 29 | Linux (Ubuntu Dapper 6.06) 30 | 31 | - bash 3.1.17(1) 32 | - ksh M-1993-12-28 33 | - pdksh 5.2.14-99/07/13.2 34 | - zsh 4.2.5 35 | 36 | Linux (Ubuntu Hardy 8.04) 37 | 38 | - bash 3.2.39(1) 39 | - dash 0.5.4 40 | - ksh M-1993-12-28 41 | - pdksh 5.2.14-99/07/13.2 42 | - zsh 4.3.4 43 | 44 | Mac OS X 10.5.4 (Darwin 9.4.0) 45 | 46 | - bash 3.2.17(1) 47 | - ksh M-1993-12-28 48 | - zsh 4.3.4 49 | 50 | Solaris 9 U6 x86 51 | 52 | - /bin/sh 53 | - bash 2.05.0(1) 54 | - ksh M-11/16/88i 55 | - zsh 3.0.8 56 | 57 | Solaris 11 x86 (Nevada 77) 58 | 59 | - /bin/sh 60 | - bash 3.2.25(1) 61 | - ksh M-11/16/88i 62 | - zsh 4.3.4 63 | 64 | 65 | New Features 66 | ------------ 67 | 68 | Support added for output assert source line number as part of assert messages. 69 | 70 | Issue #2: Added assertNotEquals() assert. 71 | 72 | Provided a public ``shunit_tmpDir`` variable that can be used by unit test 73 | scripts that need automated and guaranteed cleanup. 74 | 75 | 76 | Changes and Enhancements 77 | ------------------------ 78 | 79 | Issue #3: Removed the check for unset variables as shUnit2 should not expect 80 | scripts being tested to be clean. 81 | 82 | Issue #4: Rewrote the test summary. It is now greatly simplified and much more 83 | script friendly. 84 | 85 | Issue #5: Fixed the documentation around the usage of failures. 86 | 87 | Issue #9: Added unit tests and improved documentation around the use of macros. 88 | 89 | Code updated to meet documented coding standards. 90 | 91 | Improved code reuse of ``_shunit_exit()`` and ``_shunit_fatal()`` functions. 92 | 93 | All output except shUnit2 error messages now goes to STDOUT. 94 | 95 | Converted DocBook documentation to reStructuredText for easier maintenance. 96 | 97 | 98 | Bug Fixes 99 | --------- 100 | 101 | Issue #1: Fixed bug in rap code where certain types of exit conditions did not 102 | generate the ending report. 103 | 104 | Issue #7: Fixed duplicated printing of messages passed to asserts. 105 | 106 | Fixed bugs in ``shlib_relToAbsPath()`` in ``shlib``. 107 | 108 | 109 | Deprecated Features 110 | ------------------- 111 | 112 | None. 113 | 114 | 115 | Known Bugs and Issues 116 | --------------------- 117 | 118 | Zsh requires the ``shwordsplit`` option to be set. See the documentation for 119 | examples of how to do this. 120 | 121 | Line numbers in assert messages do not work properly with BASH 2.x. 122 | 123 | The Bourne shell of Solaris, BASH 2.x, and Zsh 3.0.x do not properly catch the 124 | SIGTERM signal. As such, shell interpreter failures due to such things as 125 | unbound variables cannot be caught. (See ``shunit_test_misc.sh``) 126 | 127 | 128 | .. vim:fileencoding=latin1:ft=rst:spell:tw=80 129 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.6.txt: -------------------------------------------------------------------------------- 1 | Release Notes for shUnit2 2.1.6 2 | =============================== 3 | 4 | This release contains bug fixes and changes. It is also the first release to 5 | support running shunit2 as a standalone program. 6 | 7 | Please read the Shell Errata section of the documentation for guidance on how 8 | to meet these requirements. 9 | 10 | See the ``CHANGES-2.1.txt`` file for a full list of changes. 11 | 12 | New Features 13 | ------------ 14 | 15 | Support for running shUnit2 as a standalone program. This makes it possible for 16 | users to execute their unit tests in a manner that is not dependent on the 17 | location an OS distribution maintainer chose to place shUnit2 in the file 18 | system. 19 | 20 | Added support for functions defined like 'function someFunction()'. 21 | 22 | Changes and Enhancements 23 | ------------------------ 24 | 25 | Renamed the public ``shunit_tmpDir`` variable to ``SHUNIT_TMPDIR`` to be more 26 | consistent with the ``TMPDIR`` variable. 27 | 28 | Bug Fixes 29 | --------- 30 | 31 | Fixed issue where shunit2 would fail on some distributions when creating a 32 | temporary directory because the **od** command was not present. 33 | 34 | Deprecated Features 35 | ------------------- 36 | 37 | None. 38 | 39 | Known Bugs and Issues 40 | --------------------- 41 | 42 | Zsh requires the ``shwordsplit`` option to be set. See the documentation for 43 | examples of how to do this. 44 | 45 | Line numbers in assert messages do not work properly with BASH 2.x. 46 | 47 | The Bourne shell of Solaris, BASH 2.x, and Zsh 3.0.x do not properly catch the 48 | SIGTERM signal. As such, shell interpreter failures due to such things as 49 | unbound variables cannot be caught. (See ``shunit_test_misc.sh``) 50 | 51 | Tested Platforms 52 | ---------------- 53 | 54 | Cygwin 1.7.9 (Windows XP SP2) 55 | 56 | - bash 4.1.10(4) 57 | - dash 0.5.6.1 58 | - ksh (sym-link to pdksh) 59 | - pdksh 5.2.14 60 | - zsh 4.3.11 61 | 62 | Linux (Ubuntu Dapper 6.06.2 LTS) 63 | 64 | - bash 3.1.17(1) 65 | - dash 0.5.3 66 | - ksh (sym-link to pdksh) 67 | - pdksh 5.2.14-99/07/13.2 68 | - zsh 4.2.5 69 | 70 | Linux (Ubuntu Hardy 8.04.4 LTS) 71 | 72 | - bash 3.2.39(1) 73 | - dash 0.5.4 74 | - ksh M-1993-12-28 75 | - pdksh 5.2.14-99/07/13.2 76 | - zsh 4.3.4 77 | 78 | Linux (Ubuntu Lucid 10.04.2 LTS) 79 | 80 | - bash 4.1.5(1) 81 | - dash 0.5.5.1 82 | - ksh JM-93t+-2009-05-01 83 | - pdksh 5.2.14-99/07/13.2 84 | - zsh 4.3.10 85 | 86 | Mac OS X 10.6.7 87 | 88 | - bash 3.2.48(1) 89 | - ksh M-1993-12-28 90 | - zsh 4.3.9 91 | 92 | Solaris 8 U7 x86 93 | 94 | - /bin/sh 95 | - bash 2.03.0(1) 96 | - ksh M-11/16/88i 97 | - zsh 3.0.6 98 | 99 | Solaris 9 U6 x86 100 | 101 | - /bin/sh 102 | - bash 2.05.0(1) 103 | - ksh M-11/16/88i 104 | - zsh 3.0.8 105 | 106 | OpenSolaris 2009.06(snv_111b) x86 107 | 108 | - /bin/sh 109 | - bash 3.2.25(1) 110 | - ksh 2008-11-04 111 | 112 | .. vim:fileencoding=latin1:ft=rst:spell:tw=80 113 | -------------------------------------------------------------------------------- /tests/shunit/doc/RELEASE_NOTES-2.1.7.md: -------------------------------------------------------------------------------- 1 | # shUnit2 2.1.7 Release Notes 2 | 3 | https://github.com/kward/shunit2 4 | 5 | This release contains bug fixes and enhancements. It is the first release since moving to GitHub. Users can now clone the latest version at any time. 6 | 7 | See the `CHANGES-2.1.md` file for a full list of changes. 8 | 9 | 10 | ## New Features 11 | 12 | Colorized output, based on popular demand. shUnit2 output is now colorized based on the result of the asserts. 13 | 14 | 15 | ## Changes and Enhancements 16 | 17 | With the move to GitHub, the shUnit2 unit tests are run on every commit using the [Travis CI][TravisCI] continuous integration framework. Additionally, all code is run through [ShellCheck](http:/www.shellcheck.net/) on every commit. 18 | 19 | [TravisCI]: https://travis-ci.org/kward/shunit2 20 | 21 | Shell commands in shUnit2 are prefixed with '\' so that they can be stubbed in tests. 22 | 23 | 24 | ## Bug Fixes 25 | 26 | shUnit2 no longer exits with an 'OK' result if there were syntax errors due to incorrect usage of the assert commands. 27 | 28 | 29 | ## Deprecated Features 30 | 31 | None. 32 | 33 | 34 | ## Known Bugs and Issues 35 | 36 | Zsh requires the `shwordsplit` option to be set. See the documentation for examples of how to do this. 37 | 38 | Line numbers in assert messages do not work properly with BASH 2.x. 39 | 40 | The Bourne shell of Solaris, BASH 2.x, and Zsh 3.0.x do not properly catch the 41 | SIGTERM signal. As such, shell interpreter failures due to such things as 42 | unbound variables cannot be caught. (See `shunit_test_misc.sh`) 43 | 44 | 45 | ## Tested Platforms 46 | 47 | Continuous integration testing is provided by [Travis CI][TravisCI]. 48 | 49 | Tested OSes: 50 | 51 | - Linux 52 | - macOS 53 | 54 | Tested shells: 55 | 56 | - /bin/sh 57 | - ash 58 | - bash 59 | - dash 60 | - ksh 61 | - pdksh 62 | - zsh 63 | -------------------------------------------------------------------------------- /tests/shunit/doc/TODO.txt: -------------------------------------------------------------------------------- 1 | Make it possible to execute a single test by passing the name of the test on 2 | the command line 3 | 4 | Add support for '--randomize-order' so that the test order is randomized to 5 | check for dependencies (which shouldn't be there) between tests. 6 | 7 | --debug option to display point in source code (line number and such) where the 8 | problem showed up. 9 | 10 | assertTrue() just gives 'ASSERT:', nothing else :-(. others too? 11 | upd: assertNull() will give message passed, but nothing else useful :-( 12 | 13 | $Revision$ 14 | -------------------------------------------------------------------------------- /tests/shunit/doc/contributors.md: -------------------------------------------------------------------------------- 1 | The original author of shunit2 is Kate Ward. The following people have 2 | contributed in some way or another to shunit2. 3 | 4 | - [Alex Harvey](https://github.com/alexharv074) 5 | - Bryan Larsen 6 | - [David Acacio](https://github.com/dacacioa) 7 | - Kevin Van Horn 8 | - [Maciej Bliziński](https://github.com/automatthias) 9 | - Mario Sparada 10 | - Mathias Goldau 11 | - Richard Jensen 12 | - Rob Holland 13 | - Rocky Bernstein 14 | - [rugk](https://github.com/rugk) 15 | - wood4321 (of code.google.com) 16 | -------------------------------------------------------------------------------- /tests/shunit/doc/design_doc.txt: -------------------------------------------------------------------------------- 1 | Design Doc for shUnit 2 | 3 | shUnit is based upon JUnit. The initial ideas for the script came from the book 4 | "Pragmatic Unit Testing - In Java with JUnit" by Andrew Hunt and David Thomas. 5 | 6 | The script was written to perform unit testing for log4sh. log4sh had grown 7 | enough that it was becoming difficult to easily test and and verify that the 8 | tests passed for the many different operating systems on which it was being 9 | used. 10 | 11 | The functions in shUnit are meant to match those in JUnit as much as possible 12 | where shell allows. In the initial version, there will be no concept of 13 | exceptions (as normal POSIX shell has no concept of them) but attempts to trap 14 | problems will be done. 15 | 16 | Programatic Standards: 17 | 18 | * SHUNIT_TRUE - public global constant 19 | * __SHUNIT_SHELL_FLAGS - private global constant 20 | * __shunit_oldShellFlags - private global variable 21 | 22 | * assertEquals - public unit test function 23 | * shunit_publicFunc - public shUnit function; can be called from parent unit 24 | test script 25 | * _shunit_privateFunc - private shUnit function; should not be called from 26 | parent script. meant for internal use by shUnit 27 | 28 | * _su_myVar - variable inside a public function. prefixing with '_su_' to 29 | reduce the chances that a variable outside of shUnit will be overridden. 30 | * _su__myVar - variable inside a private function. prefixing with '_su__' to 31 | reduce the chances that a variable in a shUnit public function, or a variable 32 | outside of shUnit will be overridden. 33 | 34 | $Revision$ 35 | -------------------------------------------------------------------------------- /tests/shunit/examples/equality_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # file: examples/equality_test.sh 3 | 4 | testEquality() { 5 | assertEquals 1 1 6 | } 7 | 8 | # Load and run shUnit2. 9 | . ../shunit2 10 | -------------------------------------------------------------------------------- /tests/shunit/examples/lineno_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # file: examples/lineno_test.sh 3 | 4 | testLineNo() { 5 | # This assert will have line numbers included (e.g. "ASSERT:[123] ...") if 6 | # they are supported. 7 | echo "_ASSERT_EQUALS_ macro value: ${_ASSERT_EQUALS_}" 8 | ${_ASSERT_EQUALS_} '"not equal"' 1 2 9 | 10 | # This assert will not have line numbers included (e.g. "ASSERT: ..."). 11 | assertEquals 'not equal' 1 2 12 | } 13 | 14 | # Load and run shUnit2. 15 | . ../shunit2 16 | -------------------------------------------------------------------------------- /tests/shunit/examples/math.inc: -------------------------------------------------------------------------------- 1 | # available as examples/math.inc 2 | 3 | add_generic() 4 | { 5 | num_a=$1 6 | num_b=$2 7 | 8 | expr $1 + $2 9 | } 10 | 11 | add_bash() 12 | { 13 | num_a=$1 14 | num_b=$2 15 | 16 | echo $(($1 + $2)) 17 | } 18 | -------------------------------------------------------------------------------- /tests/shunit/examples/math_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # file: examples/math_test.sh 3 | 4 | testAdding() { 5 | result=`add_generic 1 2` 6 | assertEquals \ 7 | "the result of '${result}' was wrong" \ 8 | 3 "${result}" 9 | 10 | # Disable non-generic tests. 11 | [ -z "${BASH_VERSION:-}" ] && startSkipping 12 | 13 | result=`add_bash 1 2` 14 | assertEquals \ 15 | "the result of '${result}' was wrong" \ 16 | 3 "${result}" 17 | } 18 | 19 | oneTimeSetUp() { 20 | # Load include to test. 21 | . ./math.inc 22 | } 23 | 24 | # Load and run shUnit2. 25 | . ../shunit2 26 | -------------------------------------------------------------------------------- /tests/shunit/examples/mkdir_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # Copyright 2008-2019 Kate Ward. All Rights Reserved. 5 | # Released under the Apache 2.0 license. 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # shUnit2 -- Unit testing framework for Unix shell scripts. 9 | # https://github.com/kward/shunit2 10 | # 11 | # Author: kate.ward@forestent.com (Kate Ward) 12 | # 13 | # Example unit test for the mkdir command. 14 | # 15 | # There are times when an existing shell script needs to be tested. In this 16 | # example, we will test several aspects of the the mkdir command, but the 17 | # techniques could be used for any existing shell script. 18 | 19 | testMissingDirectoryCreation() { 20 | ${mkdirCmd} "${testDir}" >${stdoutF} 2>${stderrF} 21 | rtrn=$? 22 | th_assertTrueWithNoOutput ${rtrn} "${stdoutF}" "${stderrF}" 23 | 24 | assertTrue 'directory missing' "[ -d '${testDir}' ]" 25 | } 26 | 27 | testExistingDirectoryCreationFails() { 28 | # Create a directory to test against. 29 | ${mkdirCmd} "${testDir}" 30 | 31 | # Test for expected failure while trying to create directory that exists. 32 | ${mkdirCmd} "${testDir}" >${stdoutF} 2>${stderrF} 33 | rtrn=$? 34 | assertFalse 'expecting return code of 1 (false)' ${rtrn} 35 | assertNull 'unexpected output to stdout' "`cat ${stdoutF}`" 36 | assertNotNull 'expected error message to stderr' "`cat ${stderrF}`" 37 | 38 | assertTrue 'directory missing' "[ -d '${testDir}' ]" 39 | } 40 | 41 | testRecursiveDirectoryCreation() { 42 | testDir2="${testDir}/test2" 43 | 44 | ${mkdirCmd} -p "${testDir2}" >${stdoutF} 2>${stderrF} 45 | rtrn=$? 46 | th_assertTrueWithNoOutput ${rtrn} "${stdoutF}" "${stderrF}" 47 | 48 | assertTrue 'first directory missing' "[ -d '${testDir}' ]" 49 | assertTrue 'second directory missing' "[ -d '${testDir2}' ]" 50 | } 51 | 52 | th_assertTrueWithNoOutput() { 53 | th_return_=$1 54 | th_stdout_=$2 55 | th_stderr_=$3 56 | 57 | assertFalse 'unexpected output to STDOUT' "[ -s '${th_stdout_}' ]" 58 | assertFalse 'unexpected output to STDERR' "[ -s '${th_stderr_}' ]" 59 | 60 | unset th_return_ th_stdout_ th_stderr_ 61 | } 62 | 63 | oneTimeSetUp() { 64 | outputDir="${SHUNIT_TMPDIR}/output" 65 | mkdir "${outputDir}" 66 | stdoutF="${outputDir}/stdout" 67 | stderrF="${outputDir}/stderr" 68 | 69 | mkdirCmd='mkdir' # save command name in variable to make future changes easy 70 | testDir="${SHUNIT_TMPDIR}/some_test_dir" 71 | } 72 | 73 | tearDown() { 74 | rm -fr "${testDir}" 75 | } 76 | 77 | # Load and run shUnit2. 78 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 79 | . ../shunit2 80 | -------------------------------------------------------------------------------- /tests/shunit/examples/mock_file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # shUnit2 example for mocking files. 4 | # 5 | # This example demonstrates two different mechanisms for mocking files on the 6 | # system. The first method is preferred for testing specific aspects of a file, 7 | # and the second method is preferred when multiple tests need access to the 8 | # same mock data. 9 | # 10 | # When mocking files, the key thing of importance is providing the code under 11 | # test with the correct file to read. The best practice for writing code where 12 | # files need to be mocked is either: 13 | # - Pass the filename to be tested into a function and test that function, or 14 | # - Provide a function that returns the name of the filename to be read. 15 | # 16 | # The first case is preferred whenever possible as it allows the unit test to 17 | # be explicit about what is being tested. The second case is useful when the 18 | # first case is not achievable. 19 | # 20 | # For the second case, there are two common methods to mock the filename 21 | # returned by the function: 22 | # - Provide a special value (e.g. a mock variable) that is only available 23 | # during testing, or 24 | # - Override something (e.g. the constant) in the test script. 25 | # 26 | # The first case is preferred as it doesn't require the unit test to alter code 27 | # in any way. Yes, it means that the code itself knows that it is under test, 28 | # and it behaves slightly differently than under normal conditions, but a 29 | # visual inspection of the code by the developer should be sufficient to 30 | # validate proper functionality of such a simple function. 31 | 32 | # Treat unset variables as an error. 33 | set -u 34 | 35 | PASSWD='/etc/passwd' 36 | 37 | # Read the root UID from the passwd filename provided as the first argument. 38 | root_uid_from_passed_filename() { 39 | filename=$1 40 | root_uid "${filename}" 41 | unset filename 42 | } 43 | 44 | 45 | # Read the root UID from the passwd filename derived by call to the 46 | # passwd_filename() function. 47 | root_uid_from_derived_filename() { 48 | root_uid "$(passwd_filename)" 49 | } 50 | 51 | passwd_filename() { 52 | if [ -n "${MOCK_PASSWD:-}" ]; then 53 | echo "${MOCK_PASSWD}" # Mock file for testing. 54 | return 55 | fi 56 | echo "${PASSWD}" 57 | } 58 | 59 | 60 | # Extract the root UID. 61 | root_uid() { awk -F: 'u==$1{print $3}' u=root "$1"; } 62 | 63 | 64 | main() { 65 | echo "root_uid_from_passed_filename:" 66 | root_uid_from_passed_filename "${PASSWD}" 67 | 68 | echo 69 | 70 | echo "root_uid_from_derived_filename:" 71 | root_uid_from_derived_filename 72 | } 73 | 74 | 75 | # Execute main() if this is run in standalone mode (i.e. not in a unit test). 76 | ARGV0="$(basename "$0")" 77 | argv0="$(echo "${ARGV0}" |sed 's/_test$//;s/_test\.sh$//')" 78 | if [ "${ARGV0}" = "${argv0}" ]; then 79 | main "$@" 80 | fi 81 | -------------------------------------------------------------------------------- /tests/shunit/examples/mock_file_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # shUnit2 example for mocking files. 4 | 5 | MOCK_PASSWD='' # This will be overridden in oneTimeSetUp(). 6 | 7 | test_root_uid_from_passed_filename() { 8 | result="$(root_uid_from_passed_filename "${MOCK_PASSWD}")" 9 | assertEquals 'unexpected root uid' '0' "${result}" 10 | } 11 | 12 | test_root_uid_from_derived_filename() { 13 | result="$(root_uid_from_derived_filename)" 14 | assertEquals 'unexpected root uid' '0' "${result}" 15 | } 16 | 17 | oneTimeSetUp() { 18 | # Provide a mock passwd file for testing. This will be cleaned up 19 | # automatically by shUnit2. 20 | MOCK_PASSWD="${SHUNIT_TMPDIR}/passwd" 21 | cat <"${MOCK_PASSWD}" 22 | nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false 23 | root:*:0:0:System Administrator:/var/root:/bin/sh 24 | daemon:*:1:1:System Services:/var/root:/usr/bin/false 25 | EOF 26 | 27 | # Load script under test. 28 | . './mock_file.sh' 29 | } 30 | 31 | # Load and run shUnit2. 32 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 33 | . ../shunit2 34 | -------------------------------------------------------------------------------- /tests/shunit/examples/party_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # file: examples/party_test.sh 3 | # 4 | # This test is mostly for fun. Technically, it is a bad example of a unit test 5 | # because of the temporal requirement, namely that the year be 1999. A better 6 | # test would have been to pass in both a known-bad and known-good year into a 7 | # function, and test for the expected result. 8 | 9 | testPartyLikeItIs1999() { 10 | year=`date '+%Y'` 11 | assertEquals "It's not 1999 :-(" \ 12 | '1999' "${year}" 13 | } 14 | 15 | # Load and run shUnit2. 16 | . ../shunit2 17 | -------------------------------------------------------------------------------- /tests/shunit/examples/suite_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # file: examples/suite_test.sh 3 | # 4 | # This test demonstrates the use of suites. Note: the suite functionality is 5 | # deprecated as of v2.1.0, and will be removed in a future major release. 6 | 7 | # suite is a special function called by shUnit2 to setup a suite of tests. It 8 | # enables a developer to call a set of functions that contain tests without 9 | # needing to rename the functions to start with "test". 10 | # 11 | # Tests that are to be called from within `suite()` are added to the list of 12 | # executable tests by means of the `suite_addTest()` function. 13 | suite() { 14 | # Add the suite_test_one() function to the list of executable tests. 15 | suite_addTest suite_test_one 16 | 17 | # Call the suite_test_two() function, but note that the test results will not 18 | # be added to the global stats, and therefore not reported at the end of the 19 | # unit test execution. 20 | suite_test_two 21 | } 22 | 23 | suite_test_one() { 24 | assertEquals 1 1 25 | } 26 | 27 | suite_test_two() { 28 | assertNotEquals 1 2 29 | } 30 | 31 | # Load and run shUnit2. 32 | . ../shunit2 33 | -------------------------------------------------------------------------------- /tests/shunit/shunit2_args_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # shunit2 unit test for running subset(s) of tests based upon command line arguments. 4 | # Also shows how non-default tests or a arbitrary subset of tests can be run. 5 | # 6 | # Disable source following. 7 | # shellcheck disable=SC1090,SC1091 8 | 9 | # Load test helpers. 10 | . ./shunit2_test_helpers 11 | 12 | # This test does not nomrally run because it does not begin "test*" 13 | # Will be run by settting the arguments to the script to include the name of this test. 14 | non_default_test() { 15 | # arbitrary assert 16 | assertTrue 0 17 | # true intent is to set this variable, which will be tested below 18 | NON_DEFAULT_TEST_RAN="yup, we ran" 19 | } 20 | 21 | # Test that the "non_default_test" ran, otherwise fail 22 | test_non_default_ran() { 23 | assertNotNull "'non_default_test' did not run" "$NON_DEFAULT_TEST_RAN" 24 | } 25 | 26 | # fail if this test runs, which is shouldn't if args are set correctly. 27 | test_will_fail() { 28 | fail "test_will_fail should not be run if arg-parsing works" 29 | } 30 | 31 | oneTimeSetUp() { 32 | th_oneTimeSetUp 33 | # prime with "null" value 34 | NON_DEFAULT_TEST_RAN="" 35 | } 36 | 37 | # Load and run shunit2. 38 | # shellcheck disable=SC2034 39 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 40 | 41 | # If zero/one argument(s) are provided, this test is being run in it's 42 | # entirety, and therefore we want to set the arguments to the script 43 | # to (simulate and) test the processing of command-line specified 44 | # tests. If we don't, then the "test_will_fail" test will run (by 45 | # default) and the overall test will fail. 46 | # 47 | # However, if two or more arguments are provided, then assume this 48 | # test script is being run by hand to experiment with command-line 49 | # test specification, and then don't override the user provided 50 | # arguments. 51 | if command [ "$#" -le 1 ]; then 52 | # We set the arguments in a POSIX way, inasmuch as we can; 53 | # helpful tip: 54 | # https://unix.stackexchange.com/questions/258512/how-to-remove-a-positional-parameter-from 55 | set -- "--" "non_default_test" "test_non_default_ran" 56 | fi 57 | 58 | # Load and run tests, but only if running as a script, not if being sourced by shunit2 59 | command [ -z "${SHUNIT_VERSION:-}" ] && . "${TH_SHUNIT}" 60 | -------------------------------------------------------------------------------- /tests/shunit/shunit2_failures_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # Copyright 2008-2019 Kate Ward. All Rights Reserved. 5 | # Released under the Apache 2.0 license. 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # shUnit2 -- Unit testing framework for Unix shell scripts. 9 | # https://github.com/kward/shunit2 10 | # 11 | # Author: kate.ward@forestent.com (Kate Ward) 12 | # 13 | # shUnit2 unit test for failure functions 14 | # 15 | # Disable source following. 16 | # shellcheck disable=SC1090,SC1091 17 | 18 | # These variables will be overridden by the test helpers. 19 | stdoutF="${TMPDIR:-/tmp}/STDOUT" 20 | stderrF="${TMPDIR:-/tmp}/STDERR" 21 | 22 | # Load test helpers. 23 | . ./shunit2_test_helpers 24 | 25 | testFail() { 26 | ( fail >"${stdoutF}" 2>"${stderrF}" ) 27 | th_assertFalseWithOutput 'fail' $? "${stdoutF}" "${stderrF}" 28 | 29 | ( fail "${MSG}" >"${stdoutF}" 2>"${stderrF}" ) 30 | th_assertFalseWithOutput 'fail with msg' $? "${stdoutF}" "${stderrF}" 31 | 32 | ( fail arg1 >"${stdoutF}" 2>"${stderrF}" ) 33 | th_assertFalseWithOutput 'too many arguments' $? "${stdoutF}" "${stderrF}" 34 | } 35 | 36 | testFailNotEquals() { 37 | ( failNotEquals 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 38 | th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}" 39 | 40 | ( failNotEquals "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 41 | th_assertFalseWithOutput 'same with msg' $? "${stdoutF}" "${stderrF}" 42 | 43 | ( failNotEquals 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 44 | th_assertFalseWithOutput 'not same' $? "${stdoutF}" "${stderrF}" 45 | 46 | ( failNotEquals '' '' >"${stdoutF}" 2>"${stderrF}" ) 47 | th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}" 48 | 49 | ( failNotEquals >"${stdoutF}" 2>"${stderrF}" ) 50 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 51 | 52 | ( failNotEquals arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" ) 53 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 54 | } 55 | 56 | testFailSame() { 57 | ( failSame 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 58 | th_assertFalseWithOutput 'same' $? "${stdoutF}" "${stderrF}" 59 | 60 | ( failSame "${MSG}" 'x' 'x' >"${stdoutF}" 2>"${stderrF}" ) 61 | th_assertFalseWithOutput 'same with msg' $? "${stdoutF}" "${stderrF}" 62 | 63 | ( failSame 'x' 'y' >"${stdoutF}" 2>"${stderrF}" ) 64 | th_assertFalseWithOutput 'not same' $? "${stdoutF}" "${stderrF}" 65 | 66 | ( failSame '' '' >"${stdoutF}" 2>"${stderrF}" ) 67 | th_assertFalseWithOutput 'null values' $? "${stdoutF}" "${stderrF}" 68 | 69 | ( failSame >"${stdoutF}" 2>"${stderrF}" ) 70 | th_assertFalseWithError 'too few arguments' $? "${stdoutF}" "${stderrF}" 71 | 72 | ( failSame arg1 arg2 arg3 arg4 >"${stdoutF}" 2>"${stderrF}" ) 73 | th_assertFalseWithError 'too many arguments' $? "${stdoutF}" "${stderrF}" 74 | } 75 | 76 | oneTimeSetUp() { 77 | th_oneTimeSetUp 78 | 79 | MSG='This is a test message' 80 | } 81 | 82 | # Load and run shUnit2. 83 | # shellcheck disable=SC2034 84 | [ -n "${ZSH_VERSION:-}" ] && SHUNIT_PARENT=$0 85 | . "${TH_SHUNIT}" 86 | -------------------------------------------------------------------------------- /tests/shunit/shunit2_standalone_test.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # vim:et:ft=sh:sts=2:sw=2 3 | # 4 | # shUnit2 unit test for standalone operation. 5 | # 6 | # Copyright 2010-2017 Kate Ward. All Rights Reserved. 7 | # Released under the Apache 2.0 license. 8 | # 9 | # Author: kate.ward@forestent.com (Kate Ward) 10 | # https://github.com/kward/shunit2 11 | # 12 | # This unit test is purely to test that calling shunit2 directly, while passing 13 | # the name of a unit test script, works. When run, this script determines if it 14 | # is running as a standalone program, and calls main() if it is. 15 | # 16 | ### ShellCheck http://www.shellcheck.net/ 17 | # $() are not fully portable (POSIX != portable). 18 | # shellcheck disable=SC2006 19 | # Disable source following. 20 | # shellcheck disable=SC1090,SC1091 21 | 22 | ARGV0="`basename "$0"`" 23 | 24 | # Load test helpers. 25 | . ./shunit2_test_helpers 26 | 27 | testStandalone() { 28 | assertTrue "${SHUNIT_TRUE}" 29 | } 30 | 31 | main() { 32 | ${TH_SHUNIT} "${ARGV0}" 33 | } 34 | 35 | # Are we running as a standalone? 36 | if [ "${ARGV0}" = 'shunit2_test_standalone.sh' ]; then 37 | if [ $# -gt 0 ]; then main "$@"; else main; fi 38 | fi 39 | -------------------------------------------------------------------------------- /tests/signal2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | pkill() 5 | { 6 | __monitor PKILL "$@" 7 | } 8 | 9 | pgrep() 10 | { 11 | __monitor PGREP "$@" 12 | } 13 | 14 | mktemp() 15 | { 16 | __monitor MKTEMP "$@" 17 | echo /dev/null 18 | } 19 | 20 | rm() 21 | { 22 | __monitor RM "$@" 23 | } 24 | 25 | # UUT 26 | . ../share/pot/signal.sh 27 | 28 | . ../share/pot/common.sh 29 | # common stubs 30 | . common-stub.sh 31 | 32 | _get_conf_var() 33 | { 34 | __monitor GETCONFVAR "$@" 35 | if [ "$1" = "test-pot-presist" ]; then 36 | echo "YES" 37 | return 38 | fi 39 | echo "NO" 40 | } 41 | 42 | # app specific stubs 43 | 44 | test_send_signal_001() 45 | { 46 | _send_signal test-pot SIGINFO "" "" "NO" "NO" 47 | assertEqualsMon "pgrep calls" "0" PGREP_CALLS 48 | assertEqualsMon "pkill calls" "1" PKILL_CALLS 49 | assertEqualsMon "pkill arg1" "-SIGINFO" PKILL_CALL1_ARG1 50 | assertEqualsMon "pkill arg2" "-j" PKILL_CALL1_ARG2 51 | assertEqualsMon "pkill arg3" "test-pot" PKILL_CALL1_ARG3 52 | assertEqualsMon "pkill arg4" "-F" PKILL_CALL1_ARG4 53 | assertEqualsMon "pkill arg5" "/tmp/pot_main_pid_test-pot" PKILL_CALL1_ARG5 54 | assertEqualsMon "rm calls" "0" RM_CALLS 55 | } 56 | 57 | test_send_signal_002() 58 | { 59 | _send_signal test-pot-presist SIGINFO "" "" "NO" "NO" 60 | rc=$? 61 | assertEquals "return code" "1" "$rc" 62 | assertEqualsMon "pgrep calls" "0" PGREP_CALLS 63 | assertEqualsMon "pkill calls" "0" PKILL_CALLS 64 | } 65 | 66 | test_send_signal_003() 67 | { 68 | _send_signal test-pot-presist SIGINFO "" "" "YES" "NO" 69 | rc=$? 70 | assertEquals "return code" "0" "$rc" 71 | assertEqualsMon "pgrep calls" "0" PGREP_CALLS 72 | assertEqualsMon "pkill calls" "0" PKILL_CALLS 73 | } 74 | 75 | test_send_signal_010() 76 | { 77 | _send_signal test-pot SIGINFO "" "command" "NO" "NO" 78 | assertEqualsMon "pgrep calls" "0" PGREP_CALLS 79 | assertEqualsMon "pkill calls" "1" PKILL_CALLS 80 | assertEqualsMon "pkill arg1" "-SIGINFO" PKILL_CALL1_ARG1 81 | assertEqualsMon "pkill arg2" "-j" PKILL_CALL1_ARG2 82 | assertEqualsMon "pkill arg3" "test-pot" PKILL_CALL1_ARG3 83 | assertEqualsMon "pkill arg4" "command" PKILL_CALL1_ARG4 84 | assertEqualsMon "rm calls" "0" RM_CALLS 85 | } 86 | 87 | test_send_signal_011() 88 | { 89 | _send_signal test-pot SIGINFO "1234" "" "NO" "NO" 90 | assertEqualsMon "pgrep calls" "0" PGREP_CALLS 91 | assertEqualsMon "pkill calls" "1" PKILL_CALLS 92 | assertEqualsMon "pkill arg1" "-SIGINFO" PKILL_CALL1_ARG1 93 | assertEqualsMon "pkill arg2" "-j" PKILL_CALL1_ARG2 94 | assertEqualsMon "pkill arg3" "test-pot" PKILL_CALL1_ARG3 95 | assertEqualsMon "pkill arg4" "-F" PKILL_CALL1_ARG4 96 | assertEqualsMon "pkill arg5" "/dev/null" PKILL_CALL1_ARG5 97 | assertEqualsMon "rm calls" "1" RM_CALLS 98 | } 99 | 100 | test_send_signal_020() 101 | { 102 | _send_signal test-pot SIGINFO "" "" "NO" "YES" 103 | assertEqualsMon "pgrep calls" "1" PGREP_CALLS 104 | assertEqualsMon "pkill arg1" "-j" PGREP_CALL1_ARG1 105 | assertEqualsMon "pkill arg2" "test-pot" PGREP_CALL1_ARG2 106 | assertEqualsMon "pkill arg4" "/tmp/pot_main_pid_test-pot" PGREP_CALL1_ARG4 107 | assertEqualsMon "pkill calls" "0" PKILL_CALLS 108 | } 109 | 110 | setUp() 111 | { 112 | common_setUp 113 | } 114 | 115 | . shunit/shunit2 116 | -------------------------------------------------------------------------------- /tests/start2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | : ${MKTEMP_FILE:=/tmp/pot_pfrules_test} 4 | # system utilities stubs 5 | pfctl() 6 | { 7 | __monitor PFCTL "$@" 8 | } 9 | 10 | mktemp() 11 | { 12 | touch $MKTEMP_FILE 13 | echo $MKTEMP_FILE 14 | } 15 | 16 | rm() 17 | { 18 | : 19 | } 20 | 21 | # UUT 22 | . ../share/pot/start.sh 23 | 24 | POT_MKTEMP_SUFFIX=XXX 25 | 26 | # common stubs 27 | . common-stub.sh 28 | 29 | _get_pot_export_ports() 30 | { 31 | __monitor GETEXPORTPORTS "$@" 32 | } 33 | 34 | _js_get_free_rnd_port() 35 | { 36 | __monitor RNDPORT "$@" 37 | echo 3333 38 | } 39 | 40 | _get_ip_var() 41 | { 42 | echo 1.2.3.4 43 | } 44 | 45 | _get_pot_export_ports() 46 | { 47 | case $1 in 48 | "test-pot80") 49 | echo 80 50 | ;; 51 | "test-pot80s3000") 52 | echo 80:3000 53 | ;; 54 | "test-pot80433") 55 | echo 80 433:3000 56 | ;; 57 | "test-pot53udp80433tcp") 58 | echo udp:53:53 tcp:80 tcp:433:3000 59 | ;; 60 | *) 61 | ;; 62 | esac 63 | } 64 | 65 | test_js_export_ports_001() 66 | { 67 | _js_export_ports test-pot80 68 | assertEqualsMon "pfctl calls" "1" PFCTL_CALLS 69 | assertEquals "pfrules lines" "1" "$( wc -l $MKTEMP_FILE | awk '{print $1}')" 70 | assertEquals "rdr rule" "rdr pass on em2 proto tcp from any to (em2) port 3333 -> 1.2.3.4 port 80" "$(sed '1!d' $MKTEMP_FILE)" 71 | } 72 | 73 | 74 | test_js_export_ports_002() 75 | { 76 | _js_export_ports test-pot80s3000 77 | assertEqualsMon "pfctl calls" "1" PFCTL_CALLS 78 | assertEquals "pfrules lines" "1" "$( wc -l $MKTEMP_FILE | awk '{print $1}')" 79 | assertEquals "rdr rule" "rdr pass on em2 proto tcp from any to (em2) port 3000 -> 1.2.3.4 port 80" "$(sed '1!d' $MKTEMP_FILE)" 80 | } 81 | 82 | test_js_export_ports_003() 83 | { 84 | _js_export_ports test-pot80433 85 | assertEqualsMon "pfctl calls" "1" PFCTL_CALLS 86 | assertEquals "pfrules lines" "2" "$( wc -l $MKTEMP_FILE | awk '{print $1}')" 87 | assertEquals "rdr rule" "rdr pass on em2 proto tcp from any to (em2) port 3333 -> 1.2.3.4 port 80" "$(sed '1!d' $MKTEMP_FILE)" 88 | assertEquals "rdr rule" "rdr pass on em2 proto tcp from any to (em2) port 3000 -> 1.2.3.4 port 433" "$(sed '2!d' $MKTEMP_FILE)" 89 | } 90 | 91 | test_js_export_ports_004() 92 | { 93 | _js_export_ports test-pot53udp80433tcp 94 | assertEqualsMon "pfctl calls" "1" PFCTL_CALLS 95 | assertEquals "pfrules lines" "3" "$( wc -l $MKTEMP_FILE | awk '{print $1}')" 96 | assertEquals "rdr rule" "rdr pass on em2 proto udp from any to (em2) port 53 -> 1.2.3.4 port 53" "$(sed '1!d' $MKTEMP_FILE)" 97 | assertEquals "rdr rule" "rdr pass on em2 proto tcp from any to (em2) port 3333 -> 1.2.3.4 port 80" "$(sed '2!d' $MKTEMP_FILE)" 98 | assertEquals "rdr rule" "rdr pass on em2 proto tcp from any to (em2) port 3000 -> 1.2.3.4 port 433" "$(sed '3!d' $MKTEMP_FILE)" 99 | } 100 | setUp() 101 | { 102 | common_setUp 103 | POT_FS_ROOT=/tmp 104 | POT_ZFS_ROOT=zpot 105 | POT_EXTIF="em2" 106 | } 107 | 108 | tearDown() 109 | { 110 | common_tearDown 111 | /bin/rm -f $MKTEMP_FILE 112 | } 113 | . shunit/shunit2 114 | -------------------------------------------------------------------------------- /tests/stop1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | lockf() 6 | { 7 | return 0 8 | } 9 | # UUT 10 | . ../share/pot/stop.sh 11 | 12 | . ../share/pot/common.sh 13 | # common stubs 14 | . common-stub.sh 15 | 16 | # app specific stubs 17 | 18 | _js_rm_resolv() 19 | { 20 | return 0 # true 21 | } 22 | 23 | _pot_umount() 24 | { 25 | return 0 # true 26 | } 27 | 28 | _epair_cleanup() 29 | { 30 | return 0 # true 31 | } 32 | 33 | _js_stop() 34 | { 35 | __monitor STOPPED "$@" 36 | } 37 | 38 | stop-help() 39 | { 40 | __monitor HELP "$@" 41 | } 42 | 43 | test_pot_stop_001() 44 | { 45 | pot-stop 46 | assertEquals "Exit rc" "1" "$?" 47 | assertEqualsMon "Help calls" "1" HELP_CALLS 48 | assertEqualsMon "Error calls" "1" ERROR_CALLS 49 | assertEqualsMon "Stop calls" "0" STOPPED_CALLS 50 | 51 | setUp 52 | pot-stop -b bb 53 | assertEquals "Exit rc" "1" "$?" 54 | assertEqualsMon "Help calls" "1" HELP_CALLS 55 | assertEqualsMon "Error calls" "0" ERROR_CALLS 56 | assertEqualsMon "Stop calls" "0" STOPPED_CALLS 57 | 58 | setUp 59 | pot-stop -h 60 | assertEquals "Exit rc" "0" "$?" 61 | assertEqualsMon "Help calls" "1" HELP_CALLS 62 | assertEqualsMon "Error calls" "0" ERROR_CALLS 63 | assertEqualsMon "Stop calls" "0" STOPPED_CALLS 64 | } 65 | 66 | test_pot_stop_002() 67 | { 68 | pot-stop non-existent-test-pot 69 | assertEquals "Exit rc" "0" "$?" 70 | assertEqualsMon "Help calls" "0" HELP_CALLS 71 | assertEqualsMon "Error calls" "1" ERROR_CALLS 72 | assertEqualsMon "Stop calls" "0" STOPPED_CALLS 73 | } 74 | 75 | test_pot_stop_020() 76 | { 77 | pot-stop test-pot 78 | assertEquals "Exit rc" "0" "$?" 79 | assertEqualsMon "Help calls" "0" HELP_CALLS 80 | assertEqualsMon "Error calls" "0" ERROR_CALLS 81 | assertEqualsMon "Stop calls" "1" STOPPED_CALLS 82 | assertEqualsMon "stop args" "test-pot" STOPPED_CALL1_ARG1 83 | assertEqualsMon "stop args" "NO" STOPPED_CALL1_ARG2 84 | assertEqualsMon "stop args" "" STOPPED_CALL1_ARG3 85 | } 86 | 87 | test_pot_stop_021() 88 | { 89 | pot-stop -p test-pot 90 | assertEquals "Exit rc" "0" "$?" 91 | assertEqualsMon "Help calls" "0" HELP_CALLS 92 | assertEqualsMon "Error calls" "0" ERROR_CALLS 93 | assertEqualsMon "Stop calls" "1" STOPPED_CALLS 94 | assertEqualsMon "stop args" "test-pot" STOPPED_CALL1_ARG1 95 | assertEqualsMon "stop args" "NO" STOPPED_CALL1_ARG2 96 | assertEqualsMon "stop args" "" STOPPED_CALL1_ARG3 97 | } 98 | 99 | test_pot_stop_022() 100 | { 101 | pot-stop -p test-pot -s 102 | assertEquals "Exit rc" "0" "$?" 103 | assertEqualsMon "Help calls" "0" HELP_CALLS 104 | assertEqualsMon "Error calls" "0" ERROR_CALLS 105 | assertEqualsMon "Stop calls" "1" STOPPED_CALLS 106 | assertEqualsMon "stop args" "test-pot" STOPPED_CALL1_ARG1 107 | assertEqualsMon "stop args" "YES" STOPPED_CALL1_ARG2 108 | assertEqualsMon "stop args" "" STOPPED_CALL1_ARG3 109 | } 110 | 111 | test_pot_stop_023() 112 | { 113 | pot-stop -p test-pot -s -i epair4a 114 | assertEquals "Exit rc" "0" "$?" 115 | assertEqualsMon "Help calls" "0" HELP_CALLS 116 | assertEqualsMon "Error calls" "0" ERROR_CALLS 117 | assertEqualsMon "Stop calls" "1" STOPPED_CALLS 118 | assertEqualsMon "stop args" "test-pot" STOPPED_CALL1_ARG1 119 | assertEqualsMon "stop args" "YES" STOPPED_CALL1_ARG2 120 | assertEqualsMon "stop args" "epair4a" STOPPED_CALL1_ARG3 121 | } 122 | 123 | setUp() 124 | { 125 | common_setUp 126 | } 127 | 128 | . shunit/shunit2 129 | -------------------------------------------------------------------------------- /tests/term1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/term.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | . common-stub.sh 11 | 12 | # app specific stubs 13 | 14 | pot-cmd() 15 | { 16 | __monitor POTCMD "$@" 17 | if [ "$POTCMD_SHOULD_START_POT" = "yes" ]; then 18 | _pname="test-pot-run" 19 | fi 20 | } 21 | 22 | 23 | _term() 24 | { 25 | __monitor TERM "$@" 26 | } 27 | 28 | term-help() 29 | { 30 | __monitor HELP "$@" 31 | } 32 | 33 | test_pot_term_001() 34 | { 35 | pot-term 36 | assertEquals "Exit rc" "1" "$?" 37 | assertEqualsMon "Help calls" "1" HELP_CALLS 38 | assertEqualsMon "Error calls" "1" ERROR_CALLS 39 | assertEqualsMon "_is_pot_running calls" "0" ISPOTRUN_CALLS 40 | assertEqualsMon "_term calls" "0" TERM_CALLS 41 | assertEqualsMon "pot-cmd calls" "0" POTCMD_CALLS 42 | 43 | setUp 44 | pot-term -b bb 45 | assertEquals "Exit rc" "1" "$?" 46 | assertEqualsMon "Help calls" "0" HELP_CALLS 47 | assertEqualsMon "Error calls" "1" ERROR_CALLS 48 | assertEqualsMon "_is_pot_running calls" "1" ISPOTRUN_CALLS 49 | assertEqualsMon "_term calls" "0" TERM_CALLS 50 | assertEqualsMon "pot-cmd calls" "0" POTCMD_CALLS 51 | 52 | setUp 53 | pot-term -h 54 | assertEquals "Exit rc" "0" "$?" 55 | assertEqualsMon "Help calls" "1" HELP_CALLS 56 | assertEqualsMon "Error calls" "0" ERROR_CALLS 57 | assertEqualsMon "_is_pot_running calls" "0" ISPOTRUN_CALLS 58 | assertEqualsMon "_term calls" "0" TERM_CALLS 59 | assertEqualsMon "pot-cmd calls" "0" POTCMD_CALLS 60 | } 61 | 62 | test_pot_term_020() 63 | { 64 | pot-term test-pot-run 65 | assertEquals "Exit rc" "0" "$?" 66 | assertEqualsMon "Help calls" "0" HELP_CALLS 67 | assertEqualsMon "Error calls" "0" ERROR_CALLS 68 | assertEqualsMon "_is_pot_running calls" "1" ISPOTRUN_CALLS 69 | assertEqualsMon "_term calls" "1" TERM_CALLS 70 | assertEqualsMon "pot-cmd calls" "0" POTCMD_CALLS 71 | } 72 | 73 | test_pot_term_030() 74 | { 75 | pot-term test-pot 76 | assertEquals "Exit rc" "1" "$?" 77 | assertEqualsMon "Help calls" "0" HELP_CALLS 78 | assertEqualsMon "Error calls" "1" ERROR_CALLS 79 | assertEqualsMon "_is_pot_running calls" "1" ISPOTRUN_CALLS 80 | assertEqualsMon "_term calls" "0" TERM_CALLS 81 | assertEqualsMon "pot-cmd calls" "0" POTCMD_CALLS 82 | } 83 | 84 | test_pot_term_031() 85 | { 86 | pot-term -f test-pot 87 | assertEquals "Exit rc" "1" "$?" 88 | assertEqualsMon "Help calls" "0" HELP_CALLS 89 | assertEqualsMon "Error calls" "1" ERROR_CALLS 90 | assertEqualsMon "_is_pot_running calls" "2" ISPOTRUN_CALLS 91 | assertEqualsMon "_term calls" "0" TERM_CALLS 92 | assertEqualsMon "pot-cmd calls" "1" POTCMD_CALLS 93 | } 94 | 95 | test_pot_term_032() { 96 | # In this test "pot-cmd start" is changing pot name from 97 | # test-pot to test-pot-run. 98 | POTCMD_SHOULD_START_POT=yes 99 | pot-term -f test-pot 100 | assertEquals "Exit rc" "0" "$?" 101 | assertEqualsMon "Help calls" "0" HELP_CALLS 102 | assertEqualsMon "Error calls" "0" ERROR_CALLS 103 | assertEqualsMon "_is_pot_running calls" "2" ISPOTRUN_CALLS 104 | assertEqualsMon "_term calls" "1" TERM_CALLS 105 | assertEqualsMon "pot-cmd calls" "1" POTCMD_CALLS 106 | } 107 | 108 | 109 | setUp() 110 | { 111 | common_setUp 112 | POTCMD_SHOULD_START_POT=no 113 | } 114 | 115 | . shunit/shunit2 116 | -------------------------------------------------------------------------------- /tests/test-suite.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | DOIT= 4 | SHL="sh" 5 | if [ "$(uname)" = "Linux" ]; then 6 | # using bash explicitely because of travis unkowns about /bin/sh 7 | DOIT=bash 8 | SHL=bash 9 | fi 10 | 11 | if ! $SHL -n ../bin/pot ../share/pot/*.sh ; then 12 | exit 1 13 | else 14 | echo "Syntax check passed" 15 | echo 16 | fi 17 | 18 | if ! command -v flock >/dev/null; then 19 | echo "flock not found." 1>&2 20 | if [ "$(uname)" = "FreeBSD" ]; then 21 | echo "Consider installing sysutils/flock" 1>&2 22 | echo "(pkg install flock)" 1>&2 23 | fi 24 | exit 1 25 | fi 26 | 27 | suites=$(ls ./*.sh) 28 | rc=0 29 | for s in $suites ; do 30 | if [ "$s" = "./test-suite.sh" ]; then 31 | continue 32 | elif [ "$s" = "./common-stub.sh" ]; then 33 | continue 34 | elif [ "$s" = "./conf-stub.sh" ]; then 35 | continue 36 | elif [ "$s" = "./pipefail-stub.sh" ]; then 37 | continue 38 | elif [ "$s" = "./monitor.sh" ]; then 39 | continue 40 | else 41 | echo "Running $( basename $s ) ..." 42 | $DOIT "./$s" || rc=1 43 | fi 44 | done 45 | exit $rc 46 | -------------------------------------------------------------------------------- /tests/top1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | top() 6 | { 7 | __monitor TOP "$@" 8 | } 9 | 10 | # UUT 11 | . ../share/pot/top.sh 12 | 13 | . ../share/pot/common.sh 14 | # common stubs 15 | . common-stub.sh 16 | 17 | # app specific stubs 18 | top-help() 19 | { 20 | __monitor HELP "$@" 21 | } 22 | 23 | test_pot_top_001() 24 | { 25 | pot-top -b bb 26 | assertEquals "Exit rc" "1" "$?" 27 | assertEqualsMon "Help calls" "1" HELP_CALLS 28 | assertEqualsMon "Error calls" "0" ERROR_CALLS 29 | assertEqualsMon "top calls" "0" TOP_CALLS 30 | 31 | setUp 32 | pot-top -h 33 | assertEquals "Exit rc" "0" "$?" 34 | assertEqualsMon "Help calls" "1" HELP_CALLS 35 | assertEqualsMon "Error calls" "0" ERROR_CALLS 36 | assertEqualsMon "top calls" "0" TOP_CALLS 37 | } 38 | 39 | test_pot_top_020() 40 | { 41 | pot-top -p 42 | assertEquals "Exit rc" "1" "$?" 43 | assertEqualsMon "Help calls" "1" HELP_CALLS 44 | assertEqualsMon "Error calls" "0" ERROR_CALLS 45 | assertEqualsMon "top calls" "0" TOP_CALLS 46 | assertEqualsMon "top arg1" "" TOP_CALL1_ARG1 47 | } 48 | 49 | test_pot_top_021() 50 | { 51 | pot-top -p "" 52 | assertEquals "Exit rc" "1" "$?" 53 | assertEqualsMon "Help calls" "1" HELP_CALLS 54 | assertEqualsMon "Error calls" "1" ERROR_CALLS 55 | assertEqualsMon "top calls" "0" TOP_CALLS 56 | assertEqualsMon "top arg1" "" TOP_CALL1_ARG1 57 | } 58 | 59 | test_pot_top_022() 60 | { 61 | pot-top -p no-pot 62 | assertEquals "Exit rc" "1" "$?" 63 | assertEqualsMon "Help calls" "1" HELP_CALLS 64 | assertEqualsMon "Error calls" "1" ERROR_CALLS 65 | assertEqualsMon "top calls" "0" TOP_CALLS 66 | assertEqualsMon "top arg1" "" TOP_CALL1_ARG1 67 | } 68 | 69 | test_pot_top_023() 70 | { 71 | pot-top -p test-pot 72 | assertEquals "Exit rc" "1" "$?" 73 | assertEqualsMon "Help calls" "1" HELP_CALLS 74 | assertEqualsMon "Error calls" "1" ERROR_CALLS 75 | assertEqualsMon "top calls" "0" TOP_CALLS 76 | assertEqualsMon "top arg1" "" TOP_CALL1_ARG1 77 | } 78 | 79 | test_pot_top_040() 80 | { 81 | pot-top -p test-pot-run 82 | assertEquals "Exit rc" "0" "$?" 83 | assertEqualsMon "Help calls" "0" HELP_CALLS 84 | assertEqualsMon "Error calls" "0" ERROR_CALLS 85 | assertEqualsMon "top calls" "1" TOP_CALLS 86 | assertEqualsMon "top arg1" "-J" TOP_CALL1_ARG1 87 | assertEqualsMon "top arg2" "test-pot-run" TOP_CALL1_ARG2 88 | } 89 | 90 | setUp() 91 | { 92 | common_setUp 93 | } 94 | 95 | . shunit/shunit2 96 | -------------------------------------------------------------------------------- /tests/version1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # system utilities stubs 4 | 5 | # UUT 6 | . ../share/pot/version.sh 7 | 8 | . ../share/pot/common.sh 9 | # common stubs 10 | . common-stub.sh 11 | 12 | # app specific stubs 13 | version-help() 14 | { 15 | __monitor HELP "$@" 16 | } 17 | 18 | test_pot_version_001() 19 | { 20 | pot-version -b bb 21 | assertEquals "Exit rc" "1" "$?" 22 | assertEqualsMon "Help calls" "1" HELP_CALLS 23 | 24 | setUp 25 | pot-version -h 26 | assertEquals "Exit rc" "0" "$?" 27 | assertEqualsMon "Help calls" "1" HELP_CALLS 28 | } 29 | 30 | test_pot_version_020() 31 | { 32 | result=$(pot-version) 33 | assertEquals "Exit rc" "0" "$?" 34 | assertEquals "Incorrect version" "pot version: $_POT_VERSION" "$result" 35 | } 36 | 37 | test_pot_version_021() 38 | { 39 | result=$(pot-version -v) 40 | assertEquals "Exit rc" "0" "$?" 41 | assertEquals "Incorrect version" "pot version: $_POT_VERSION" "$result" 42 | } 43 | 44 | test_pot_version_022() 45 | { 46 | result=$(pot-version -q) 47 | assertEquals "Exit rc" "0" "$?" 48 | assertEquals "Incorrect version" "$_POT_VERSION" "$result" 49 | } 50 | 51 | setUp() 52 | { 53 | common_setUp 54 | _POT_VERSION="5.4.3" 55 | _POT_VERBOSITY="1" 56 | 57 | } 58 | 59 | . shunit/shunit2 60 | --------------------------------------------------------------------------------