From 6c0d1eafe38f156978f55a09a79645ec6ab95a89 Mon Sep 17 00:00:00 2001
From: Simon Walter <simon@gikaku.com>
Date: Thu, 9 May 2024 14:41:26 +0200
Subject: [PATCH] net_bridge_interfaces_d for making bridge interfaces on
 debian derivatives

---
 .../type/__net_bridge_interfaces_d/README     |  11 ++
 .../explorer/interface                        |  46 ++++++
 .../explorer/interfaces.d                     |  33 ++++
 .../files/dynamic.sh                          |  10 ++
 .../__net_bridge_interfaces_d/files/static.sh |  16 ++
 .../__net_bridge_interfaces_d/gencode-remote  | 146 ++++++++++++++++++
 .../type/__net_bridge_interfaces_d/man.rst    |  80 ++++++++++
 .../type/__net_bridge_interfaces_d/man.text   |  79 ++++++++++
 .../type/__net_bridge_interfaces_d/manifest   |  36 +++++
 .../parameter/boolean                         |   1 +
 .../parameter/default/state                   |   1 +
 .../parameter/optional                        |   5 +
 12 files changed, 464 insertions(+)
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/README
 create mode 100755 cdist/conf/type/__net_bridge_interfaces_d/explorer/interface
 create mode 100755 cdist/conf/type/__net_bridge_interfaces_d/explorer/interfaces.d
 create mode 100755 cdist/conf/type/__net_bridge_interfaces_d/files/dynamic.sh
 create mode 100755 cdist/conf/type/__net_bridge_interfaces_d/files/static.sh
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/gencode-remote
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/man.rst
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/man.text
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/manifest
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/parameter/boolean
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/parameter/default/state
 create mode 100644 cdist/conf/type/__net_bridge_interfaces_d/parameter/optional

