Skip to content

Commit

Permalink
Add tunnel ip allocator syncer, and add wireguard ipam allocation type
Browse files Browse the repository at this point in the history
  • Loading branch information
Rob Brockbank committed May 29, 2020
1 parent efdcb3c commit fb67c6d
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 14 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ checkouts
/report/*.xml
/release
Makefile.common*
*.test
15 changes: 8 additions & 7 deletions lib/backend/model/block.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016-2019 Tigera, Inc. All rights reserved.
// Copyright (c) 2016-2020 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.
Expand Down Expand Up @@ -29,12 +29,13 @@ import (

const (
// Common attributes which may be set on allocations by clients.
IPAMBlockAttributePod = "pod"
IPAMBlockAttributeNamespace = "namespace"
IPAMBlockAttributeNode = "node"
IPAMBlockAttributeType = "type"
IPAMBlockAttributeTypeIPIP = "ipipTunnelAddress"
IPAMBlockAttributeTypeVXLAN = "vxlanTunnelAddress"
IPAMBlockAttributePod = "pod"
IPAMBlockAttributeNamespace = "namespace"
IPAMBlockAttributeNode = "node"
IPAMBlockAttributeType = "type"
IPAMBlockAttributeTypeIPIP = "ipipTunnelAddress"
IPAMBlockAttributeTypeVXLAN = "vxlanTunnelAddress"
IPAMBlockAttributeTypeWireguard = "wireguardTunnelAddress"
)

var (
Expand Down
23 changes: 23 additions & 0 deletions lib/backend/syncersv1/tunnelipsyncer/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) 2020 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 tunnelipsyncer

/*
tunnelipsyncer implements an api.Syncer for consumers of configuration used to determine tunnel IP addresses.
The primary use case here is for the allocate-tunnel-ip script used within calico-node.
This implementation uses the watchersyncer.
*/
39 changes: 39 additions & 0 deletions lib/backend/syncersv1/tunnelipsyncer/tunnelipsyncer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2020 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 tunnelipsyncer

import (
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
"github.com/projectcalico/libcalico-go/lib/backend/api"
"github.com/projectcalico/libcalico-go/lib/backend/model"
"github.com/projectcalico/libcalico-go/lib/backend/syncersv1/updateprocessors"
"github.com/projectcalico/libcalico-go/lib/backend/watchersyncer"
)

// New creates a new tunnel IP allocation v1 Syncer. An optional node name may be supplied. If set, the syncer only
// watches the specified node rather than all nodes.
func New(client api.Client, callbacks api.SyncerCallbacks, node string) api.Syncer {
resourceTypes := []watchersyncer.ResourceType{
{
ListInterface: model.ResourceListOptions{Kind: apiv3.KindIPPool},
UpdateProcessor: updateprocessors.NewIPPoolUpdateProcessor(),
},
{
ListInterface: model.ResourceListOptions{Kind: apiv3.KindNode, Name: node},
},
}

return watchersyncer.New(client, resourceTypes, callbacks)
}
135 changes: 135 additions & 0 deletions lib/backend/syncersv1/tunnelipsyncer/tunnelipsyncer_e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// Copyright (c) 2020 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 tunnelipsyncer_test

import (
"context"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/projectcalico/libcalico-go/lib/apiconfig"
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
"github.com/projectcalico/libcalico-go/lib/backend"
"github.com/projectcalico/libcalico-go/lib/backend/api"
"github.com/projectcalico/libcalico-go/lib/backend/encap"
"github.com/projectcalico/libcalico-go/lib/backend/model"
"github.com/projectcalico/libcalico-go/lib/backend/syncersv1/tunnelipsyncer"
"github.com/projectcalico/libcalico-go/lib/clientv3"
"github.com/projectcalico/libcalico-go/lib/net"
"github.com/projectcalico/libcalico-go/lib/options"
"github.com/projectcalico/libcalico-go/lib/testutils"
)

