Add static CNI plugin
This changes to add 'static' CNI plugin, which provides to assign IPv4/v6 address statically from given config file. See README.md for the details.
This commit is contained in:
142
plugins/ipam/static/main.go
Normal file
142
plugins/ipam/static/main.go
Normal file
@ -0,0 +1,142 @@
|
||||
// Copyright 2018 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 main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/containernetworking/cni/pkg/skel"
|
||||
"github.com/containernetworking/cni/pkg/types"
|
||||
"github.com/containernetworking/cni/pkg/types/current"
|
||||
"github.com/containernetworking/cni/pkg/version"
|
||||
|
||||
types020 "github.com/containernetworking/cni/pkg/types/020"
|
||||
)
|
||||
|
||||
// The top-level network config - IPAM plugins are passed the full configuration
|
||||
// of the calling plugin, not just the IPAM section.
|
||||
type Net struct {
|
||||
Name string `json:"name"`
|
||||
CNIVersion string `json:"cniVersion"`
|
||||
IPAM *IPAMConfig `json:"ipam"`
|
||||
}
|
||||
|
||||
type IPAMConfig struct {
|
||||
Name string
|
||||
Type string `json:"type"`
|
||||
Routes []*types.Route `json:"routes"`
|
||||
Addresses []Address `json:"addresses"`
|
||||
DNS types.DNS `json:"dns"`
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
AddressStr string `json:"address"`
|
||||
Gateway net.IP `json:"gateway,omitempty"`
|
||||
Address net.IPNet
|
||||
Version string
|
||||
}
|
||||
|
||||
func main() {
|
||||
skel.PluginMain(cmdAdd, cmdDel, version.All)
|
||||
}
|
||||
|
||||
// canonicalizeIP makes sure a provided ip is in standard form
|
||||
func canonicalizeIP(ip *net.IP) error {
|
||||
if ip.To4() != nil {
|
||||
*ip = ip.To4()
|
||||
return nil
|
||||
} else if ip.To16() != nil {
|
||||
*ip = ip.To16()
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("IP %s not v4 nor v6", *ip)
|
||||
}
|
||||
|
||||
// NewIPAMConfig creates a NetworkConfig from the given network name.
|
||||
func LoadIPAMConfig(bytes []byte, envArgs string) (*IPAMConfig, string, error) {
|
||||
n := Net{}
|
||||
if err := json.Unmarshal(bytes, &n); err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if n.IPAM == nil {
|
||||
return nil, "", fmt.Errorf("IPAM config missing 'ipam' key")
|
||||
}
|
||||
|
||||
// Validate all ranges
|
||||
numV4 := 0
|
||||
numV6 := 0
|
||||
for i := range n.IPAM.Addresses {
|
||||
ip, addr, err := net.ParseCIDR(n.IPAM.Addresses[i].AddressStr)
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("invalid CIDR %s: %s", n.IPAM.Addresses[i].AddressStr, err)
|
||||
}
|
||||
n.IPAM.Addresses[i].Address = *addr
|
||||
n.IPAM.Addresses[i].Address.IP = ip
|
||||
|
||||
if err := canonicalizeIP(&n.IPAM.Addresses[i].Address.IP); err != nil {
|
||||
return nil, "", fmt.Errorf("invalid address %d: %s", i, err)
|
||||
}
|
||||
|
||||
if n.IPAM.Addresses[i].Address.IP.To4() != nil {
|
||||
n.IPAM.Addresses[i].Version = "4"
|
||||
numV4++
|
||||
} else {
|
||||
n.IPAM.Addresses[i].Version = "6"
|
||||
numV6++
|
||||
}
|
||||
}
|
||||
|
||||
// CNI spec 0.2.0 and below supported only one v4 and v6 address
|
||||
if numV4 > 1 || numV6 > 1 {
|
||||
for _, v := range types020.SupportedVersions {
|
||||
if n.CNIVersion == v {
|
||||
return nil, "", fmt.Errorf("CNI version %v does not support more than 1 address per family", n.CNIVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy net name into IPAM so not to drag Net struct around
|
||||
n.IPAM.Name = n.Name
|
||||
|
||||
return n.IPAM, n.CNIVersion, nil
|
||||
}
|
||||
|
||||
func cmdAdd(args *skel.CmdArgs) error {
|
||||
ipamConf, confVersion, err := LoadIPAMConfig(args.StdinData, args.Args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := ¤t.Result{}
|
||||
result.DNS = ipamConf.DNS
|
||||
result.Routes = ipamConf.Routes
|
||||
for _, v := range ipamConf.Addresses {
|
||||
result.IPs = append(result.IPs, ¤t.IPConfig{
|
||||
Version: v.Version,
|
||||
Address: v.Address,
|
||||
Gateway: v.Gateway})
|
||||
}
|
||||
|
||||
result.Routes = ipamConf.Routes
|
||||
return types.PrintResult(result, confVersion)
|
||||
}
|
||||
|
||||
func cmdDel(args *skel.CmdArgs) error {
|
||||
// Nothing required because of no resource allocation in static plugin.
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user