Initial commit

This commit is contained in:
Joel Elkins 2022-07-14 13:52:28 -05:00
commit 0049fb818c
3 changed files with 252 additions and 0 deletions

237
cmd/ccl/ccl.go Normal file
View File

@ -0,0 +1,237 @@
package main
import (
"fmt"
"log"
"os"
"strings"
"github.com/emirpasic/gods/sets/hashset"
toml "github.com/pelletier/go-toml"
"golang.org/x/exp/slices"
)
const (
CONFIG_FILE = "/etc/containerdefs.toml"
)
type Network struct {
Name string
DNS []string
IPv6 bool `default:true`
IPv4Address string `toml:"ipv4_address"`
IPv6Address string `toml:"ipv6_address"`
}
type Container struct {
Category string
Name string
Image string
Hostname string
Command string
Arguments string
Networks []Network
createCommands []string
upCommands []string
}
type command string
const (
CREATE command = "create"
START command = "start"
)
var (
networks *[]Network
containers *[]Container
categories *[]string
commands = map[command]func(*Container){
CREATE: PrintCreate,
START: PrintStart,
}
)
// A parsing convenience
type parse struct {
Networks []Network
Containers []Container
}
func Categories() []string {
if categories != nil {
return *categories
}
categories = &[]string{"all"}
gs := hashset.New()
for _, c := range *containers {
gs.Add(c.Category)
}
for _, c := range gs.Values() {
*categories = append(*categories, c.(string))
}
return *categories
}
func Union(ids []string) (conts []Container) {
h := hashset.New()
for _, id := range ids {
for _, c := range *containers {
if id == "all" || c.Name == id || c.Category == id {
h.Add(c.Name)
}
}
}
for _, c := range h.Values() {
name := c.(string)
match := slices.IndexFunc(*containers, func(c Container) bool { return c.Name == name })
conts = append(conts, (*containers)[match])
}
return
}
func Init(configFile string) {
f, err := os.ReadFile(configFile)
if err != nil {
return
}
p := parse{}
err = toml.Unmarshal(f, &p)
if err != nil {
return
}
containers, networks = &p.Containers, &p.Networks
for i, c := range p.Containers {
p.Containers[i].createCommands, p.Containers[i].upCommands = c.MakeCommands()
}
}
func netToArgs(c *Network) string {
net := "%s%s%s"
ipv4 := ""
if c.IPv4Address != "" {
ipv4 = fmt.Sprintf(" --ip %s", c.IPv4Address)
}
ipv6 := ""
if c.IPv6Address != "" {
ipv6 = fmt.Sprintf(" --ip6 %s", c.IPv6Address)
}
net = fmt.Sprintf(net, c.Name, ipv4, ipv6)
return net
}
func NetworkDefaults(name string) (net *Network) {
for _, n := range *networks {
if n.Name == name {
net = &n
}
}
return
}
func ClearRACommands(c *Container) *[]string {
cmds := []string{}
for _, n := range c.Networks {
nw := NetworkDefaults(n.Name)
if !nw.IPv6 {
cmds = append(cmds, fmt.Sprintf("ip netns exec %s sysctl -w net.ipv6.conf.default.accept_ra=0", c.Name))
cmds = append(cmds, fmt.Sprintf("ip netns exec %s sysctl -w net.ipv6.conf.all.accept_ra=0", c.Name))
// TODO: iterate through invoices and set the accpet_ra parameter to zero for each
return &cmds
}
}
return &cmds
}
func (c *Container) MakeCommands() ([]string, []string) {
cmd := []string{
"podman create --name %s%s%s%s%s%s",
}
hostname := ""
if c.Hostname != "" {
hostname = fmt.Sprintf(" --hostname %s", c.Hostname)
}
net := ""
dns := ""
if len(c.Networks) > 0 {
net = " --net " + netToArgs(&c.Networks[0])
if len(c.Networks[0].DNS) > 0 {
dns = " --dns " + strings.Join(c.Networks[0].DNS, ",")
} else if len(NetworkDefaults(c.Networks[0].Name).DNS) > 0 {
dns = " --dns " + strings.Join(NetworkDefaults(c.Networks[0].Name).DNS, ",")
}
}
args := ""
if c.Arguments != "" {
args = " " + c.Arguments
}
entry := ""
if c.Command != "" {
entry = " " + c.Command
}
cmd[0] = fmt.Sprintf(cmd[0], c.Name, hostname, net, dns, args, entry)
if len(c.Networks) > 1 {
for i := 1; i < len(c.Networks); i++ {
n := c.Networks[i]
s := fmt.Sprintf("podman network connect %s %s", c.Name, netToArgs(&n))
cmd = append(cmd, s)
}
}
up := []string{}
if len(c.Networks) > 0 {
if !c.Networks[0].IPv6 || !NetworkDefaults(c.Networks[0].Name).IPv6 {
for _, k := range *ClearRACommands(c) {
up = append(up, k)
}
up = append(up, fmt.Sprintf("ip netns exec %s ip -6 address flush scope global", c.Name))
up = append(up, fmt.Sprintf("ip netns exec %s ip -6 route flush proto ra", c.Name))
}
}
return cmd, up
}
func main() {
Init(CONFIG_FILE)
containers := Union([]string{"all"})
if len(os.Args) > 1 {
containers = Union(os.Args[1:])
}
for _, c := range containers {
commands[CREATE](&c)
// commands[START](&c)
}
log.Printf("CATEGORIES: %v", Categories())
}
func PrintCreate(ct *Container) {
for _, c := range ct.createCommands {
fmt.Println(c)
}
}
func (c *Container) Pid() int {
return 0
}
func (c *Container) AssureNetNS() {
// stat, _ := file.Stat("/var/run/netns")
// if !stat.IsDir() {
// os.MkdirAll("/var/run/netns", os.ModePerm)
// }
}
func PrintStart(ct *Container) {
start_commands := []string{
"podman start " + ct.Name,
"sleep 1",
}
for _, c := range ct.upCommands {
start_commands = append(start_commands, c)
}
for _, c := range start_commands {
fmt.Println(c)
}
}

9
go.mod Normal file
View File

@ -0,0 +1,9 @@
module gitea.elkins.co/Networking/ccl
go 1.18
require (
github.com/emirpasic/gods v1.18.1
github.com/pelletier/go-toml v1.9.5
golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75
)

6
go.sum Normal file
View File

@ -0,0 +1,6 @@
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75 h1:x03zeu7B2B11ySp+daztnwM5oBJ/8wGUSqrwcw9L0RA=
golang.org/x/exp v0.0.0-20220713135740-79cabaa25d75/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=