// These tests validate that the various resources that the BGP watches are
// handled correctly by the syncer. We don't validate in detail the behavior of
// each of update handlers that are invoked, since these are tested more thoroughly
// elsewhere.
var _ = testutils.E2eDatastoreDescribe("Tunnel IP allocation syncer tests", testutils.DatastoreAll, func(config apiconfig.CalicoAPIConfig) {

ctx := context.Background()

Describe("Tunnel IP allocation syncer functionality", func() {
It("should receive the synced after return all current data", func() {
// Create a v3 client to drive data changes (luckily because this is the _test module,
// we don't get circular imports.
c, err := clientv3.New(config)
Expect(err).NotTo(HaveOccurred())

// Create the backend client to obtain a syncer interface.
be, err := backend.NewClient(config)
Expect(err).NotTo(HaveOccurred())
be.Clean()

// Create a SyncerTester to receive the tunnel IP allocation syncer callback events and to allow us
// to assert state.
syncTester := testutils.NewSyncerTester()
syncer := tunnelipsyncer.New(be, syncTester, "127.0.0.1")
syncer.Start()
expectedCacheSize := 0

By("Checking status is updated to sync'd at start of day")
syncTester.ExpectStatusUpdate(api.WaitForDatastore)
syncTester.ExpectCacheSize(expectedCacheSize)
syncTester.ExpectStatusUpdate(api.ResyncInProgress)
if config.Spec.DatastoreType == apiconfig.Kubernetes {
expectedCacheSize += 1
}
syncTester.ExpectCacheSize(expectedCacheSize)
syncTester.ExpectStatusUpdate(api.InSync)
syncTester.ExpectCacheSize(expectedCacheSize)

// For Kubernetes test one entry already in the cache for the node.
if config.Spec.DatastoreType == apiconfig.Kubernetes {
syncTester.ExpectPath("/calico/resources/v3/projectcalico.org/nodes/127.0.0.1")
}

By("Creating an IPPool")
poolCIDR := "192.124.0.0/21"
poolCIDRNet := net.MustParseCIDR(poolCIDR)
pool, err := c.IPPools().Create(
ctx,
&apiv3.IPPool{
ObjectMeta: metav1.ObjectMeta{Name: "mypool"},
Spec: apiv3.IPPoolSpec{
CIDR: poolCIDR,
IPIPMode: apiv3.IPIPModeCrossSubnet,
NATOutgoing: true,
},
},
options.SetOptions{},
)
Expect(err).NotTo(HaveOccurred())
// The pool will add as single entry ( +1 )
poolKeyV1 := model.IPPoolKey{CIDR: net.MustParseCIDR("192.124.0.0/21")}
expectedCacheSize += 1
syncTester.ExpectCacheSize(expectedCacheSize)
syncTester.ExpectData(model.KVPair{
Key: poolKeyV1,
Value: &model.IPPool{
CIDR: poolCIDRNet,
IPIPInterface: "tunl0",
IPIPMode: encap.CrossSubnet,
Masquerade: true,
IPAM: true,
Disabled: false,
},
Revision: pool.ResourceVersion,
})

By("Starting a new syncer and verifying that all current entries are returned before sync status")
// We need to create a new syncTester and syncer.
current := syncTester.GetCacheEntries()
syncTester = testutils.NewSyncerTester()
syncer = tunnelipsyncer.New(be, syncTester, "127.0.0.1")
syncer.Start()

// Verify the data is the same as the data from the previous cache. We got the cache in the previous
// step.
syncTester.ExpectStatusUpdate(api.WaitForDatastore)
syncTester.ExpectStatusUpdate(api.ResyncInProgress)
syncTester.ExpectCacheSize(expectedCacheSize)
for _, e := range current {
if config.Spec.DatastoreType == apiconfig.Kubernetes {
// Don't check revisions for K8s since the node data gets updated constantly.
e.Revision = ""
}
syncTester.ExpectData(e)
}
syncTester.ExpectStatusUpdate(api.InSync)
})
})
})
33 changes: 33 additions & 0 deletions lib/backend/syncersv1/tunnelipsyncer/tunnelipsyncer_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2020 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 tunnelipsyncer

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"

"github.com/onsi/ginkgo/reporters"

"github.com/projectcalico/libcalico-go/lib/testutils"
)

func TestClient(t *testing.T) {
testutils.HookLogrusForGinkgo()
RegisterFailHandler(Fail)
junitReporter := reporters.NewJUnitReporter("../../../../report/tunnelipsyncer_suite.xml")
RunSpecsWithDefaultAndCustomReporters(t, "Tunnel IP syncer test suite", []Reporter{junitReporter})
}
15 changes: 8 additions & 7 deletions lib/ipam/ipam.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2016-2019 Tigera, Inc. All rights reserved.
// Copyright (c) 2016-2020 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.
Expand Down Expand Up @@ -39,12 +39,13 @@ const (

// Common attributes which may be set on allocations by clients. Moved to the model package so they can be used
// by the AllocationBlock code too.
AttributePod = model.IPAMBlockAttributePod
AttributeNamespace = model.IPAMBlockAttributeNamespace
AttributeNode = model.IPAMBlockAttributeNode
AttributeType = model.IPAMBlockAttributeType
AttributeTypeIPIP = model.IPAMBlockAttributeTypeIPIP
AttributeTypeVXLAN = model.IPAMBlockAttributeTypeVXLAN
AttributePod = model.IPAMBlockAttributePod
AttributeNamespace = model.IPAMBlockAttributeNamespace
AttributeNode = model.IPAMBlockAttributeNode
AttributeType = model.IPAMBlockAttributeType
AttributeTypeIPIP = model.IPAMBlockAttributeTypeIPIP
AttributeTypeVXLAN = model.IPAMBlockAttributeTypeVXLAN
AttributeTypeWireguard = model.IPAMBlockAttributeTypeWireguard
)

var (
Expand Down

0 comments on commit fb67c6d

Please sign in to comment.