diff --git a/version/legacy_examples/example_runtime.go b/version/legacy_examples/example_runtime.go new file mode 100644 index 00000000..a461981f --- /dev/null +++ b/version/legacy_examples/example_runtime.go @@ -0,0 +1,167 @@ +// Copyright 2016 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 legacy_examples + +// An ExampleRuntime is a small program that uses libcni to invoke a network plugin. +// It should call ADD and DELETE, verifying all intermediate steps +// and data structures. +type ExampleRuntime struct { + Example + NetConfs []string // The network configuration names to pass +} + +// NetConfs are various versioned network configuration files. Examples should +// specify which version they expect +var NetConfs = map[string]string{ + "unversioned": `{ + "name": "default", + "type": "ptp", + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24" + } +}`, + "0.1.0": `{ + "cniVersion": "0.1.0", + "name": "default", + "type": "ptp", + "ipam": { + "type": "host-local", + "subnet": "10.1.2.0/24" + } +}`, +} + +// V010_Runtime creates a simple ptp network configuration, then +// executes libcni against the currently-built plugins. +var V010_Runtime = ExampleRuntime{ + NetConfs: []string{"unversioned", "0.1.0"}, + Example: Example{ + Name: "example_invoker_v010", + CNIRepoGitRef: "c0d34c69", //version with ns.Do + PluginSource: `package main + +import ( + "fmt" + "io/ioutil" + "net" + "os" + + "github.com/containernetworking/cni/pkg/ns" + "github.com/containernetworking/cni/libcni" +) + +func main(){ + code := exec() + os.Exit(code) +} + +func exec() int { + confBytes, err := ioutil.ReadAll(os.Stdin) + if err != nil { + fmt.Printf("could not read netconfig from stdin: %+v", err) + return 1 + } + + netConf, err := libcni.ConfFromBytes(confBytes) + if err != nil { + fmt.Printf("could not parse netconfig: %+v", err) + return 1 + } + fmt.Printf("Parsed network configuration: %+v\n", netConf.Network) + + if len(os.Args) == 1 { + fmt.Printf("Expect CNI plugin paths in argv") + return 1 + } + + targetNs, err := ns.NewNS() + if err != nil { + fmt.Printf("Could not create ns: %+v", err) + return 1 + } + defer targetNs.Close() + + ifName := "eth0" + + runtimeConf := &libcni.RuntimeConf{ + ContainerID: "some-container-id", + NetNS: targetNs.Path(), + IfName: ifName, + } + + cniConfig := &libcni.CNIConfig{Path: os.Args[1:]} + + result, err := cniConfig.AddNetwork(netConf, runtimeConf) + if err != nil { + fmt.Printf("AddNetwork failed: %+v", err) + return 2 + } + fmt.Printf("AddNetwork result: %+v", result) + + expectedIP := result.IP4.IP + + err = targetNs.Do(func(ns.NetNS) error { + netif, err := net.InterfaceByName(ifName) + if err != nil { + return fmt.Errorf("could not retrieve interface: %v", err) + } + + addrs, err := netif.Addrs() + if err != nil { + return fmt.Errorf("could not retrieve addresses, %+v", err) + } + + found := false + for _, addr := range addrs { + if addr.String() == expectedIP.String() { + found = true + break + } + } + + if !found { + return fmt.Errorf("Far-side link did not have expected address %s", expectedIP) + } + return nil + }) + if err != nil { + fmt.Println(err) + return 4 + } + + err = cniConfig.DelNetwork(netConf, runtimeConf) + if err != nil { + fmt.Printf("DelNetwork failed: %v", err) + return 5 + } + + err = targetNs.Do(func(ns.NetNS) error { + _, err := net.InterfaceByName(ifName) + if err == nil { + return fmt.Errorf("interface was not deleted") + } + return nil + }) + if err != nil { + fmt.Println(err) + return 6 + } + + return 0 +} +`, + }, +}