diff --git a/cdist/conf/type/__net_bridge_interfaces_d/README b/cdist/conf/type/__net_bridge_interfaces_d/README
new file mode 100644
index 00000000..6b653873
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/README
@@ -0,0 +1,11 @@
+Notes:
+
+It would be nice if some CentOS/Redhat/Slackware/BSD/etc hackers could write
+other types to compliment this one for other OSes. Then we can unite them with a
+__net_bridge type that would call the other types such as this one.
+
+I might add support for vde2 and other linux/BSD virtual network technologies
+when I require them.
+
+If you have such a requirement for Debian derivatives, do not hesitate to
+contact me.
\ No newline at end of file
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/explorer/interface b/cdist/conf/type/__net_bridge_interfaces_d/explorer/interface
new file mode 100755
index 00000000..9cffa449
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/explorer/interface
@@ -0,0 +1,46 @@
+#!/bin/sh
+#
+# 2016 Simon Walter (simon at explicit dot technology)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+# Debug
+#exec >&2
+#set -x
+
+if [ -f "$__object/parameter/name" ]; then
+    name="$(cat "$__object/parameter/name")"
+else
+    name="$__object_id"
+fi
+
+if [ -f "/etc/network/interfaces.d/${name}" ] && ip link | grep -q "$name"; then
+    echo "true"
+fi
+if [ ! -f "/etc/network/interfaces.d/${name}" ] && ! ip link | grep -q "$name"; then
+    echo "false"
+fi
+if [ ! -f "/etc/network/interfaces.d/${name}" ] && ip link | grep -q "$name"; then
+    echo "conflict"
+fi
+if [ -f "/etc/network/interfaces.d/${name}" ] && ! ip link | grep -q "$name"; then
+    echo "conflict"
+fi
+
+# Debug
+#set +x
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/explorer/interfaces.d b/cdist/conf/type/__net_bridge_interfaces_d/explorer/interfaces.d
new file mode 100755
index 00000000..215d8426
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/explorer/interfaces.d
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# 2016 Simon Walter (simon at explicit dot technology)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+# Debug
+#exec >&2
+#set -x
+
+if [ -d "/etc/network/interfaces.d/" ]; then
+    echo "true"
+else
+    echo "false"
+fi
+
+# Debug
+#set +x
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/files/dynamic.sh b/cdist/conf/type/__net_bridge_interfaces_d/files/dynamic.sh
new file mode 100755
index 00000000..8f42d897
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/files/dynamic.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+cat << EOF
+auto $bridge
+iface $bridge inet dhcp
+    bridge_stp off
+    bridge_waitport 0
+    bridge_fd 0
+    pre-up brctl addbr $bridge
+    post-down brctl delbr $bridge
+EOF
\ No newline at end of file
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/files/static.sh b/cdist/conf/type/__net_bridge_interfaces_d/files/static.sh
new file mode 100755
index 00000000..4a3d3e60
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/files/static.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+cat << EOF
+auto $bridge
+iface $bridge inet static
+    address $ipaddress
+    netmask $netmask
+    broadcast $broadcast
+    bridge_stp off           # disable Spanning Tree Protocol
+    bridge_waitport 0        # no delay before a port becomes available
+    bridge_fd 0              # no forwarding delay
+    pre-up brctl addbr $bridge
+    post-down brctl delbr $bridge
+EOF
+#    bridge_ports none        # not to be used together with pre-up and post-down
+#    up        ip link set $bridge up # doesn't seem necessary
+#    down      ip link set $bridge down # doesn't seem necessary
\ No newline at end of file
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/gencode-remote b/cdist/conf/type/__net_bridge_interfaces_d/gencode-remote
new file mode 100644
index 00000000..8c7ba707
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/gencode-remote
@@ -0,0 +1,146 @@
+#!/bin/sh
+#
+# 2016 Simon Walter (simon at explicit dot technology)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+if [ -f "$__object/parameter/name" ]; then
+    name="$(cat "$__object/parameter/name")"
+else
+    name="$__object_id"
+fi
+
+if [ -f "$__object/parameter/force" ]; then
+    force="true"
+fi
+
+create()
+{
+    echo "Creating ${name}..." >&2
+    
+    if [ -f "/etc/network/interfaces.d/${name}" ]; then
+        echo "\"/etc/network/interfaces.d/${name}\" exists. Terminating..." >&2
+        exit 1
+    fi
+    
+    if [ -f "/etc/network/interfaces.d/${name}" -a "$force" = "true" ]; then
+        echo "\"/etc/network/interfaces.d/${name}\" exists. Deleteing..." >&2
+        echo "rm /etc/network/interfaces.d/${name}"
+    fi
+
+    echo "touch /etc/network/interfaces.d/${name}"
+    
+    echo "echo \"auto ${name}\" > /etc/network/interfaces.d/${name}"
+    if [ -f "$__object/parameter/ipaddress" ]; then
+        echo "echo \"iface ${name} inet static\" >> /etc/network/interfaces.d/${name}"
+        echo "echo \"    address $(cat "$__object/parameter/ipaddress")\" >> /etc/network/interfaces.d/${name}"
+        if [ -f "$__object/parameter/netmask" ]; then
+            echo "echo \"    netmask $(cat "$__object/parameter/netmask")\" >> /etc/network/interfaces.d/${name}"
+        fi
+        if [ -f "$__object/parameter/broadcast" ]; then
+            echo "echo \"    broadcast $(cat "$__object/parameter/broadcast")\" >> /etc/network/interfaces.d/${name}"
+        fi
+    else
+        echo "echo \"iface ${name} inet dhcp\" >> /etc/network/interfaces.d/${name}"
+    fi
+    echo "echo \"    bridge_stp off\" >> /etc/network/interfaces.d/${name}"
+    echo "echo \"    bridge_waitport 0\" >> /etc/network/interfaces.d/${name}"
+    echo "echo \"    bridge_fd 0\" >> /etc/network/interfaces.d/${name}"
+    echo "echo \"    pre-up brctl addbr ${name}\" >> /etc/network/interfaces.d/${name}"
+    echo "echo \"    post-down brctl delbr ${name}\" >> /etc/network/interfaces.d/${name}"
+    
+    echo "Starting ${name}..." >&2
+    #echo "if ifup lxcbr0 2>&1 | grep -q \"already configured\"; then echo \"darn\"; fi"
+
+    echo "ifup ${name}"
+}
+
+remove()
+{
+    echo "Stopping ${name}..." >&2
+    
+    echo "ifdown ${name}"
+    
+    echo "Removing ${name}..." >&2
+    
+    echo "rm /etc/network/interfaces.d/${name}"
+}
+
+force_remove()
+{
+    echo "Stopping ${name}..." >&2
+
+    echo "ip address flush dev ${name}"
+    echo "ip link set ${name} down"
+    echo "ip link delete ${name}"
+    echo "ifdown ${name} --force"
+    
+    echo "Removing ${name}..." >&2
+    
+    if [ -f "/etc/network/interfaces.d/${name}" ]; then
+        echo "rm /etc/network/interfaces.d/${name}"
+    fi
+}
+
+os=$(cat "$__global/explorer/os")
+case "$os" in
+    debian|ubuntu|devuan)
+        state="$(cat "$__object/parameter/state")"
+        exists="$(cat "$__object/explorer/interface")"
+        
+        if [ "$exists" = "false" -a "$state" = "absent" ]; then
+            exit 0;
+        fi
+        if [ "$exists" = "true" -a "$state" = "present" ]; then
+            if [ "$force" = "true" ]; then
+                remove
+                create
+            else
+                exit 0;
+            fi
+        fi
+        if [ "$exists" = "true" -a "$state" = "absent" ]; then
+            remove
+        fi
+        if [ "$exists" = "false" -a "$state" = "present" ]; then
+            create
+        fi
+        if [ "$exists" = "conflict" -a "$state" = "absent" -a "$force" = "true" ]; then
+            echo "Warning! This interface might not be managed by cdist." >&2
+            echo "\"force\" parameter given." >&2
+            force_remove
+        fi
+        if [ "$exists" = "conflict" -a "$state" = "present" -a "$force" = "true" ]; then
+            echo "Warning! This interface might not be managed by cdist." >&2
+            echo "\"force\" parameter given." >&2
+            force_remove
+            create
+        fi
+        if [ "$exists" = "conflict" -a "$force" != "true" ]; then
+            echo "Warning! This interface might not be managed by cdist." >&2
+            echo "\"force\" parameter given not given. Terminating..." >&2
+            exit 1
+        fi
+    ;;
+
+    *)
+        #Other types should handle other OSes
+        echo "Unsupported OS: ${os}" >&2
+        exit 1
+    ;;
+esac
\ No newline at end of file
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/man.rst b/cdist/conf/type/__net_bridge_interfaces_d/man.rst
new file mode 100644
index 00000000..095103fd
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/man.rst
@@ -0,0 +1,80 @@
+ 
+cdist-type__net_bridge_interface_d(7)
+==================================
+Simon Walter <simon at explicit dot technology>
+
+
+NAME
+----
+cdist-type__net_bridge_interface_d - Manage network bridges with
+/etc/network/interfaces.d/files
+
+
+DESCRIPTION
+-----------
+Add and remove bridges on a Debian derivative. Does not respect any network
+manager or other userspace software.
+
+The files under /etc/network/interfaces.d/ allow one to add configurations 
+without touching the main /etc/network/interfaces file.
+
+You will need: __package bridge-utils --state present
+
+
+REQUIRED PARAMETERS
+-------------------
+None - defaults may not be suitable!
+
+
+OPTIONAL PARAMETERS
+-------------------
+- name
+    If supplied, use the name and not the object id as the bridge name.
+
+- state
+    Either "present" or "absent", defaults to "present"
+
+- ipaddress
+    Set the IP address of the bridge to static. If not set, defaults to DHCP.
+
+- netmask
+    If ipaddress is in CIDR notation, this is not required.
+
+- broadcast
+    If ipaddress is in CIDR notation, this is not required.
+
+- force
+    This type manages bridges with files in /etc/network/interfaces.d/. When
+    an interface does not have a correspoding file in
+    /etc/network/interfaces.d/, it is assumed that it is not managed by cdist.
+    This flag will override the default to exit when no file is found.
+    It will also recreate the interface and file even if both exist. This is a
+    good way to make sure that you've updated to new values.
+
+EXAMPLES
+--------
+
+--------------------------------------------------------------------------------
+::
+# Set up a bridge with a static IP address
+__net_bridge_interface_d br0 --ipaddress 10.1.1.1 --netmask 255.255.255.0 \
+--broadcast 10.1.1.255 --force-update
+
+# Remove bridge "br0"
+__net_bridge_interface_d br0 --state absent
+
+# Making sure that the necessary packages are installed first
+require="__package/bridge-utils" __net_bridge_interface_d br0 \
+--ipaddress 10.1.1.1 --netmask 255.255.255.0 --broadcast 10.1.1.255
+--------------------------------------------------------------------------------
+
+
+SEE ALSO
+--------
+- cdist-type(7)
+
+
+COPYING
+-------
+Copyright \(C) 2016 Simon Walter. Free use of this software is
+granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/man.text b/cdist/conf/type/__net_bridge_interfaces_d/man.text
new file mode 100644
index 00000000..22b51384
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/man.text
@@ -0,0 +1,79 @@
+ 
+cdist-type__net_bridge_interface_d(7)
+==========================
+Simon Walter <simon at explicit dot technology>
+
+
+NAME
+----
+cdist-type__net_bridge_interface_d - Manage network bridges with
+/etc/network/interfaces.d/files
+
+
+DESCRIPTION
+-----------
+Add and remove bridges on a Debian derivative. Does not respect any network
+manager or other userspace software.
+
+The files under /etc/network/interfaces.d/ allow one to add configurations 
+without touching the main /etc/network/interfaces file.
+
+You will need: __package bridge-utils --state present
+
+
+REQUIRED PARAMETERS
+-------------------
+None - defaults may not be suitable!
+
+
+OPTIONAL PARAMETERS
+-------------------
+name::
+    If supplied, use the name and not the object id as the bridge name.
+
+state::
+    Either "present" or "absent", defaults to "present"
+
+ipaddress::
+    Set the IP address of the bridge to static. If not set, defaults to DHCP.
+
+netmask::
+    If ipaddress is in CIDR notation, this is not required.
+
+broadcast::
+    If ipaddress is in CIDR notation, this is not required.
+
+force::
+    This type manages bridges with files in /etc/network/interfaces.d/. When
+    an interface does not have a correspoding file in
+    /etc/network/interfaces.d/, it is assumed that it is not managed by cdist.
+    This flag will override default to exit when no file is found.
+    It will also recreate the interface and file even if both exist. This is a
+    good way to make sure that you've updated to new values.
+
+EXAMPLES
+--------
+
+--------------------------------------------------------------------------------
+# Set up a bridge with a static IP address
+__net_bridge_interface_d br0 --ipaddress 10.1.1.1 --netmask 255.255.255.0 \
+--broadcast 10.1.1.255 --force-update
+
+# Remove bridge "br0"
+__net_bridge_interface_d br0 --state absent
+
+# Making sure that the necessary packages are installed first
+require="__package/bridge-utils" __net_bridge_interface_d br0 \
+--ipaddress 10.1.1.1 --netmask 255.255.255.0 --broadcast 10.1.1.255
+--------------------------------------------------------------------------------
+
+
+SEE ALSO
+--------
+- cdist-type(7)
+
+
+COPYING
+-------
+Copyright \(C) 2016 Simon Walter. Free use of this software is
+granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/manifest b/cdist/conf/type/__net_bridge_interfaces_d/manifest
new file mode 100644
index 00000000..5db17003
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/manifest
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# 2016 Simon Walter (simon at explicit dot technology)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+os=$(cat "$__global/explorer/os")
+case "$os" in
+    debian|ubuntu|devuan)
+        if [ "$(cat "$__object/explorer/interfaces.d")" = "false" ]; then
+            __directory /etc/network/interfaces.d/ --parents --mode 0755
+        fi
+        __line source-interfaces --file /etc/network/interfaces \
+            --line 'source /etc/network/interfaces.d/*' \
+            --state present
+    ;;
+    *)
+        echo "Unsupported OS: ${os}" >&2
+        exit 1
+    ;;
+esac
\ No newline at end of file
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/parameter/boolean b/cdist/conf/type/__net_bridge_interfaces_d/parameter/boolean
new file mode 100644
index 00000000..3802376a
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/parameter/boolean
@@ -0,0 +1 @@
+force 
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/parameter/default/state b/cdist/conf/type/__net_bridge_interfaces_d/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/parameter/default/state
@@ -0,0 +1 @@
+present
diff --git a/cdist/conf/type/__net_bridge_interfaces_d/parameter/optional b/cdist/conf/type/__net_bridge_interfaces_d/parameter/optional
new file mode 100644
index 00000000..1cd6cb28
--- /dev/null
+++ b/cdist/conf/type/__net_bridge_interfaces_d/parameter/optional
@@ -0,0 +1,5 @@
+name
+state
+ipaddress
+netmask
+broadcast
\ No newline at end of file