Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add per-node and global BGP config to KDD #468

Merged
merged 1 commit into from
Jul 7, 2017

Conversation

robbrockbank
Copy link
Contributor

@robbrockbank robbrockbank commented Jul 3, 2017

Adds per-node and global BGP config to KDD. Most importantly the global BGP config option to enabled/disable the node mesh is present.

This PR includes some changes to the client and etcd code too:
Reason:

  • etcd exposes the BGP config parameters in an odd way:
  • capitalization differs from the Felix "standard"
  • the node-2-node mesh is a json blob rather than a single boolean value.

Changes:

  • Hide the etcd oddities in the compat driver - so on the KVPair interface we'll just define camelcase options AsNumber NodeMeshEnabled (this is what Felix uses, should we? ... or should I change AsNumber to ASNumber?) parameters.
  • compat module will convert these to the original as_num and node_mesh.
  • In addition, the NodeMeshEnabled will be exposed in the KVPair as a boolean string - in compat we'll convert this to the json blob.

This allows the KVPair interface to expose sensible config names and values with consistent format as used by Felix. I think this is only used by etcd so I'm wondering if we should just be more explicit about that and do all conversion in that module.

Converting KVPairs / Keys in the compat module is a bit of a PITA because error responses from the etcd driver will have the modified Key as the Identifier -- so that means we have to jump through hoops to adjust the Identifier in the error back to the original Key. Nothing terrible, but a side effect of adding the identifier inforamation in the backend when it should really be handed by the client. Anyhoo.

@robbrockbank robbrockbank changed the title Add per-node and global BGP config to KDD [DO NOT REVIEW] Add per-node and global BGP config to KDD Jul 3, 2017
@robbrockbank robbrockbank changed the title [DO NOT REVIEW] Add per-node and global BGP config to KDD Add per-node and global BGP config to KDD Jul 3, 2017
@robbrockbank robbrockbank changed the title Add per-node and global BGP config to KDD [WIP] Add per-node and global BGP config to KDD Jul 5, 2017
@robbrockbank robbrockbank force-pushed the bgp-config-types branch 2 times, most recently from 04b0ba3 to 2704959 Compare July 5, 2017 20:55
@robbrockbank robbrockbank changed the title [WIP] Add per-node and global BGP config to KDD Add per-node and global BGP config to KDD Jul 5, 2017
@robbrockbank robbrockbank force-pushed the bgp-config-types branch 3 times, most recently from 86856cb to 8b8987c Compare July 6, 2017 18:39
Copy link
Member

@caseydavenport caseydavenport left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, first round done!

}

func (_ GlobalBgpConfigConverter) NameToKey(name string) (model.Key, error) {
return nil, fmt.Errorf("Mapping of Name to Key is not possible for global config")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably say global bgp config

Name: "network_v6",
},
},
}

return primary, optional
}

// toDatastoreGlobalBGPConfigKey modifies the Global BGP Config key to the one required by
// the datastore (for back-compatibility).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you update the comments here so it says "for back-compatibility with what is expected in the etcdv2 datastore driver" or similar?

That would make it more clear why we need to do this.

func toDatastoreGlobalBGPConfig(d model.KVPair) *model.KVPair {
// Copy the KVPair, so we aren't modifying the original.
k := d.Key.(model.GlobalBGPConfigKey)
d.Key = toDatastoreGlobalBGPConfigKey(k)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, so we're copying it so that toDatastoreGlobalBGPConfigKey doesn't modify the original, but then we're overwriting the original in the same line?

Are we just keeping this so that we can use k.Name below? If so, why don't we either:

  • Switch on the "datastore" representation of the name, OR
  • Just save off the same and use that in the switch below.

Or, am I misunderstanding?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh the Copy KVPair comment is bogus. It's already copied by virtue of us not passing in a pointer.

@@ -397,15 +415,19 @@ func (c *KubeClient) Delete(d *model.KVPair) error {
log.Debugf("Performing 'Delete' for %+v", d)
switch d.Key.(type) {
case model.GlobalConfigKey:
return c.globalConfigClient.Delete(d)
return c.globalFelixConfigClient.Delete(d)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, so this is nice because it makes it clear that it's for felix, however the model is called GlobalConfig, so it might be nice to keep this in-sync with what the model is called.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah don't mind either way. Makes it a little less verbose and easy to rename.

restClient: r,
name: GlobalBgpConfigTPRName,
resource: GlobalBgpConfigResourceName,
description: "Calico Global Configuration",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calico Global BGP Configuration?

}

func (_ GlobalBgpConfigConverter) ListInterfaceToKey(l model.ListInterface) model.Key {
pl := l.(model.GlobalBGPConfigListOptions)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is pl short for? Could we just do name := l.(model.GlobalBGPConfigListOptions).Name?


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

var (
typeGlobalBGPConfig = rawStringType
typeHostBGPConfig = rawStringType
matchGlobalBGPConfig = regexp.MustCompile("^/?calico/bgp/v1/global/(.+)$")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, what are the changes to this file for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We didn't previously support list operations for config. I was adding that in, although for the life of me I can't remember why.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I think it was for "no surprises" later on -- was thinking ahead about moving away from confd and using a common set of library function for both backends to configure bird. Strictly not required for this PR though.

@@ -89,6 +89,89 @@ var _ = testutils.E2eDatastoreDescribe("with config option API tests", testutils
Expect(cs).To(Equal(client.ConfigLocationGlobal))
})

It("should handle node IP in IP tunnel address", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, so this fails with KDD because KDD gets the tunnel address from the Node.PodCIDR field, and we needed to move it to an etcd-only set of tests, yeah? Just making sure I understand.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup - and that is why I didn't just add node-specific Felix config in this PR. It's not required for KDD routing, and needs a little more thought regarding interactions with this field.

Expect(ip).To(BeNil())
})

It("should handle per-node felix config", func() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should work now in KDD right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope - as with the above, I haven't added per-node Felix config to KDD. It isn't required for KDD routing.

I think we should add it soon, and then we should be feature complete (in terms of what can be configured through calicoctl).

return nil
}

switch e := err.(type) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, why do we need to create a new var e and then re-assign to err?

Couldn't we just do err.Identifier= id for each of these?

Copy link
Contributor Author

@robbrockbank robbrockbank Jul 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we cannot.

It's a golang thang:

Firstly err is of type "error" so you can't reference the Identifier field. Secondly, when we do e := err.(type) we actually create a copy of the exception struct - so you are modifying a copy of rather than the original.

Copy link
Member

@caseydavenport caseydavenport left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of minor nits left, but otherwise feel free to merge.

go func() { done <- c.globalConfigClient.EnsureInitialized() }()
go func() { done <- c.globalBgpConfigClient.EnsureInitialized() }()

// Wait for all 4 registrations to complete and keep track of the last
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is out-of-date

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants