testing: adds basic test of backwards compatibility

This commit is contained in:
Gabe Rosenhouse 2016-10-02 21:43:51 -07:00
parent a29fc24f11
commit 51b51a0182
4 changed files with 254 additions and 0 deletions

View File

@ -0,0 +1,53 @@
// 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 libcni_test
import (
"fmt"
"os"
"path/filepath"
"github.com/containernetworking/cni/libcni"
"github.com/containernetworking/cni/pkg/version/legacy_examples"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Backwards compatibility", func() {
It("correctly handles the response from a legacy plugin", func() {
example := legacy_examples.V010
pluginPath, err := example.Build()
Expect(err).NotTo(HaveOccurred())
netConf, err := libcni.ConfFromBytes([]byte(fmt.Sprintf(
`{ "name": "old-thing", "type": "%s" }`, example.Name)))
Expect(err).NotTo(HaveOccurred())
runtimeConf := &libcni.RuntimeConf{
ContainerID: "some-container-id",
NetNS: "/some/netns/path",
IfName: "eth0",
}
cniConfig := &libcni.CNIConfig{Path: []string{filepath.Dir(pluginPath)}}
result, err := cniConfig.AddNetwork(netConf, runtimeConf)
Expect(err).NotTo(HaveOccurred())
Expect(result).To(Equal(legacy_examples.ExpectedResult))
Expect(os.RemoveAll(pluginPath)).To(Succeed())
})
})

View File

@ -0,0 +1,138 @@
// 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 contains sample code from prior versions of
// the CNI library, for use in verifying backwards compatibility.
package legacy_examples
import (
"io/ioutil"
"net"
"path/filepath"
"sync"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/version/testhelpers"
)
// An Example is a Git reference to the CNI repo and a Golang CNI plugin that
// builds against that version of the repo.
//
// By convention, every Example plugin returns an ADD result that is
// semantically equivalent to the ExpectedResult.
type Example struct {
Name string
CNIRepoGitRef string
PluginSource string
}
var buildDir = ""
var buildDirLock sync.Mutex
func ensureBuildDirExists() error {
buildDirLock.Lock()
defer buildDirLock.Unlock()
if buildDir != "" {
return nil
}
var err error
buildDir, err = ioutil.TempDir("", "cni-example-plugins")
return err
}
// Build builds the example, returning the path to the binary
func (e Example) Build() (string, error) {
if err := ensureBuildDirExists(); err != nil {
return "", err
}
outBinPath := filepath.Join(buildDir, e.Name)
if err := testhelpers.BuildAt([]byte(e.PluginSource), e.CNIRepoGitRef, outBinPath); err != nil {
return "", err
}
return outBinPath, nil
}
// V010 acts like a CNI plugin from the v0.1.0 era
var V010 = Example{
Name: "example_v010",
CNIRepoGitRef: "2c482f4",
PluginSource: `package main
import (
"net"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
)
var result = types.Result{
IP4: &types.IPConfig{
IP: net.IPNet{
IP: net.ParseIP("10.1.2.3"),
Mask: net.CIDRMask(24, 32),
},
Gateway: net.ParseIP("10.1.2.1"),
Routes: []types.Route{
types.Route{
Dst: net.IPNet{
IP: net.ParseIP("0.0.0.0"),
Mask: net.CIDRMask(0, 32),
},
GW: net.ParseIP("10.1.0.1"),
},
},
},
DNS: types.DNS{
Nameservers: []string{"8.8.8.8"},
Domain: "example.com",
},
}
func c(_ *skel.CmdArgs) error { result.Print(); return nil }
func main() { skel.PluginMain(c, c) }
`,
}
// ExpectedResult is the current representation of the plugin result
// that is expected from each of the examples.
//
// As we change the CNI spec, the Result type and this value may change.
// The text of the example plugins should not.
var ExpectedResult = &types.Result{
IP4: &types.IPConfig{
IP: net.IPNet{
IP: net.ParseIP("10.1.2.3"),
Mask: net.CIDRMask(24, 32),
},
Gateway: net.ParseIP("10.1.2.1"),
Routes: []types.Route{
types.Route{
Dst: net.IPNet{
IP: net.ParseIP("0.0.0.0"),
Mask: net.CIDRMask(0, 32),
},
GW: net.ParseIP("10.1.0.1"),
},
},
},
DNS: types.DNS{
Nameservers: []string{"8.8.8.8"},
Domain: "example.com",
},
}

View File

@ -0,0 +1,27 @@
// 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_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestLegacyExamples(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "LegacyExamples Suite")
}

View File

@ -0,0 +1,36 @@
// 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_test
import (
"os"
"path/filepath"
"github.com/containernetworking/cni/pkg/version/legacy_examples"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("The v0.1.0 Example", func() {
It("builds ok", func() {
example := legacy_examples.V010
pluginPath, err := example.Build()
Expect(err).NotTo(HaveOccurred())
Expect(filepath.Base(pluginPath)).To(Equal(example.Name))
Expect(os.RemoveAll(pluginPath)).To(Succeed())
})
})