Skip to content

Commit c3112c7

Browse files
authored
Release 2.1.0 (#74)
Bug Fixes: - Proper tenant selection for on-demand created L4LB resources whose backends are from the nested subnet. New Features: - Added option to set the default Tenant for L4LB resources. It's useful for situations when there is a need to choose from which tenant the L4LB frontend IP Address should be selected.
1 parent c5bab8c commit c3112c7

File tree

18 files changed

+132
-99
lines changed

18 files changed

+132
-99
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ KUSTOMIZE = $(shell pwd)/bin/kustomize
8888
kustomize: ## Download kustomize locally if necessary.
8989
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/[email protected])
9090

91-
# go-get-tool will 'go get' any package $2 and install it to $1.
91+
# go-get-tool will 'go install' any package $2 and install it to $1.
9292
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
9393
define go-get-tool
9494
@[ -f $(1) ] || { \
@@ -97,7 +97,7 @@ TMP_DIR=$$(mktemp -d) ;\
9797
cd $$TMP_DIR ;\
9898
go mod init tmp ;\
9999
echo "Downloading $(2)" ;\
100-
GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\
100+
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
101101
rm -rf $$TMP_DIR ;\
102102
}
103103
endef

calicowatcher/main.go

+53-34
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828

2929
"github.com/go-logr/logr"
3030
"github.com/netrisai/netris-operator/api/v1alpha1"
31-
k8sv1alpha1 "github.com/netrisai/netris-operator/api/v1alpha1"
3231
"github.com/netrisai/netris-operator/calicowatcher/calico"
3332
"github.com/netrisai/netris-operator/configloader"
3433
"github.com/netrisai/netris-operator/netrisstorage"
@@ -70,8 +69,8 @@ type Watcher struct {
7069

7170
type data struct {
7271
deleteMode bool
73-
generatedBGPs []*k8sv1alpha1.BGP
74-
bgpList []*k8sv1alpha1.BGP
72+
generatedBGPs []*v1alpha1.BGP
73+
bgpList []*v1alpha1.BGP
7574
bgpConfs []*calico.BGPConfiguration
7675

7776
nodesMap map[string]*nodeIP
@@ -98,7 +97,7 @@ type Options struct {
9897
// NewWatcher is the main initialization function.
9998
func NewWatcher(nStorage *netrisstorage.Storage, mgr manager.Manager, options Options) (*Watcher, error) {
10099
if nStorage == nil {
101-
return nil, fmt.Errorf("Please provide NStorage")
100+
return nil, fmt.Errorf("please provide NStorage")
102101
}
103102

104103
watcher := &Watcher{
@@ -170,7 +169,7 @@ func (w *Watcher) Start() {
170169
case <-w.stop:
171170
ticker.Stop()
172171
close(w.stop)
173-
break
172+
return
174173
}
175174
}
176175
}
@@ -347,7 +346,7 @@ func (w *Watcher) deleteProcess() error {
347346
return err
348347
}
349348

350-
w.data.generatedBGPs = []*k8sv1alpha1.BGP{}
349+
w.data.generatedBGPs = []*v1alpha1.BGP{}
351350

352351
debugLogger.Info("Geting BGPs from k8s", "deleteMode", w.data.deleteMode)
353352
bgps, err := w.getBGPs()
@@ -431,22 +430,29 @@ func (w *Watcher) updateBGPConfMesh(enabled bool) error {
431430
}
432431

433432
func (w *Watcher) generateBGPs() error {
434-
generatedBGPs := []*k8sv1alpha1.BGP{}
433+
generatedBGPs := []*v1alpha1.BGP{}
435434

436435
nameReg, _ := regexp.Compile("[^a-z0-9.]+")
437436
for name, node := range w.data.nodesMap {
438437
asn, err := strconv.Atoi(node.ASN)
439438
if err != nil {
440439
return err
441440
}
442-
PrefixListInboundList := []string{fmt.Sprintf("permit %s/%d", node.IPIP, w.data.blockSize)}
441+
442+
// Get the network address using node IP
443+
_, ipipNetAddr, err := net.ParseCIDR(fmt.Sprintf("%s/%d", node.IPIP, w.data.blockSize))
444+
if err != nil {
445+
return fmt.Errorf("node ip: %s", err)
446+
}
447+
448+
PrefixListInboundList := []string{fmt.Sprintf("permit %s", ipipNetAddr.String())}
443449
for _, cidr := range w.data.serviceCIDRs {
444450
PrefixListInboundList = append(PrefixListInboundList, fmt.Sprintf("permit %s le %d", cidr, 32))
445451
}
446452

447453
name := fmt.Sprintf("%s-%s", name, strings.Split(node.IP, "/")[0])
448454

449-
bgp := &k8sv1alpha1.BGP{
455+
bgp := &v1alpha1.BGP{
450456
ObjectMeta: metav1.ObjectMeta{
451457
Name: nameReg.ReplaceAllString(name, "-"),
452458
Namespace: "default",
@@ -455,7 +461,7 @@ func (w *Watcher) generateBGPs() error {
455461
Kind: "BGP",
456462
APIVersion: "k8s.netris.ai/v1alpha1",
457463
},
458-
Spec: k8sv1alpha1.BGPSpec{
464+
Spec: v1alpha1.BGPSpec{
459465
Site: w.data.site.Name,
460466
NeighborAS: asn,
461467
Hardware: w.data.switchName,
@@ -468,7 +474,7 @@ func (w *Watcher) generateBGPs() error {
468474
PrefixListInbound: PrefixListInboundList,
469475
PrefixListOutbound: []string{
470476
"permit 0.0.0.0/0",
471-
fmt.Sprintf("deny %s/%d", node.IPIP, w.data.blockSize),
477+
fmt.Sprintf("deny %s", ipipNetAddr.String()),
472478
fmt.Sprintf("permit %s le %d", w.data.clusterCIDR, w.data.blockSize),
473479
},
474480
},
@@ -483,7 +489,7 @@ func (w *Watcher) generateBGPs() error {
483489
return nil
484490
}
485491

486-
func (w *Watcher) createBGPs(BGPs []*k8sv1alpha1.BGP) []error {
492+
func (w *Watcher) createBGPs(BGPs []*v1alpha1.BGP) []error {
487493
var errors []error
488494
for _, bgp := range BGPs {
489495
if err := w.createBGP(bgp); err != nil {
@@ -493,13 +499,13 @@ func (w *Watcher) createBGPs(BGPs []*k8sv1alpha1.BGP) []error {
493499
return errors
494500
}
495501

496-
func (w *Watcher) createBGP(bgp *k8sv1alpha1.BGP) error {
502+
func (w *Watcher) createBGP(bgp *v1alpha1.BGP) error {
497503
ctx, cancel := context.WithTimeout(cntxt, contextTimeout)
498504
defer cancel()
499505
return w.client.Create(ctx, bgp.DeepCopyObject(), &client.CreateOptions{})
500506
}
501507

502-
func (w *Watcher) updateBGPs(BGPs []*k8sv1alpha1.BGP) []error {
508+
func (w *Watcher) updateBGPs(BGPs []*v1alpha1.BGP) []error {
503509
var errors []error
504510
for _, bgp := range BGPs {
505511
if err := w.updateBGP(bgp); err != nil {
@@ -509,13 +515,13 @@ func (w *Watcher) updateBGPs(BGPs []*k8sv1alpha1.BGP) []error {
509515
return errors
510516
}
511517

512-
func (w *Watcher) updateBGP(bgp *k8sv1alpha1.BGP) error {
518+
func (w *Watcher) updateBGP(bgp *v1alpha1.BGP) error {
513519
ctx, cancel := context.WithTimeout(cntxt, contextTimeout)
514520
defer cancel()
515521
return w.client.Update(ctx, bgp.DeepCopyObject(), &client.UpdateOptions{})
516522
}
517523

518-
func (w *Watcher) deleteBGPs(BGPs []*k8sv1alpha1.BGP) []error {
524+
func (w *Watcher) deleteBGPs(BGPs []*v1alpha1.BGP) []error {
519525
var errors []error
520526
for _, bgp := range BGPs {
521527
if err := w.deleteBGP(bgp); err != nil {
@@ -525,19 +531,19 @@ func (w *Watcher) deleteBGPs(BGPs []*k8sv1alpha1.BGP) []error {
525531
return errors
526532
}
527533

528-
func (w *Watcher) deleteBGP(bgp *k8sv1alpha1.BGP) error {
534+
func (w *Watcher) deleteBGP(bgp *v1alpha1.BGP) error {
529535
ctx, cancel := context.WithTimeout(cntxt, contextTimeout)
530536
defer cancel()
531537
return w.client.Delete(ctx, bgp.DeepCopyObject(), &client.DeleteAllOfOptions{})
532538
}
533539

534-
func (w *Watcher) compareBGPs() ([]*k8sv1alpha1.BGP, []*k8sv1alpha1.BGP, []*k8sv1alpha1.BGP) {
535-
genBGPsMap := make(map[string]*k8sv1alpha1.BGP)
536-
BGPsMap := make(map[string]*k8sv1alpha1.BGP)
540+
func (w *Watcher) compareBGPs() ([]*v1alpha1.BGP, []*v1alpha1.BGP, []*v1alpha1.BGP) {
541+
genBGPsMap := make(map[string]*v1alpha1.BGP)
542+
BGPsMap := make(map[string]*v1alpha1.BGP)
537543

538-
bgpsForCreate := []*k8sv1alpha1.BGP{}
539-
bgpsForDelete := []*k8sv1alpha1.BGP{}
540-
bgpsForUpdate := []*k8sv1alpha1.BGP{}
544+
bgpsForCreate := []*v1alpha1.BGP{}
545+
bgpsForDelete := []*v1alpha1.BGP{}
546+
bgpsForUpdate := []*v1alpha1.BGP{}
541547

542548
for _, bgp := range w.data.generatedBGPs {
543549
genBGPsMap[bgp.Name] = bgp
@@ -568,10 +574,10 @@ func (w *Watcher) compareBGPs() ([]*k8sv1alpha1.BGP, []*k8sv1alpha1.BGP, []*k8sv
568574
return bgpsForCreate, bgpsForDelete, bgpsForUpdate
569575
}
570576

571-
func (w *Watcher) getBGPs() (*k8sv1alpha1.BGPList, error) {
577+
func (w *Watcher) getBGPs() (*v1alpha1.BGPList, error) {
572578
ctx, cancel := context.WithTimeout(cntxt, contextTimeout)
573579
defer cancel()
574-
bgps := &k8sv1alpha1.BGPList{}
580+
bgps := &v1alpha1.BGPList{}
575581
err := w.client.List(ctx, bgps, &client.ListOptions{})
576582
if err != nil {
577583
return nil, err
@@ -605,7 +611,7 @@ func (w *Watcher) getNodes() error {
605611
}
606612

607613
if len(nodes.Items) == 0 {
608-
return fmt.Errorf("Nodes are missing")
614+
return fmt.Errorf("nodes are missing")
609615
}
610616
w.data.nodes = nodes
611617
return nil
@@ -716,7 +722,7 @@ func (w *Watcher) nodesProcessing() error {
716722
asn := ""
717723

718724
if _, ok := anns["projectcalico.org/ASNumber"]; !ok {
719-
return fmt.Errorf("Couldn't get as number for node %s", node.Name)
725+
return fmt.Errorf("couldn't get as number for node %s", node.Name)
720726
}
721727

722728
asn = anns["projectcalico.org/ASNumber"]
@@ -734,17 +740,30 @@ func (w *Watcher) nodesProcessing() error {
734740
}
735741

736742
if siteName == "" {
737-
id, gateway, err := w.findSiteByIP(ip)
743+
sbnt, err := findIPAMByIP(ip, w.NStorage.SubnetsStorage.GetAll())
738744
if err != nil {
739745
fmt.Println(err)
740746
continue
741747
}
748+
749+
_, ipNet, err := net.ParseCIDR(sbnt.Prefix)
750+
if err != nil {
751+
fmt.Println(err)
752+
continue
753+
}
754+
755+
subnet = ipNet.String()
756+
id := 0
757+
758+
if len(sbnt.Sites) > 0 {
759+
id = sbnt.Sites[0].ID
760+
}
761+
742762
var ok bool
743763
if site, ok = w.NStorage.SitesStorage.FindByID(id); ok {
744764
siteName = site.Name
745765
}
746-
subnet = gateway
747-
if vn, ok := w.NStorage.VNetStorage.FindByGateway(gateway); ok {
766+
if vn, ok := w.NStorage.VNetStorage.FindByGateway(subnet); ok {
748767
vnet = vn
749768
}
750769
}
@@ -753,14 +772,14 @@ func (w *Watcher) nodesProcessing() error {
753772
}
754773

755774
if siteName == "" {
756-
return fmt.Errorf("Couldn't find site")
775+
return fmt.Errorf("couldn't find site")
757776
}
758777

759778
if vnet == nil {
760-
return fmt.Errorf("Couldn't find vnet")
779+
return fmt.Errorf("couldn't find vnet")
761780
}
762781
if vnet.ID == 0 {
763-
return fmt.Errorf("Couldn't find vnet")
782+
return fmt.Errorf("couldn't find vnet")
764783
}
765784

766785
vnetName = vnet.Name
@@ -816,7 +835,7 @@ func (w *Watcher) validateASNRange(asns string) (int, int, error) {
816835
return a, b, nil
817836
}
818837

819-
// patchStringValue specifies a patch operation for a string.
838+
// patchStringValue specifies a patch operation for a string.
820839
type patchStringValue struct {
821840
Op string `json:"op"`
822841
Path string `json:"path"`

calicowatcher/utils.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,30 @@ import (
2323
"github.com/netrisai/netriswebapi/v2/types/ipam"
2424
)
2525

26-
func (w *Watcher) findSiteByIP(ip string) (int, string, error) {
27-
siteID := 0
28-
subnets := w.NStorage.SubnetsStorage.GetAll()
29-
30-
subnetChilds := []*ipam.IPAM{}
26+
func findIPAMByIP(ip string, subnets []*ipam.IPAM) (*ipam.IPAM, error) {
3127
for _, subnet := range subnets {
32-
subnetChilds = append(subnetChilds, subnet.Children...)
33-
}
34-
35-
for _, subnet := range subnetChilds {
3628
ipAddr := net.ParseIP(ip)
3729
_, ipNet, err := net.ParseCIDR(subnet.Prefix)
3830
if err != nil {
39-
return siteID, "", err
31+
return nil, err
4032
}
33+
4134
if ipNet.Contains(ipAddr) {
42-
if len(subnet.Sites) > 0 {
43-
return subnet.Sites[0].ID, ipNet.String(), nil
35+
if len(subnet.Children) > 0 {
36+
ip, err := findIPAMByIP(ip, subnet.Children)
37+
if ip != nil {
38+
return ip, err
39+
}
4440
}
41+
42+
return subnet, nil
43+
4544
}
4645
}
4746

48-
return siteID, "", fmt.Errorf("There are no sites for specified IP address %s", ip)
47+
return nil, fmt.Errorf("there are no subnet for specified IP address %s", ip)
48+
}
49+
50+
func FindIPAMByIP(ip string, subnets []*ipam.IPAM) (*ipam.IPAM, error) {
51+
return findIPAMByIP(ip, subnets)
4952
}

config/manager/custom-env.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,5 @@ spec:
3232
value: "15"
3333
- name: NOPERATOR_CALICO_ASN_RANGE
3434
value: "4230000000-4239999999"
35+
- name: NOPERATOR_L4LB_TENANT
36+
value: ""

configloader/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type config struct {
1111
LogDevMode bool `yaml:"logdevmode" envconfig:"NOPERATOR_DEV_MODE"`
1212
RequeueInterval int `yaml:"requeueinterval" envconfig:"NOPERATOR_REQUEUE_INTERVAL"`
1313
CalicoASNRange string `yaml:"calicoasnrange" envconfig:"NOPERATOR_CALICO_ASN_RANGE"`
14+
L4lbTenant string `yaml:"l4lbtenant" envconfig:"NOPERATOR_L4LB_TENANT"`
1415
}
1516

1617
type controller struct {

configloader/config.yml

+1
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ controller:
77
# logdevmode: false # overwrite env: NOPERATOR_DEV_MODE
88
# requeueinterval: 15 # overwrite env: NOPERATOR_REQUEUE_INTERVAL
99
# calicoasnrange: 4230000000-4239999999 # overwrite env: NOPERATOR_CALICO_ASN_RANGE
10+
# l4lbtenant: # overwrite env: NOPERATOR_L4LB_TENANT

controllers/l4lb_controller.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@ import (
3636
// L4LBReconciler reconciles a L4LB object
3737
type L4LBReconciler struct {
3838
client.Client
39-
Log logr.Logger
40-
Scheme *runtime.Scheme
41-
Cred *api.Clientset
42-
NStorage *netrisstorage.Storage
39+
Log logr.Logger
40+
Scheme *runtime.Scheme
41+
Cred *api.Clientset
42+
NStorage *netrisstorage.Storage
43+
L4LBTenant string
4344
}
4445

4546
// +kubebuilder:rbac:groups=k8s.netris.ai,resources=l4lbs,verbs=get;list;watch;create;update;patch;delete

controllers/l4lb_translations.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"strings"
2525

2626
k8sv1alpha1 "github.com/netrisai/netris-operator/api/v1alpha1"
27+
"github.com/netrisai/netris-operator/calicowatcher"
2728
"github.com/netrisai/netriswebapi/v2/types/ipam"
2829
"github.com/netrisai/netriswebapi/v2/types/l4lb"
2930
"github.com/r3labs/diff/v2"
@@ -58,11 +59,16 @@ func (r *L4LBReconciler) L4LBToL4LBMeta(l4lb *k8sv1alpha1.L4LB) (*k8sv1alpha1.L4
5859
}
5960

6061
if l4lb.Spec.OwnerTenant == "" {
61-
tenantid, err := r.findTenantByIP(ipForTenant)
62-
if err != nil {
63-
return nil, err
62+
if r.L4LBTenant != "" {
63+
l4lb.Spec.OwnerTenant = r.L4LBTenant
64+
} else {
65+
subnet, err := calicowatcher.FindIPAMByIP(ipForTenant, r.NStorage.SubnetsStorage.GetAll())
66+
if err != nil {
67+
return nil, err
68+
}
69+
70+
tenantID = subnet.Tenant.ID
6471
}
65-
tenantID = tenantid
6672
}
6773

6874
if tenantID == 0 {

deploy/charts/netris-operator/Chart.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ type: application
1515
# This is the chart version. This version number should be incremented each time you make changes
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18-
version: 1.0.1
18+
version: 1.1.0
1919

2020
# This is the version number of the application being deployed. This version number should be
2121
# incremented each time you make changes to the application. Versions are not expected to
2222
# follow Semantic Versioning. They should reflect the version the application is using.
23-
appVersion: v2.0.1
23+
appVersion: v2.1.0
2424
home: https://github.com/netrisai/netris-operator
2525
icon: https://www.netris.ai/wp-content/uploads/2021/01/logo-300.png # [todo] Change url to permalink
2626
keywords:

0 commit comments

Comments
 (0)