gator
IMPORTANT: gator is currently unstable and is not ready for production
release.
gator
is a templating delegator (get it?) CNI meta plugin. It allows a CNI
plugin's configuration to be dynamically generated at runtime based on the
result from previous plugins in the chain.
It takes the name of the downstream plugin, configuration for the downstream
plugin, and a JSON merge patch to be applied to that configuration.
The patch can include golang template
syntax which will be executed based on the full input from stdin before the
patch is applied to the downstream configuration.
Once the patch has been applied to the downstream configuration, it will be
merged with stdin (gator's plugin configuration will be removed) and the the
downstream plugin will be called with the same environment and the new,
templated, patched stdin... just as if it had been called originally, but now
you can dynamically configure plugins based on previous results!
Functions from sprig are included and
available in gator
.
Examples
Say you want to use the
route-override CNI plugin to
add a route to each pod after it has received an IP configuration from flannel.
Unfortunately, route-override
doesn't look at the gateway set by the previous
result, and you must set the gateway for the route in the plugin's
configuration. With gator
, you can template the configuration you want to
calculate at runtime.
You want to end up with this config at runtime, which adds a route for the
service subnet 10.96.0.0/16
through the gateway defined in the first IP
listed in the PrevResult from flannel:
{
"type": "route-override",
"addroutes": [
{
"dst": "10.96.0.0/16",
"gw": "<GATEWAY IP FROM FLANNEL>"
}
]
}
You're getting something like this from stdin:
{
...
"prevResult": {
"cniVersion": "0.3.1",
"interfaces": [...]
"ips": [
{
"version": "4",
"interface": 2,
"address": "10.244.1.42/24",
"gateway": "10.244.1.1"
}
]
}
}
You would start with a base configuration (which in this case will be empty),
then merge in the JSON patch that results from executing the following
template:
{
"addroutes": [
{
"dst": "10.96.0.0/16",
"gw": "{{with $n := index .prevResult.ips 0}}{{$n.gateway}}{{end}}"
}
]
}
Now you have the plugin name, the plugin's base configuration, and a template
for an RFC7396 JSON merge patch to apply to that configuration.
Put it all together and you get the following gator
configuration:
{
"type": "gator",
"plugin": "route-override",
"patch": "{\"addroutes\": [{\"dst\": \"10.96.0.0/16\", \"gw\": \"{{with $n := index .prevResult.ips 0}}{{$n.gateway}}{{end}}\"}]}"
}
One more example: You want to set every container interface to promiscuous mode
with the debug plugin (this is from the debug
repo), but
you also want to save the debug logs to separate files based on the date.
Here's the gator
config:
{
"type": "gator",
"plugin": "debug",
"config": {
"addHooks": [
[ "sh", "-c", "ip link set $CNI_IFNAME promisc on" ]
]
},
"patch": "{\"cniOutput\": \"{{printf \"/tmp/cni-output-%s.log\" (now | date \"2006-01-02\")}}\"}"
}
The patch
looks like this without all the JSON escapes:
{"cniOutput": "{{printf "/tmp/cni-output-%s.log" (now | date "2006-01-02")}}"}
At runtime, the debug
plugin will be called with the following configuration
(along with PrevResult
, etc):
{
...
"addHooks": [
[ "sh", "-c", "ip link set $CNI_IFNAME promisc on" ]
],
"cniOutput": "/tmp/cni-output-2023-10-03.log",
"type": "debug"
}
Have fun!