diff --git a/.gitignore b/.gitignore index 04d0e8bd..dba7ee01 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ example/*/Makefile lib/Makefile lib/*/Makefile test/Makefile +test/*/Makefile yang/Makefile yang/*/Makefile autom4te.cache/ @@ -58,4 +59,6 @@ util/clixon_util_xpath util/clixon_util_yang test/site.sh +test/vagrant/site.mk +test/cicd/site.mk doc/html \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 003669a3..16267558 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Expected: July 2020 ### Minor changes +* Added [Vagrant tests](test/vagrant/README.md) * Added new function `clicon_xml2str()` to complement xml_print and others that returns a malloced string. * Added new function `xml_child_index_each()` to iterate over the children of an XML node according to the order defined by an explicit index variable. This is a complement to `xml_child_each()` which iterates using the default order. diff --git a/apps/restconf/restconf_fcgi_lib.c b/apps/restconf/restconf_fcgi_lib.c index ea2371d4..1ad9678c 100644 --- a/apps/restconf/restconf_fcgi_lib.c +++ b/apps/restconf/restconf_fcgi_lib.c @@ -246,8 +246,8 @@ clixon_restconf_params_set(clicon_handle h, { int retval = -1; int i; - char *param; - char *val; + char *param = NULL; + char *val = NULL; clicon_debug(1, "%s", __FUNCTION__); for (i = 0; envp[i] != NULL; i++){ /* on the form = */ @@ -256,6 +256,14 @@ clixon_restconf_params_set(clicon_handle h, clicon_debug(1, "%s param:%s val:%s", __FUNCTION__, param, val); if (clixon_restconf_param_set(h, param, val) < 0) goto done; + if (param){ + free(param); + param = NULL; + } + if (val){ + free(val); + val = NULL; + } } retval = 0; done: @@ -274,16 +282,19 @@ clixon_restconf_params_clear(clicon_handle h, { int retval = -1; int i; - char *param; - char *val; + char *param = NULL; clicon_debug(1, "%s", __FUNCTION__); for (i = 0; envp[i] != NULL; i++){ /* on the form = */ - if (clixon_strsplit(envp[i], '=', ¶m, &val) < 0) + if (clixon_strsplit(envp[i], '=', ¶m, NULL) < 0) goto done; - clicon_debug(1, "%s param:%s val:%s", __FUNCTION__, param, val); + clicon_debug(1, "%s param:%s", __FUNCTION__, param); if (clixon_restconf_param_del(h, param) < 0) goto done; + if (param){ + free(param); + param = NULL; + } } retval = 0; done: diff --git a/configure b/configure index 379c41b0..4f6c306e 100755 --- a/configure +++ b/configure @@ -5325,7 +5325,7 @@ _ACEOF -ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/main/Makefile extras/rpm/Makefile docker/Makefile docker/main/Makefile docker/base/Makefile util/Makefile yang/Makefile yang/clixon/Makefile yang/mandatory/Makefile yang/optional/Makefile doc/Makefile test/Makefile test/cicd/Makefile" +ac_config_files="$ac_config_files Makefile lib/Makefile lib/src/Makefile lib/clixon/Makefile apps/Makefile apps/cli/Makefile apps/backend/Makefile apps/netconf/Makefile apps/restconf/Makefile include/Makefile etc/Makefile etc/clixonrc example/Makefile example/main/Makefile extras/rpm/Makefile docker/Makefile docker/main/Makefile docker/base/Makefile util/Makefile yang/Makefile yang/clixon/Makefile yang/mandatory/Makefile yang/optional/Makefile doc/Makefile test/Makefile test/cicd/Makefile test/vagrant/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -6045,6 +6045,7 @@ do "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; "test/cicd/Makefile") CONFIG_FILES="$CONFIG_FILES test/cicd/Makefile" ;; + "test/vagrant/Makefile") CONFIG_FILES="$CONFIG_FILES test/vagrant/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac diff --git a/configure.ac b/configure.ac index 075ffeed..a596e841 100644 --- a/configure.ac +++ b/configure.ac @@ -325,6 +325,7 @@ AC_OUTPUT(Makefile yang/optional/Makefile doc/Makefile test/Makefile - test/cicd/Makefile + test/cicd/Makefile + test/vagrant/Makefile ) diff --git a/test/README.md b/test/README.md index 0f5bfac2..579fce68 100644 --- a/test/README.md +++ b/test/README.md @@ -19,6 +19,10 @@ this directory is executed. There are also [manual cicd scripts here](cicd/README.md) +## Vagrant + +[Vagrant scripts are here](vagrant/README.md) + ## Getting started You need to build and install the clixon utility programs before running the tests as some of the tests rely on them: diff --git a/test/cicd/Makefile.in b/test/cicd/Makefile.in index 13ea0c51..c4b97269 100644 --- a/test/cicd/Makefile.in +++ b/test/cicd/Makefile.in @@ -41,25 +41,19 @@ SHELL = /bin/sh .PHONY: all clean distclean depend install uninstall -HOSTS= -# The "hosts" file must exist and define the HOSTS variable +# Include "site.mk" file if it exists and define the HOSTS variables # eg : # HOSTS += vandal.hagsand.com # i86_32 ubuntu # ... --include hosts +HOSTS= +-include site.mk -SCRIPTS = cligen-mk.sh -SCRIPTS += clixon-mk.sh -SCRIPTS += clixon-config.sh +.PHONY: all clean distclean depend install uninstall $(HOSTS) $(VAGRANTS) -.PHONY: all clean distclean depend install uninstall $(HOSTS) - -all: $(HOSTS) +all: $(HOSTS) $(VAGRANTS) +# Real hosts reachable by ssh $(HOSTS): - for s in $(SCRIPTS); do \ - (scp $$s $@:/tmp/ ; ssh $@ chmod 750 /tmp/$$s || exit 1) \ - done; ./cicd.sh $@ 2>&1 | tee $@.log clean: diff --git a/test/cicd/README.md b/test/cicd/README.md index 57bc5b44..515534ed 100644 --- a/test/cicd/README.md +++ b/test/cicd/README.md @@ -1,15 +1,13 @@ -CICD scripts -============ -Manual scripts for running committed code on a set of hosts. +Hosts scripts +============= +Manual scripts for running committed code on a set of remote hosts accessible with ssh. The script then uses a Makefile and logs in to each host, pulls from git, configure, makes and runs through the tests. Make is used to get -concurrency - non-trivial with bash, eg with `make -j 10` +concurrency, eg with `make -j 10` -Note there are other cicd scripts than this, such as the the "travis" scrips. - -The Makefile contains a configurable HOSTS variable, which ius defined -in a "hosts" file. You must add such a file, eg: +The Makefile contains a configurable HOSTS variable, which is defined +in a "site.mk" file. You must add such a file, eg: ``` HOSTS += vandal.hagsand.com # i86_32 ubuntu ``` diff --git a/test/cicd/cicd.sh b/test/cicd/cicd.sh index 660ef33b..ec1821a1 100755 --- a/test/cicd/cicd.sh +++ b/test/cicd/cicd.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash # CI/CD script complementing trevor github -# Login in to a number of hosts and fo the following: +# Triggered from Makefile +# Login in to a number of hosts and do the following: # 0. Create and transfer sub-scripts used in main script: cligen-mk.sh clixon-mk.sh clixon-config.sh # 1. pull latest version # 2. Run configure @@ -27,14 +28,23 @@ fi h=$1 +SCRIPTS="cligen-mk.sh clixon-mk.sh clixon-config.sh" + +# Copy test scripts to remote machine +scp $SCRIPTS $h:/tmp/ +ssh -t $h "(cd /tmp; chmod 750 $SCRIPTS)" + +# pull git changes and build cligen ssh -t $h "test -d src || mkdir src" ssh -t $h "test -d src/cligen || (cd src;git clone https://github.com/olofhagsand/cligen.git)" ssh -t $h "(cd src/cligen;git pull)" ssh -t $h "(cd src/cligen;./configure)" ssh -t $h "(cd src/cligen; /tmp/cligen-mk.sh)" +# pull git changes and build clixon ssh -t $h "test -d src/clixon || (cd src;git clone https://github.com/clicon/clixon.git)" ssh -t $h "(cd src/clixon;git pull)" ssh -t $h "(cd src/clixon; /tmp/clixon-config.sh)" ssh -t $h "(cd src/clixon; /tmp/clixon-mk.sh)" ssh -t $h sudo ldconfig +# Run clixon test suite ssh -t $h "(cd src/clixon/test; ./sum.sh)" diff --git a/test/test_api_path.sh b/test/test_api_path.sh index 6a38b45a..3c19f9e8 100755 --- a/test/test_api_path.sh +++ b/test/test_api_path.sh @@ -12,14 +12,14 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi : ${clixon_util_path:=clixon_util_path -a -D $DBG} +# Number of list/leaf-list entries +: ${nr:=100} + if [ $nr -lt 2 ] ; then echo "nr==$nr must be > 1" exit fi -# Number of list/leaf-list entries -: ${nr:=100} - # Number of tests to generate XML for max=7 diff --git a/test/vagrant/Makefile.in b/test/vagrant/Makefile.in new file mode 100644 index 00000000..70a921c8 --- /dev/null +++ b/test/vagrant/Makefile.in @@ -0,0 +1,73 @@ +# +# ***** BEGIN LICENSE BLOCK ***** +# +# Copyright (C) 2009-2019 Olof Hagsand +# Copyright (C) 2020 Olof Hagsand and Rubicon Communications, LLC(Netgate) +# +# This file is part of CLIXON +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Alternatively, the contents of this file may be used under the terms of +# the GNU General Public License Version 3 or later (the "GPL"), +# in which case the provisions of the GPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of the GPL, and not to allow others to +# use your version of this file under the terms of Apache License version 2, +# indicate your decision by deleting the provisions above and replace them with +# the notice and other provisions required by the GPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the Apache License version 2 or the GPL. +# +# ***** END LICENSE BLOCK ***** +# + +VPATH = @srcdir@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ + +SHELL = /bin/sh + +.PHONY: all clean distclean depend install uninstall + + +# The "site.mk" file if it exists and define the VAGRANTS variables +# eg: +# VAGRANTS += freebsd/FreeBSD-12.1-STABLE + +VAGRANTS = + +-include site.mk + +.PHONY: all clean distclean depend install uninstall $(VAGRANTS) + +all: $(VAGRANTS) + +# Local vagrant hosts +$(VAGRANTS): + ./vagrant.sh $@ destroy 2>&1 | tee $@.log + +clean: + rm -f *.log + +distclean: clean + rm -f Makefile *~ .depend + +depend: + +install-include: + +install: + +uninstall: + diff --git a/test/vagrant/README.md b/test/vagrant/README.md new file mode 100644 index 00000000..6e0c30e5 --- /dev/null +++ b/test/vagrant/README.md @@ -0,0 +1,28 @@ +Vagrant scripts +=============== +Scripts for booting local vagrant hosts, installing clixon and running clixon tests + +The script then uses a Makefile and logs in to each host, pulls from +git, configure, makes and runs through the tests. Make is used to get +concurrency - eg with `make -j 10` + +The Makefile contains a configurable VAGRANTS variable, which is defined +in a "site.mk" file. You can add such a file, eg: +``` + VAGRANTS += freebsd/FreeBSD-12.1-STABLE + VAGRANTS += generic/centos8 +``` + +Logs appear in : .log. + +You can also run a single vagrant test as follows: +``` + vagrant.sh freebsd/FreeBSD-12.1-STABLE +``` + +The current status is as follows +* freebsd/FreeBSD-12.1-STABLE +* generic/centos8 - some remaining nginx issue +* generic/opensuse42 - fastcgi is not installed + +See more Vagrant boxes at [https://vagrantcloud.com/search]). diff --git a/test/vagrant/nginx.sh b/test/vagrant/nginx.sh new file mode 100755 index 00000000..587b6b2c --- /dev/null +++ b/test/vagrant/nginx.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash +# Nginx config script. There are different variants of nginx configs, just off-loading +# this to a separate script to hide the complexity + +set -eux + +if [ $# -ne 3 ]; then + echo "usage: $0 " + exit -1 +fi +dir=$1 +idfile=$2 +port=$3 + +sshcmd="ssh -o StrictHostKeyChecking=no -i $idfile -p $port vagrant@127.0.0.1" +scpcmd="scp -o StrictHostKeyChecking=no -p -i $idfile -P $port" + +if $($sshcmd test -d /etc/nginx/conf.d) ; then + confd=true +else + confd=false +fi + +if $confd; then # conf.d nginx config +cat < $dir/default.conf +# +server { + listen 80 default_server; + listen localhost:80 default_server; + listen [::]:80 default_server; + server_name localhost; + server_name _; + location / { + fastcgi_pass unix:/www-data/fastcgi_restconf.sock; + include fastcgi_params; + } + location /streams { + fastcgi_pass unix:/www-data/fastcgi_restconf.sock; + include fastcgi_params; + proxy_http_version 1.1; + proxy_set_header Connection ""; + } +} +EOF + $scpcmd $dir/default.conf vagrant@127.0.0.1: +cat< $dir/startnginx.sh + sudo cp default.conf /etc/nginx/conf.d/ +# if [ ! -d /run/nginx ]; then +# sudo mkdir /run/nginx +# fi + # Start nginx + /usr/sbin/nginx -c /etc/nginx/nginx.conf + >&2 echo "nginx started" + +EOF + +else # full nginx config + +# Nginx conf file +cat<<'EOF' > $dir/nginx.conf +# +worker_processes 1; +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + # '$status $body_bytes_sent "$http_referer" ' + # '"$http_user_agent" "$http_x_forwarded_for"'; + + #access_log logs/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + server { + listen 80 default_server; + listen localhost:80 default_server; + listen [::]:80 default_server; + server_name localhost; + server_name _; + location / { + fastcgi_pass unix:/www-data/fastcgi_restconf.sock; + include fastcgi_params; + } + location /streams { + fastcgi_pass unix:/www-data/fastcgi_restconf.sock; + include fastcgi_params; + proxy_http_version 1.1; + proxy_set_header Connection ""; + } + } +} +EOF + $scpcmd $dir/nginx.conf vagrant@127.0.0.1: +cat< $dir/startnginx.sh + #!/usr/bin/env bash + # start nginx + sudo cp nginx.conf /usr/local/etc/nginx/ + if [ ! $(grep nginx_enable /etc/rc.conf) ]; then + sudo sh -c ' echo 'nginx_enable="YES"' >> /etc/rc.conf' + fi + sudo /usr/local/etc/rc.d/nginx restart +EOF + +fi # full nginx config + +chmod a+x $dir/startnginx.sh +$scpcmd $dir/startnginx.sh vagrant@127.0.0.1: +$sshcmd ./startnginx.sh + diff --git a/test/vagrant/vagrant.sh b/test/vagrant/vagrant.sh new file mode 100755 index 00000000..c0555f2e --- /dev/null +++ b/test/vagrant/vagrant.sh @@ -0,0 +1,183 @@ +#!/usr/bin/env bash +# Script for running cligen and clixon test scripts on local vagrant virtual hosts +# 1. Create a vagrant host based on "box" argument +# 2. setup host for clixon +# 3. Compile and install clixon +# 4. Run tests +# Example run: ./vagrant.sh generic/centos8 2>&1 | tee cilog + +set -eux # x + +if [ $# -ne 1 -a $# -ne 2 ]; then + echo "usage: $0 [destroy]\n as defined in https://vagrantcloud.com/search" + exit -1 +fi + +box=$1 # As defined in https://vagrantcloud.com/search +if [ $# -eq 2 ]; then + destroy=true +else + destroy=false +fi +host=$(echo "$box"|awk -F'/' '{print $2}') +dir=$box +# XXX: ad-hoc to get (linus) release from boxname +# using lsb_release is too heavyweight in many cases +release=$(echo "$host" | grep -io "[a-z]*" | head -1 | tr '[:upper:]' '[:lower:]') + +# example box="freebsd/FreeBSD-12.1-STABLE" +test -d $dir || mkdir -p $dir + +# Write a freebsd vagrant file +cat< $dir/Vagrantfile +Vagrant.configure("2") do |config| + # Every Vagrant development environment requires a box. You can search for + # boxes at https://vagrantcloud.com/search. + config.vm.box = "$box" + config.ssh.shell = "sh" # freebsd + config.vm.define "$host" + config.vm.hostname = "$host" +end +EOF + +# Start vagrant +if $destroy; then + (cd $dir; vagrant destroy -f) +fi +(cd $dir; vagrant up) + +# Get ssh config to make proper ssh/scp calls to local vagrant host +cfg=$(cd $dir; vagrant ssh-config $host) +idfile=$(echo "$cfg" |grep "IdentityFile"|awk '{print $2}') +port=$(echo "$cfg" |grep "Port"|awk '{print $2}') +# make ssh and scp shorthand commands using vagrant-generated keys +sshcmd="ssh -o StrictHostKeyChecking=no -i $idfile -p $port vagrant@127.0.0.1" +scpcmd="scp -p -o StrictHostKeyChecking=no -i $idfile -P $port" +ssh-keygen -f "$HOME/.ssh/known_hosts" -R "[127.0.0.1]:$port" +echo "$sshcmd" + +system=$($sshcmd uname) + +case $system in + FreeBSD) + # packages for building + $sshcmd sudo pkg install -y git gmake bash + # cligen + $sshcmd sudo pkg install -y bison flex + # clixon + $sshcmd sudo pkg install -y fcgi-devkit nginx # FreeBSD + ;; + Linux) + case $release in + centos) # centos 8 + # packages for building + $sshcmd sudo yum install -y git + # cligen + $sshcmd sudo yum install -y bison flex + # clixon + $sshcmd sudo yum install -y fcgi-devel nginx + # clixon utilities + $sshcmd sudo yum install -y libcurl-devel + ;; + opensuse) # opensuse42 + # clixon + $sshcmd sudo zypper install -y nginx + ;; + *) + ;; + esac + ;; + *) + echo "Unknown system: $system" + ;; +esac + +# Hide all complex nginx config in sub-script +. ./nginx.sh $dir $idfile $port + +# Setup cligen and clixon +# 'EOF' means dont expand $ +cat<<'EOF' > $dir/setup.sh +#!/usr/bin/env bash +set -eux # x + +if [ $# -ne 1 ]; then + echo "usage: $0 " + exit -1 +fi +release=$1 +# create user & group +if [ ! $(id -u clicon) ]; then + if [ $release = "freebsd" ]; then + sudo pw useradd clicon; + sudo pw group mod clicon -m vagrant; + sudo pw group mod clicon -m www; + else + sudo useradd clicon; + sudo usermod -a -G clicon vagrant; + sudo usermod -a -G clicon nginx; # nginx? + fi +fi + +# cligen +test -d src || mkdir src +test -d src/cligen || (cd src;git clone https://github.com/olofhagsand/cligen.git) +cd src/cligen +git pull + +if [ $release = "freebsd" ]; then + ./configure + MAKE=$(which gmake) +else + ./configure --prefix=/usr + MAKE=$(which make) +fi +echo "MAKE:$MAKE" +$MAKE clean +$MAKE -j10 +sudo $MAKE install + +# Clixon +cd +test -d src/clixon || (cd src;git clone https://github.com/clicon/clixon.git) +cd src/clixon +git pull + +if [ $release = "freebsd" ]; then + LDFLAGS=-L/usr/local/lib ./configure --with-wwwuser=www --enable-optyangs +else + # Problems with su not having "sbin" in path on centos when when we run tests later + ./configure --sbindir=/usr/sbin --libdir=/usr/lib --with-wwwuser=nginx --enable-optyangs +fi +$MAKE clean +$MAKE -j10 +sudo $MAKE install +(cd example; $MAKE) +(cd util; $MAKE) +(cd example; sudo $MAKE install) +(cd util; sudo $MAKE install) +sudo ldconfig +cd test +echo "#!/usr/bin/env bash" > ./site.sh +if [ $release = "freebsd" ]; then +echo "wwwuser=www" >> ./site.sh +echo "make=gmake" >> ./site.sh +echo 'SKIPLIST="test_api.sh"' >> ./site.sh +else +echo "wwwuser=nginx" >> ./site.sh +fi +EOF +chmod a+x $dir/setup.sh + +# config and setup cligen and clixon +$scpcmd $dir/setup.sh vagrant@127.0.0.1: +$sshcmd ./setup.sh $release + +# Run tests +$sshcmd "(cd src/cligen/test; ./sum.sh)" +$sshcmd "(cd src/clixon/test; ./sum.sh)" + +# destroy vm +if $destroy; then + (cd $dir; vagrant destroy -f) +fi