diff --git a/Makefile b/Makefile index 1653d2c2e..54516ad22 100644 --- a/Makefile +++ b/Makefile @@ -28,13 +28,13 @@ ut: vendor .PHONY: test-containerized ## Run the tests in a container. Useful for CI, Mac dev. -test-containerized: vendor run-kubernetes-master +test-containerized: vendor run-etcd run-kubernetes-master -mkdir -p .go-pkg-cache docker run --rm --privileged --net=host \ -e LOCAL_USER_ID=$(LOCAL_USER_ID) \ -v $(CURDIR)/.go-pkg-cache:/go/pkg/:rw \ -v $(CURDIR):/go/src/github.com/$(PACKAGE_NAME):rw \ - $(CALICO_BUILD) sh -c 'cd /go/src/github.com/$(PACKAGE_NAME) && make WHAT=$(WHAT) ut' + $(CALICO_BUILD) sh -c 'cd /go/src/github.com/$(PACKAGE_NAME) && make WHAT=$(WHAT) SKIP=$(SKIP) ut' ## Run etcd as a container run-etcd: stop-etcd @@ -44,7 +44,7 @@ run-etcd: stop-etcd --advertise-client-urls "http://$(LOCAL_IP_ENV):2379,http://127.0.0.1:2379,http://$(LOCAL_IP_ENV):4001,http://127.0.0.1:4001" \ --listen-client-urls "http://0.0.0.0:2379,http://0.0.0.0:4001" -run-kubernetes-master: stop-kubernetes-master run-etcd +run-kubernetes-master: stop-kubernetes-master # Run the kubelet which will launch the master components in a pod. docker run \ -v /:/rootfs:ro \ diff --git a/git-hooks/pre-commit b/git-hooks/pre-commit index fab7c5257..8686e9208 100755 --- a/git-hooks/pre-commit +++ b/git-hooks/pre-commit @@ -10,7 +10,8 @@ exec 1>&2 changed_files=$(git diff --cached --name-only) changed_go_files=$(git diff --cached --name-only | grep -E '.go$' || true) -all_go_files=$(find -name '*.go' | grep -v /vendor/) + +all_go_files=$(find . -name '*.go' | grep -v /vendor/) copyright_check_failed=false copyright_owner="Tigera, Inc" diff --git a/lib/backend/backend_test.go b/lib/backend/backend_test.go index 53d48cd41..492e2fe62 100644 --- a/lib/backend/backend_test.go +++ b/lib/backend/backend_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,54 +18,49 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/projectcalico/libcalico-go/lib/backend/etcd" + "github.com/projectcalico/libcalico-go/lib/api" + bapi "github.com/projectcalico/libcalico-go/lib/backend/api" "github.com/projectcalico/libcalico-go/lib/backend/model" "github.com/projectcalico/libcalico-go/lib/testutils" ) -// Setting localhost as the etcd endpoint location since that's where `make run-etcd` runs it. -var etcdConfig = &etcd.EtcdConfig{ - EtcdEndpoints: "http://127.0.0.1:2379", -} - -var _ = Describe("Backend tests", func() { - etcdClient, _ := etcd.NewEtcdClient(etcdConfig) - +var _ = testutils.E2eDatastoreDescribe("Backend tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { var ( - block model.KVPair - err error + block model.KVPair + client bapi.Client + err error ) BeforeEach(func() { - testutils.CleanEtcd() - + c := testutils.CreateCleanClient(config) + client = c.Backend block = model.KVPair{ Key: model.BlockKey{ CIDR: testutils.MustParseNetwork("10.0.0.0/26"), }, - Value: model.AllocationBlock{ + Value: &model.AllocationBlock{ CIDR: testutils.MustParseNetwork("10.0.0.0/26"), }, } - _, err = etcdClient.Create(&block) + _, err = client.Create(&block) Expect(err).NotTo(HaveOccurred()) }) Describe("Create", func() { It("persists a new kv pair", func() { - kv, err := etcdClient.Get(block.Key) + kv, err := client.Get(block.Key) Expect(err).NotTo(HaveOccurred()) expectedCIDR := kv.Value.(*model.AllocationBlock).CIDR - persitedCIRD := block.Value.(model.AllocationBlock).CIDR + persitedCIDR := block.Value.(*model.AllocationBlock).CIDR - Expect(expectedCIDR).To(Equal(persitedCIRD)) + Expect(expectedCIDR).To(Equal(persitedCIDR)) }) It("sets revision field", func() { - kv, err := etcdClient.Get(block.Key) + kv, err := client.Get(block.Key) Expect(err).NotTo(HaveOccurred()) Expect(kv.Revision).NotTo(BeNil()) @@ -76,21 +71,21 @@ var _ = Describe("Backend tests", func() { Describe("Update", func() { It("updates a kv pair", func() { - block.Value = model.AllocationBlock{ + block.Value = &model.AllocationBlock{ CIDR: testutils.MustParseNetwork("192.168.0.0/26"), } - kv, err := etcdClient.Update(&block) + kv, err := client.Update(&block) Expect(err).NotTo(HaveOccurred()) - expectedCIDR := kv.Value.(model.AllocationBlock).CIDR - persitedCIRD := block.Value.(model.AllocationBlock).CIDR + expectedCIDR := kv.Value.(*model.AllocationBlock).CIDR + persitedCIDR := block.Value.(*model.AllocationBlock).CIDR - Expect(expectedCIDR).To(Equal(persitedCIRD)) + Expect(expectedCIDR).To(Equal(persitedCIDR)) }) It("sets revision field", func() { - kv, err := etcdClient.Update(&block) + kv, err := client.Update(&block) Expect(err).NotTo(HaveOccurred()) Expect(kv.Revision).NotTo(BeNil()) @@ -98,7 +93,7 @@ var _ = Describe("Backend tests", func() { It("validates revision field", func() { block.Revision = uint64(1000) - _, err := etcdClient.Update(&block) + _, err := client.Update(&block) Expect(err).To(HaveOccurred()) }) @@ -107,17 +102,17 @@ var _ = Describe("Backend tests", func() { Describe("Apply", func() { It("updates a kv pair", func() { - block.Value = model.AllocationBlock{ + block.Value = &model.AllocationBlock{ CIDR: testutils.MustParseNetwork("192.168.0.0/26"), } - kv, err := etcdClient.Apply(&block) + kv, err := client.Apply(&block) Expect(err).NotTo(HaveOccurred()) - expectedCIDR := kv.Value.(model.AllocationBlock).CIDR - persitedCIRD := block.Value.(model.AllocationBlock).CIDR + expectedCIDR := kv.Value.(*model.AllocationBlock).CIDR + persitedCIDR := block.Value.(*model.AllocationBlock).CIDR - Expect(expectedCIDR).To(Equal(persitedCIRD)) + Expect(expectedCIDR).To(Equal(persitedCIDR)) }) It("creates a kv pair", func() { @@ -125,21 +120,21 @@ var _ = Describe("Backend tests", func() { CIDR: testutils.MustParseNetwork("192.168.0.0/26"), } - kv, err := etcdClient.Apply(&block) + kv, err := client.Apply(&block) Expect(err).NotTo(HaveOccurred()) - expectedCIDR := kv.Value.(model.AllocationBlock).CIDR - persitedCIRD := block.Value.(model.AllocationBlock).CIDR + expectedCIDR := kv.Value.(*model.AllocationBlock).CIDR + persitedCIDR := block.Value.(*model.AllocationBlock).CIDR - Expect(expectedCIDR).To(Equal(persitedCIRD)) + Expect(expectedCIDR).To(Equal(persitedCIDR)) }) It("sets revision field", func() { - block.Value = model.AllocationBlock{ + block.Value = &model.AllocationBlock{ CIDR: testutils.MustParseNetwork("192.168.0.0/26"), } - kv, err := etcdClient.Apply(&block) + kv, err := client.Apply(&block) Expect(err).NotTo(HaveOccurred()) Expect(kv.Revision).NotTo(BeNil()) @@ -147,7 +142,7 @@ var _ = Describe("Backend tests", func() { It("validates revision field", func() { block.Revision = uint64(1000) - _, err := etcdClient.Apply(&block) + _, err := client.Apply(&block) Expect(err).NotTo(HaveOccurred()) }) @@ -156,10 +151,10 @@ var _ = Describe("Backend tests", func() { Describe("Delete", func() { It("deletes the kv pair", func() { - err := etcdClient.Delete(&block) + err := client.Delete(&block) Expect(err).NotTo(HaveOccurred()) - _, err = etcdClient.Get(block.Key) + _, err = client.Get(block.Key) Expect(err).To(HaveOccurred()) }) @@ -170,15 +165,13 @@ var _ = Describe("Backend tests", func() { IPVersion: 4, } - bl, err := etcdClient.List(blockListOpt) + It("List", func() { + bl, err := client.List(blockListOpt) + Expect(err).NotTo(HaveOccurred()) - for _, blv := range bl { - It("sets revision field", func() { - Expect(err).NotTo(HaveOccurred()) + for _, blv := range bl { Expect(blv.Revision).NotTo(BeNil()) - }) - } - + } + }) }) - }) diff --git a/lib/client/bgppeer_e2e_test.go b/lib/client/bgppeer_e2e_test.go index 0127fbe13..75adaedbd 100644 --- a/lib/client/bgppeer_e2e_test.go +++ b/lib/client/bgppeer_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -46,19 +46,11 @@ import ( "github.com/projectcalico/libcalico-go/lib/testutils" ) -var _ = Describe("BGPPeer tests", func() { +var _ = testutils.E2eDatastoreDescribe("BGPPeer tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { DescribeTable("BGPPeer e2e tests", func(meta1, meta2 api.BGPPeerMetadata, spec1, spec2 api.BGPPeerSpec) { - - // Erase etcd clean. - testutils.CleanEtcd() - - // Create a new client. - c, err := testutils.NewClient("") - if err != nil { - log.Println("Error creating client:", err) - } + c := testutils.CreateCleanClient(config) By("Updating the BGPPeer before it is created") _, outError := c.BGPPeers().Update(&api.BGPPeer{Metadata: meta1, Spec: spec1}) diff --git a/lib/client/config_e2e_test.go b/lib/client/config_e2e_test.go index 093a3c29a..e125515c9 100644 --- a/lib/client/config_e2e_test.go +++ b/lib/client/config_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,22 +22,19 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/projectcalico/libcalico-go/lib/api" "github.com/projectcalico/libcalico-go/lib/client" "github.com/projectcalico/libcalico-go/lib/net" "github.com/projectcalico/libcalico-go/lib/numorstring" "github.com/projectcalico/libcalico-go/lib/testutils" ) -var _ = Describe("with config option API tests", func() { +var _ = testutils.E2eDatastoreDescribe("with config option API tests", testutils.DatastoreEtcdV2, func(calicoConfig api.CalicoAPIConfig) { var config client.ConfigInterface BeforeEach(func() { - // Erase etcd clean - testutils.CleanEtcd() - - c, err := testutils.NewClient("") - Expect(err).NotTo(HaveOccurred()) + c := testutils.CreateCleanClient(calicoConfig) config = c.Config() }) diff --git a/lib/client/hostendpoint_e2e_test.go b/lib/client/hostendpoint_e2e_test.go index 3c712ee01..25366e888 100644 --- a/lib/client/hostendpoint_e2e_test.go +++ b/lib/client/hostendpoint_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -48,19 +48,12 @@ import ( cnet "github.com/projectcalico/libcalico-go/lib/net" ) -var _ = Describe("HostEndpoint tests", func() { +var _ = testutils.E2eDatastoreDescribe("HostEndpoint tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { DescribeTable("HostEndpoint e2e tests", func(meta1, meta2 api.HostEndpointMetadata, spec1, spec2 api.HostEndpointSpec) { - - // Erase etcd clean. - testutils.CleanEtcd() - // Create a new client. - c, err := testutils.NewClient("") - if err != nil { - log.Println("Error creating client:", err) - } + c := testutils.CreateCleanClient(config) By("Updating the HostEndpoint before it is created") _, outError := c.HostEndpoints().Update(&api.HostEndpoint{Metadata: meta1, Spec: spec1}) diff --git a/lib/client/ipam_test.go b/lib/client/ipam_test.go index f57279627..dde953e76 100644 --- a/lib/client/ipam_test.go +++ b/lib/client/ipam_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -88,21 +88,12 @@ import ( . "github.com/onsi/ginkgo/extensions/table" "github.com/projectcalico/libcalico-go/lib/api" - "github.com/projectcalico/libcalico-go/lib/backend/etcd" "github.com/projectcalico/libcalico-go/lib/client" cerrors "github.com/projectcalico/libcalico-go/lib/errors" cnet "github.com/projectcalico/libcalico-go/lib/net" "github.com/projectcalico/libcalico-go/lib/testutils" ) -// Setting BackendType to etcdv2 which is the only supported backend at the moment. -var etcdType api.DatastoreType = "etcdv2" - -// Setting localhost as the etcd endpoint location since that's where `make run-etcd` runs it. -var etcdConfig = etcd.EtcdConfig{ - EtcdEndpoints: "http://127.0.0.1:2379", -} - type testArgsClaimAff struct { inNet, host string cleanEnv bool @@ -112,7 +103,7 @@ type testArgsClaimAff struct { expError error } -var _ = Describe("IPAM tests", func() { +var _ = testutils.E2eDatastoreDescribe("IPAM tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { // We're assigning one IP which should be from the only ipPool created at the time, second one // should be from the same /26 block since they're both from the same host, then delete @@ -120,8 +111,7 @@ var _ = Describe("IPAM tests", func() { // assigned IP to be from the new ipPool that was created, this is to make sure the assigned IP // doesn't come from the old affinedBlock even after the ipPool was deleted. Describe("IPAM AutoAssign from the default pool then delete the pool and assign again", func() { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) ic := setupIPAMClient(c, true) host := "host-A" @@ -204,8 +194,7 @@ var _ = Describe("IPAM tests", func() { }) Describe("IPAM AutoAssign from any pool", func() { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) ic := setupIPAMClient(c, true) testutils.CreateNewIPPool(*c, "10.0.0.0/24", false, false, true) @@ -236,8 +225,7 @@ var _ = Describe("IPAM tests", func() { }) Describe("IPAM AutoAssign from different pools", func() { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) ic := setupIPAMClient(c, true) host := "host-A" @@ -336,8 +324,7 @@ var _ = Describe("IPAM tests", func() { }) Describe("IPAM AutoAssign from different pools - multi", func() { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) ic := setupIPAMClient(c, true) host := "host-A" @@ -388,7 +375,7 @@ var _ = Describe("IPAM tests", func() { DescribeTable("AutoAssign: requested IPs vs returned IPs", func(host string, cleanEnv bool, pool []string, usePool string, inv4, inv6, expv4, expv6 int, expError error) { - outv4, outv6, outError := testIPAMAutoAssign(inv4, inv6, host, cleanEnv, pool, usePool) + outv4, outv6, outError := testIPAMAutoAssign(inv4, inv6, host, cleanEnv, pool, usePool, config) Expect(outv4).To(Equal(expv4)) Expect(outv6).To(Equal(expv6)) if expError != nil { @@ -421,7 +408,7 @@ var _ = Describe("IPAM tests", func() { DescribeTable("AssignIP: requested IP vs returned error", func(inIP net.IP, host string, cleanEnv bool, pool []string, expError error) { - outError := testIPAMAssignIP(inIP, host, pool, cleanEnv) + outError := testIPAMAssignIP(inIP, host, pool, cleanEnv, config) if expError != nil { Expect(outError).To(HaveOccurred()) Expect(outError).To(Equal(expError)) @@ -447,7 +434,7 @@ var _ = Describe("IPAM tests", func() { DescribeTable("ReleaseIPs: requested IPs to be released vs actual unallocated IPs", func(inIP net.IP, cleanEnv bool, pool []string, assignIP net.IP, autoAssignNumIPv4 int, expUnallocatedIPs []cnet.IP, expError error) { - unallocatedIPs, outError := testIPAMReleaseIPs(inIP, pool, cleanEnv, assignIP, autoAssignNumIPv4) + unallocatedIPs, outError := testIPAMReleaseIPs(inIP, pool, cleanEnv, assignIP, autoAssignNumIPv4, config) // Expect returned slice of unallocatedIPs to be equal to expected expUnallocatedIPs. Expect(unallocatedIPs).To(Equal(expUnallocatedIPs)) @@ -486,11 +473,11 @@ var _ = Describe("IPAM tests", func() { DescribeTable("ClaimAffinity: claim IPNet vs actual number of blocks claimed", func(args testArgsClaimAff) { inIPNet := testutils.MustParseNetwork(args.inNet) - c, _ := testutils.NewClient("") + c := testutils.CreateClient(config) // Wipe clean etcd, create a new client, and pools when cleanEnv flag is true. if args.cleanEnv { - testutils.CleanEtcd() + testutils.CleanDatastore(config) for _, v := range args.pool { testutils.CreateNewIPPool(*c, v, false, false, true) } @@ -540,17 +527,16 @@ var _ = Describe("IPAM tests", func() { // testIPAMReleaseIPs takes an IP, slice of string with IP pools to setup, cleanEnv flag means setup a new environment. // assignIP is if you want to assign a single IP before releasing an IP, and AutoAssign is to assign IPs in bulk before releasing any. -func testIPAMReleaseIPs(inIP net.IP, poolSubnet []string, cleanEnv bool, assignIP net.IP, autoAssignNumIPv4 int) ([]cnet.IP, error) { +func testIPAMReleaseIPs(inIP net.IP, poolSubnet []string, cleanEnv bool, assignIP net.IP, autoAssignNumIPv4 int, config api.CalicoAPIConfig) ([]cnet.IP, error) { inIPs := []cnet.IP{cnet.IP{inIP}} if cleanEnv { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) for _, v := range poolSubnet { testutils.CreateNewIPPool(*c, v, false, false, true) } } - c, _ := testutils.NewClient("") + c := testutils.CreateClient(config) ic := setupIPAMClient(c, cleanEnv) if len(assignIP) != 0 { @@ -584,19 +570,18 @@ func testIPAMReleaseIPs(inIP net.IP, poolSubnet []string, cleanEnv bool, assignI // testIPAMAssignIP takes an IPv4 or IPv6 IP with a hostname and pool name and calls AssignIP. // Set cleanEnv to true to wipe clean etcd and reset IPAM config. -func testIPAMAssignIP(inIP net.IP, host string, poolSubnet []string, cleanEnv bool) error { +func testIPAMAssignIP(inIP net.IP, host string, poolSubnet []string, cleanEnv bool, config api.CalicoAPIConfig) error { args := client.AssignIPArgs{ IP: cnet.IP{inIP}, Hostname: host, } if cleanEnv { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) for _, v := range poolSubnet { testutils.CreateNewIPPool(*c, v, false, false, true) } } - c, _ := testutils.NewClient("") + c := testutils.CreateClient(config) ic := setupIPAMClient(c, cleanEnv) outErr := ic.AssignIP(args) @@ -608,7 +593,7 @@ func testIPAMAssignIP(inIP net.IP, host string, poolSubnet []string, cleanEnv bo // testIPAMAutoAssign takes number of requested IPv4 and IPv6, and hostname, and setus up/cleans up client and etcd, // then it calls AutoAssign (function under test) and returns the number of returned IPv4 and IPv6 addresses and returned error. -func testIPAMAutoAssign(inv4, inv6 int, host string, cleanEnv bool, poolSubnet []string, usePool string) (int, int, error) { +func testIPAMAutoAssign(inv4, inv6 int, host string, cleanEnv bool, poolSubnet []string, usePool string, config api.CalicoAPIConfig) (int, int, error) { fromPool := testutils.MustParseNetwork(usePool) args := client.AutoAssignArgs{ Num4: inv4, @@ -618,13 +603,12 @@ func testIPAMAutoAssign(inv4, inv6 int, host string, cleanEnv bool, poolSubnet [ } if cleanEnv { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) for _, v := range poolSubnet { testutils.CreateNewIPPool(*c, v, false, false, true) } } - c, _ := testutils.NewClient("") + c := testutils.CreateClient(config) ic := setupIPAMClient(c, cleanEnv) v4, v6, outErr := ic.AutoAssign(args) diff --git a/lib/client/ippool_e2e_test.go b/lib/client/ippool_e2e_test.go index 058945495..1e799c16c 100644 --- a/lib/client/ippool_e2e_test.go +++ b/lib/client/ippool_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -44,22 +44,16 @@ import ( . "github.com/onsi/gomega" "github.com/projectcalico/libcalico-go/lib/api" - "github.com/projectcalico/libcalico-go/lib/client" cerrors "github.com/projectcalico/libcalico-go/lib/errors" "github.com/projectcalico/libcalico-go/lib/ipip" "github.com/projectcalico/libcalico-go/lib/testutils" ) -var _ = testutils.E2eDatastoreDescribe("IPPool e2e tests", testutils.DatastoreEtcdV2 |testutils.DatastoreK8s, func(apiConfig api.CalicoAPIConfig) { +var _ = testutils.E2eDatastoreDescribe("IPPool e2e tests", testutils.DatastoreAll, func(apiConfig api.CalicoAPIConfig) { DescribeTable("IPPool e2e tests", func(meta1, meta2 api.IPPoolMetadata, spec1, spec2 api.IPPoolSpec) { - - // Create a new client and clean the datastore - c, err := client.New(apiConfig) - if err != nil { - log.Println("Error creating client:", err) - } + c := testutils.CreateClient(apiConfig) testutils.CleanIPPools(c) By("Updating the pool before it is created") @@ -265,7 +259,7 @@ var _ = testutils.E2eDatastoreDescribe("IPPool e2e tests", testutils.DatastoreEt ) Describe("Checking operations perform data validation", func() { - c, _ := client.New(apiConfig) + c := testutils.CreateClient(apiConfig) testutils.CleanIPPools(c) var err error diff --git a/lib/client/node_e2e_test.go b/lib/client/node_e2e_test.go index 82c3642de..939aeab3b 100644 --- a/lib/client/node_e2e_test.go +++ b/lib/client/node_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -29,7 +29,6 @@ package client_test import ( "errors" - "log" "reflect" . "github.com/onsi/ginkgo" @@ -42,25 +41,18 @@ import ( "github.com/projectcalico/libcalico-go/lib/testutils" ) -var _ = Describe("Node tests", func() { +var _ = testutils.E2eDatastoreDescribe("Node tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { cidrv4 := testutils.MustParseCIDR("1.2.3.5/24") cidrv6 := testutils.MustParseCIDR("aa::bb00:0001/104") asn := numorstring.ASNumber(12345) DescribeTable("Node e2e tests", func(meta1, meta2 api.NodeMetadata, spec1, spec2 api.NodeSpec) { - // Erase etcd clean. - testutils.CleanEtcd() - - // Create a new client. - c, err := testutils.NewClient("") - if err != nil { - log.Println("Error creating client:", err) - } + c := testutils.CreateCleanClient(config) // Updating non-existent node1 should return an error By("Updating the node before it is created") - _, err = c.Nodes().Update(&api.Node{Metadata: meta1, Spec: spec1}) + _, err := c.Nodes().Update(&api.Node{Metadata: meta1, Spec: spec1}) Expect(err.Error()).To(Equal(errors.New("resource does not exist: Node(name=node1)").Error())) // Create a new node1 with meta1 and spec1. This should not error. @@ -78,7 +70,8 @@ var _ = Describe("Node tests", func() { _, err = c.Nodes().Apply(&api.Node{Metadata: meta2, Spec: spec2}) Expect(err).NotTo(HaveOccurred()) - testutils.DumpEtcd() + err = testutils.DumpDatastore(config) + Expect(err).NotTo(HaveOccurred()) // Get node1. This should not error, spec should match spec1. By("Getting node1 and comparing with spec1") @@ -192,8 +185,7 @@ var _ = Describe("Node tests", func() { ) Describe("Checking global config is set only once", func() { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) var guidOrig string var guidNew string var set bool @@ -238,8 +230,7 @@ var _ = Describe("Node tests", func() { }) Describe("Checking delete/get/list operations perform data validation", func() { - testutils.CleanEtcd() - c, _ := testutils.NewClient("") + c := testutils.CreateCleanClient(config) var err error valErrorType := reflect.TypeOf(cerrors.ErrorValidation{}) diff --git a/lib/client/policy_e2e_test.go b/lib/client/policy_e2e_test.go index 9429547da..b81ad73ef 100644 --- a/lib/client/policy_e2e_test.go +++ b/lib/client/policy_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -63,19 +63,11 @@ var policySpec2 = api.PolicySpec{ DoNotTrack: true, } -var _ = Describe("Policy tests", func() { +var _ = testutils.E2eDatastoreDescribe("Policy tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { DescribeTable("Policy e2e tests", func(meta1, meta2 api.PolicyMetadata, spec1, spec2 api.PolicySpec) { - - // Erase etcd clean. - testutils.CleanEtcd() - - // Create a new client. - c, err := testutils.NewClient("") - if err != nil { - log.Println("Error creating client:", err) - } + c := testutils.CreateCleanClient(config) By("Updating the policy before it is created") _, outError := c.Policies().Update(&api.Policy{Metadata: meta1, Spec: spec1}) diff --git a/lib/client/profile_e2e_test.go b/lib/client/profile_e2e_test.go index e54ab538f..27472a361 100644 --- a/lib/client/profile_e2e_test.go +++ b/lib/client/profile_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -57,19 +57,12 @@ var profileSpec2 = api.ProfileSpec{ } var tags2 = []string{"profile2-tag1", "profile2-tag2"} -var _ = Describe("Profile tests", func() { +var _ = testutils.E2eDatastoreDescribe("Profile tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { DescribeTable("Profile e2e tests", func(meta1, meta2 api.ProfileMetadata, spec1, spec2 api.ProfileSpec) { + c := testutils.CreateCleanClient(config) - // Erase etcd clean. - testutils.CleanEtcd() - - // Create a new client. - c, err := testutils.NewClient("") - if err != nil { - log.Println("Error creating client:", err) - } By("Updating the profile before it is created") _, outError := c.Profiles().Update(&api.Profile{Metadata: meta1, Spec: spec1}) diff --git a/lib/client/workloadendpoint_e2e_test.go b/lib/client/workloadendpoint_e2e_test.go index 4558ecc87..9c1b93b17 100644 --- a/lib/client/workloadendpoint_e2e_test.go +++ b/lib/client/workloadendpoint_e2e_test.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ import ( cnet "github.com/projectcalico/libcalico-go/lib/net" ) -var _ = Describe("WorkloadEndpoint tests", func() { +var _ = testutils.E2eDatastoreDescribe("WorkloadEndpoint tests", testutils.DatastoreEtcdV2, func(config api.CalicoAPIConfig) { cidr1 := testutils.MustParseNetwork("10.0.0.0/32") cidr2 := testutils.MustParseNetwork("20.0.0.0/32") cidr3 := testutils.MustParseNetwork("192.168.0.0/32") @@ -60,15 +60,8 @@ var _ = Describe("WorkloadEndpoint tests", func() { DescribeTable("WorkloadEndpoint e2e tests", func(meta1, meta2 api.WorkloadEndpointMetadata, spec1, spec2 api.WorkloadEndpointSpec) { + c := testutils.CreateCleanClient(config) - // Erase etcd clean. - testutils.CleanEtcd() - - // Create a new client. - c, err := testutils.NewClient("") - if err != nil { - log.Println("Error creating client:", err) - } By("Updating the WorkloadEndpoint before it is created") _, outError := c.WorkloadEndpoints().Update(&api.WorkloadEndpoint{Metadata: meta1, Spec: spec1}) diff --git a/lib/testutils/cleanEtcd.go b/lib/testutils/cleanEtcd.go deleted file mode 100644 index 2811ab11b..000000000 --- a/lib/testutils/cleanEtcd.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. - -// 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 testutils - -import ( - "context" - "log" - "os/exec" - - etcdclient "github.com/coreos/etcd/client" -) - -var kapi etcdclient.KeysAPI - -func init() { - cfg := etcdclient.Config{Endpoints: []string{"http://127.0.0.1:2379"}} - c, _ := etcdclient.New(cfg) - kapi = etcdclient.NewKeysAPI(c) -} - -// CleanEtcd is a utility function to wipe clean "/calico" recursively from etcd. -func CleanEtcd() { - _, err := kapi.Delete(context.Background(), "/calico", &etcdclient.DeleteOptions{Dir: true, Recursive: true}) - if err != nil { - log.Println(err) - } -} - -// DumpEtcd prints out a recursive dump of the contents of etcd. -func DumpEtcd() { - output, err := exec.Command("curl", "http://127.0.0.1:2379/v2/keys?recursive=true").Output() - if err != nil { - log.Println(err) - } else { - log.Println(string(output)) - } -} diff --git a/lib/testutils/client.go b/lib/testutils/client.go index 6918b0917..f87a8f56d 100644 --- a/lib/testutils/client.go +++ b/lib/testutils/client.go @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Tigera, Inc. All rights reserved. +// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,35 +15,21 @@ package testutils import ( - "log" "net" - "os" + log "github.com/Sirupsen/logrus" + etcdclient "github.com/coreos/etcd/client" "github.com/projectcalico/libcalico-go/lib/api" "github.com/projectcalico/libcalico-go/lib/api/unversioned" "github.com/projectcalico/libcalico-go/lib/client" cnet "github.com/projectcalico/libcalico-go/lib/net" -) - -// NewClient is a util function to create a new default client. -// When passed empty string, it loads the default config instead from a config file. -func NewClient(cf string) (*client.Client, error) { - if _, err := os.Stat(cf); err != nil { - cf = "" - } - - cfg, err := client.LoadClientConfig(cf) - if err != nil { - return nil, err - } - c, err := client.New(*cfg) - if err != nil { - return nil, err - } - - return c, err -} + "errors" + "fmt" + "golang.org/x/net/context" + "os/exec" + "strings" +) // CreateNewIPPool takes a client.Client with a poolSubnet CIDR (in "192.168.1.0/24" format) with // ipip, natOut, and ipam bools for the pool to be setup and creates a new pool. @@ -77,10 +63,18 @@ func CreateNewIPPool(c client.Client, poolSubnet string, ipip, natOut, ipam bool if err != nil { log.Printf("Error creating pool: %s\n", err) } +} + +func CreateClient(config api.CalicoAPIConfig) *client.Client { + c, err := client.New(config) + + if err != nil { + panic(err) + } + return c } -// CleanIPPools removes all IP pool configuration from the datastore. func CleanIPPools(c *client.Client) { if pools, err := c.IPPools().List(api.IPPoolMetadata{}); err == nil { for _, pool := range pools.Items { @@ -88,7 +82,70 @@ func CleanIPPools(c *client.Client) { panic(err) } } - } else { + } +} + +func CleanDatastore(config api.CalicoAPIConfig) { + var err error + + log.Println(fmt.Sprintf("Cleaning datastore: %v", config.Spec.DatastoreType)) + + switch config.Spec.DatastoreType { + case api.EtcdV2: + cfg := etcdclient.Config{ + Endpoints: []string{config.Spec.EtcdScheme + "://" + config.Spec.EtcdAuthority}, + } + if config.Spec.EtcdEndpoints != "" { + cfg = etcdclient.Config{ + Endpoints: strings.Split(config.Spec.EtcdEndpoints, ","), + } + } + if c, err := etcdclient.New(cfg); c != nil { + kapi := etcdclient.NewKeysAPI(c) + _, err = kapi.Delete(context.Background(), "/calico", &etcdclient.DeleteOptions{Dir: true, Recursive: true}) + } else { + log.Errorf("Can't create etcd backend %v", err) + } + default: + err = errors.New(fmt.Sprintf("Unknown datastore type: %v", config.Spec.DatastoreType)) + } + + if err != nil { panic(err) } } + +// CreateCleanClient is a utility function to wipe clean "/calico" recursively from backend +// and to return confugred client to it +func CreateCleanClient(config api.CalicoAPIConfig) *client.Client { + CleanDatastore(config) + + return CreateClient(config) +} + +// DumpDatastore prints out a recursive dump of the contents of backend. +func DumpDatastore(config api.CalicoAPIConfig) error { + var output []byte + var err error + + log.Println(fmt.Sprintf("Dumping datastore: %v", config.Spec.DatastoreType)) + + switch config.Spec.DatastoreType { + case api.EtcdV2: + output, err = exec.Command("curl", "http://127.0.0.1:2379/v2/keys?recursive=true").Output() + default: + err = errors.New(fmt.Sprintf("Unknown datastore type: %v", config.Spec.DatastoreType)) + } + + if err != nil { + if ee, ok := err.(*exec.ExitError); ok { + log.Printf("Dump backend return error: %s, %v", string(ee.Stderr), *ee.ProcessState) + } else { + log.Println(err) + } + } else { + log.Println(string(output)) + } + + return err +} diff --git a/lib/testutils/e2e_describe.go b/lib/testutils/e2e_describe.go index 2727541c0..b2146ae55 100644 --- a/lib/testutils/e2e_describe.go +++ b/lib/testutils/e2e_describe.go @@ -1,3 +1,16 @@ +// Copyright (c) 2017 Tigera, Inc. All rights reserved. + +// 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 testutils import ( @@ -10,9 +23,13 @@ import ( . "github.com/onsi/ginkgo" ) +type DatastoreType int + const ( - DatastoreEtcdV2 = 1 << iota + DatastoreEtcdV2 DatastoreType = 1 << iota DatastoreK8s + + DatastoreAll = DatastoreEtcdV2 | DatastoreK8s ) // E2eDatastoreDescribe is a replacement for ginkgo.Describe which invokes Describe @@ -23,9 +40,8 @@ const ( // // The *datastores* parameter is a bit-wise OR of the required datastore drivers // that will be tested. -func E2eDatastoreDescribe(description string, datastores int, body func(config api.CalicoAPIConfig)) bool { - - if datastores & DatastoreEtcdV2 != 0 { +func E2eDatastoreDescribe(description string, datastores DatastoreType, body func(config api.CalicoAPIConfig)) bool { + if datastores&DatastoreEtcdV2 != 0 { Describe(fmt.Sprintf("%s (etcdv2 backend)", description), func() { body(api.CalicoAPIConfig{ @@ -39,7 +55,7 @@ func E2eDatastoreDescribe(description string, datastores int, body func(config a }) } - if datastores & DatastoreK8s != 0 { + if datastores&DatastoreK8s != 0 { Describe(fmt.Sprintf("%s (kubernetes backend)", description), func() { body(api.CalicoAPIConfig{ diff --git a/run-uts b/run-uts index b93092730..3ebbbb376 100755 --- a/run-uts +++ b/run-uts @@ -2,9 +2,17 @@ set -e +if [ -z $SKIP ] +then + SKIP="vendor" +else + SKIP="vendor,$SKIP" +fi + # Run tests in random order find tests recursively (-r). -echo $WHAT -ginkgo -cover -r --skipPackage vendor $WHAT +echo WHAT: $WHAT +echo SKIP: $SKIP +ginkgo -cover -r --skipPackage $SKIP $WHAT echo echo '+==============+'