
Using a new ".configlist" file format that allows specifying a list of CNI network configurations to run, add new libcni helper functions to call each plugin in the list, injecting the overall name, CNI version, and previous plugin's Result structure into the configuration of the next plugin.
171 lines
4.3 KiB
Go
171 lines
4.3 KiB
Go
// Copyright 2015 CNI authors
|
|
//
|
|
// 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.
|
|
|
|
package libcni
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/containernetworking/cni/pkg/invoke"
|
|
"github.com/containernetworking/cni/pkg/types"
|
|
"github.com/containernetworking/cni/pkg/version"
|
|
)
|
|
|
|
type RuntimeConf struct {
|
|
ContainerID string
|
|
NetNS string
|
|
IfName string
|
|
Args [][2]string
|
|
}
|
|
|
|
type NetworkConfig struct {
|
|
Network *types.NetConf
|
|
Bytes []byte
|
|
}
|
|
|
|
type NetworkConfigList struct {
|
|
Name string
|
|
CNIVersion string
|
|
Plugins []*NetworkConfig
|
|
Bytes []byte
|
|
}
|
|
|
|
type CNI interface {
|
|
AddNetworkList(net *NetworkConfigList, rt *RuntimeConf) (*types.Result, error)
|
|
DelNetworkList(net *NetworkConfigList, rt *RuntimeConf) error
|
|
|
|
AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error)
|
|
DelNetwork(net *NetworkConfig, rt *RuntimeConf) error
|
|
}
|
|
|
|
type CNIConfig struct {
|
|
Path []string
|
|
}
|
|
|
|
// CNIConfig implements the CNI interface
|
|
var _ CNI = &CNIConfig{}
|
|
|
|
func buildOneConfig(list *NetworkConfigList, orig *NetworkConfig, prevResult *types.Result) (*NetworkConfig, error) {
|
|
var err error
|
|
|
|
// Ensure every config uses the same name and version
|
|
orig, err = InjectConf(orig, "name", list.Name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
orig, err = InjectConf(orig, "cniVersion", list.CNIVersion)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Add previous plugin result
|
|
if prevResult != nil {
|
|
orig, err = InjectConf(orig, "prevResult", prevResult)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return orig, nil
|
|
}
|
|
|
|
// AddNetworkList executes a sequence of plugins with the ADD command
|
|
func (c *CNIConfig) AddNetworkList(list *NetworkConfigList, rt *RuntimeConf) (*types.Result, error) {
|
|
var prevResult *types.Result
|
|
for _, net := range list.Plugins {
|
|
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
newConf, err := buildOneConfig(list, net, prevResult)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
prevResult, err = invoke.ExecPluginWithResult(pluginPath, newConf.Bytes, c.args("ADD", rt))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return prevResult, nil
|
|
}
|
|
|
|
// DelNetworkList executes a sequence of plugins with the DEL command
|
|
func (c *CNIConfig) DelNetworkList(list *NetworkConfigList, rt *RuntimeConf) error {
|
|
for i := len(list.Plugins) - 1; i >= 0; i-- {
|
|
net := list.Plugins[i]
|
|
|
|
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newConf, err := buildOneConfig(list, net, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := invoke.ExecPluginWithoutResult(pluginPath, newConf.Bytes, c.args("DEL", rt)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddNetwork executes the plugin with the ADD command
|
|
func (c *CNIConfig) AddNetwork(net *NetworkConfig, rt *RuntimeConf) (*types.Result, error) {
|
|
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return invoke.ExecPluginWithResult(pluginPath, net.Bytes, c.args("ADD", rt))
|
|
}
|
|
|
|
// DelNetwork executes the plugin with the DEL command
|
|
func (c *CNIConfig) DelNetwork(net *NetworkConfig, rt *RuntimeConf) error {
|
|
pluginPath, err := invoke.FindInPath(net.Network.Type, c.Path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return invoke.ExecPluginWithoutResult(pluginPath, net.Bytes, c.args("DEL", rt))
|
|
}
|
|
|
|
// GetVersionInfo reports which versions of the CNI spec are supported by
|
|
// the given plugin.
|
|
func (c *CNIConfig) GetVersionInfo(pluginType string) (version.PluginInfo, error) {
|
|
pluginPath, err := invoke.FindInPath(pluginType, c.Path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return invoke.GetVersionInfo(pluginPath)
|
|
}
|
|
|
|
// =====
|
|
func (c *CNIConfig) args(action string, rt *RuntimeConf) *invoke.Args {
|
|
return &invoke.Args{
|
|
Command: action,
|
|
ContainerID: rt.ContainerID,
|
|
NetNS: rt.NetNS,
|
|
PluginArgs: rt.Args,
|
|
IfName: rt.IfName,
|
|
Path: strings.Join(c.Path, ":"),
|
|
}
|
|
}
|