Skip to content

Commit 83a6089

Browse files
author
OpenShift Bot
authored
Merge pull request #13391 from rajatchopra/f5partition
Merged by openshift-bot
2 parents b39b0ed + 6ee3a7e commit 83a6089

File tree

4 files changed

+405
-248
lines changed

4 files changed

+405
-248
lines changed

pkg/router/f5/f5.go

+95-38
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,50 @@ func (f5 *f5LTM) delete(url string, result interface{}) error {
481481
return f5.restRequest("DELETE", url, nil, result)
482482
}
483483

484+
//
485+
// iControl REST resource helper methods.
486+
//
487+
488+
// encodeiControlUriPathComponent returns an encoded resource path for use
489+
// in the URI for the iControl REST calls.
490+
// For example for a path /Common/foo, the corresponding encoded iControl
491+
// URI path component would be ~Common~foo and this can then be used in the
492+
// iControl REST calls ala:
493+
// https://<ip>:<port>/mgmt/tm/ltm/policy/~Common~foo/rules
494+
func encodeiControlUriPathComponent(pathName string) string {
495+
return strings.Replace(pathName, "/", "~", -1)
496+
}
497+
498+
// iControlUriResourceId returns an encoded resource id (resource path
499+
// including the partition), which can be used the iControl REST calls.
500+
// For example, for a policy named openshift_secure_routes policy in the
501+
// /Common partition, the encoded resource id would be:
502+
// ~Common~openshift_secure_routes
503+
// which can then be used as a resource specifier in the URI ala:
504+
// https://<ip>:<port>/mgmt/tm/ltm/policy/~Common~openshift_secure_routes/rules
505+
func (f5 *f5LTM) iControlUriResourceId(resourceName string) string {
506+
resourcePath := path.Join(f5.partitionPath, resourceName)
507+
return encodeiControlUriPathComponent(resourcePath)
508+
}
509+
510+
// iControlUriVserverId returns an encoded Virtual Server id (virtual
511+
// server name including the partition), which can be used in the iControl
512+
// REST calls.
513+
// For example, for a virtual server named ose-vserver in
514+
// the /rht/ose3/config partition path, the encoded Virtual Server id is:
515+
// ~rht~ose-vserver
516+
func (f5 *f5LTM) iControlUriVserverId(vserverName string) string {
517+
// Note: Most resources are stored under the configured partition
518+
// path, which may be a top-level folder or a sub-folder.
519+
// However a virtual server can only be stored under a
520+
// top-level folder.
521+
// Example: For a vserver named ose-server in the /rht/ose3/config
522+
// partition path, the encoded URI path component is:
523+
// ~rht~ose-vserver
524+
pathComponents := strings.Split(f5.partitionPath, "/")
525+
return encodeiControlUriPathComponent(path.Join("/", pathComponents[1], vserverName))
526+
}
527+
484528
//
485529
// Routines for controlling F5.
486530
//
@@ -532,7 +576,7 @@ func (f5 *f5LTM) ensureVxLANTunnel() error {
532576
AddressSource: "from-user",
533577
Floating: "disabled",
534578
InheritedTrafficGroup: "false",
535-
TrafficGroup: path.Join(f5.partitionPath, "traffic-group-local-only"),
579+
TrafficGroup: path.Join("/Common", "traffic-group-local-only"), // Traffic group is global
536580
Unit: 0,
537581
Vlan: path.Join(f5.partitionPath, F5VxLANTunnelName),
538582
AllowService: "all",
@@ -552,8 +596,9 @@ func (f5 *f5LTM) ensureVxLANTunnel() error {
552596
func (f5 *f5LTM) ensurePolicyExists(policyName string) error {
553597
glog.V(4).Infof("Checking whether policy %s exists...", policyName)
554598

599+
policyResourceId := f5.iControlUriResourceId(policyName)
555600
policyUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s",
556-
f5.host, policyName)
601+
f5.host, policyResourceId)
557602

558603
err := f5.get(policyUrl, nil)
559604
if err != nil && err.(F5Error).httpStatusCode != 404 {
@@ -570,11 +615,13 @@ func (f5 *f5LTM) ensurePolicyExists(policyName string) error {
570615

571616
policiesUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy", f5.host)
572617

618+
policyPath := path.Join(f5.partitionPath, policyName)
619+
573620
if f5.setupOSDNVxLAN {
574621
// if vxlan needs to be setup, it will only happen
575622
// with ver12, for which we need to use a different payload
576623
policyPayload := f5Ver12Policy{
577-
Name: policyName,
624+
Name: policyPath,
578625
TmPartition: f5.partitionPath,
579626
Controls: []string{"forwarding"},
580627
Requires: []string{"http"},
@@ -584,10 +631,11 @@ func (f5 *f5LTM) ensurePolicyExists(policyName string) error {
584631
err = f5.post(policiesUrl, policyPayload, nil)
585632
} else {
586633
policyPayload := f5Policy{
587-
Name: policyName,
588-
Controls: []string{"forwarding"},
589-
Requires: []string{"http"},
590-
Strategy: "best-match",
634+
Name: policyPath,
635+
Partition: f5.partitionPath,
636+
Controls: []string{"forwarding"},
637+
Requires: []string{"http"},
638+
Strategy: "best-match",
591639
}
592640
err = f5.post(policiesUrl, policyPayload, nil)
593641
}
@@ -602,7 +650,7 @@ func (f5 *f5LTM) ensurePolicyExists(policyName string) error {
602650
glog.V(4).Infof("Policy %s created. Adding no-op rule...", policyName)
603651

604652
rulesUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s/rules",
605-
f5.host, policyName)
653+
f5.host, policyResourceId)
606654

607655
rulesPayload := f5Rule{
608656
Name: "default_noop",
@@ -624,11 +672,13 @@ func (f5 *f5LTM) ensureVserverHasPolicy(vserverName, policyName string) error {
624672
glog.V(4).Infof("Checking whether vserver %s has policy %s...",
625673
vserverName, policyName)
626674

675+
vserverResourceId := f5.iControlUriVserverId(vserverName)
676+
627677
// We could use fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s/policies/%s",
628-
// f5.host, vserverName, policyName) here, except that F5 iControl REST
629-
// returns a 200 even if the policy does not exist.
678+
// f5.host, vserverResourceId, policyName) here, except that F5
679+
// iControl REST returns a 200 even if the policy does not exist.
630680
vserverPoliciesUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s/policies",
631-
f5.host, vserverName)
681+
f5.host, vserverResourceId)
632682

633683
res := f5VserverPolicies{}
634684

@@ -637,8 +687,10 @@ func (f5 *f5LTM) ensureVserverHasPolicy(vserverName, policyName string) error {
637687
return err
638688
}
639689

690+
policyPath := path.Join(f5.partitionPath, policyName)
691+
640692
for _, policy := range res.Policies {
641-
if policy.Name == policyName {
693+
if policy.FullPath == policyPath {
642694
glog.V(4).Infof("Vserver %s has policy %s associated with it;"+
643695
" nothing to do.", vserverName, policyName)
644696
return nil
@@ -648,7 +700,8 @@ func (f5 *f5LTM) ensureVserverHasPolicy(vserverName, policyName string) error {
648700
glog.V(4).Infof("Adding policy %s to vserver %s...", policyName, vserverName)
649701

650702
vserverPoliciesPayload := f5VserverPolicy{
651-
Name: policyName,
703+
Name: policyPath,
704+
Partition: f5.partitionPath,
652705
}
653706

654707
err = f5.post(vserverPoliciesUrl, vserverPoliciesPayload, nil)
@@ -709,7 +762,8 @@ func (f5 *f5LTM) ensureDatagroupExists(datagroupName string) error {
709762
func (f5 *f5LTM) ensureIRuleExists(iRuleName, iRule string) error {
710763
glog.V(4).Infof("Checking whether iRule %s exists...", iRuleName)
711764

712-
iRuleUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/rule/%s", f5.host, iRuleName)
765+
iRuleUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/rule/%s", f5.host,
766+
f5.iControlUriResourceId(iRuleName))
713767

714768
err := f5.get(iRuleUrl, nil)
715769
if err != nil && err.(F5Error).httpStatusCode != 404 {
@@ -727,8 +781,9 @@ func (f5 *f5LTM) ensureIRuleExists(iRuleName, iRule string) error {
727781
iRulesUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/rule", f5.host)
728782

729783
iRulePayload := f5IRule{
730-
Name: iRuleName,
731-
Code: iRule,
784+
Name: iRuleName,
785+
Partition: f5.partitionPath,
786+
Code: iRule,
732787
}
733788

734789
err = f5.post(iRulesUrl, iRulePayload, nil)
@@ -748,7 +803,7 @@ func (f5 *f5LTM) ensureVserverHasIRule(vserverName, iRuleName string) error {
748803
vserverName, iRuleName)
749804

750805
vserverUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s",
751-
f5.host, vserverName)
806+
f5.host, f5.iControlUriVserverId(vserverName))
752807

753808
res := f5VserverIRules{}
754809

@@ -757,7 +812,7 @@ func (f5 *f5LTM) ensureVserverHasIRule(vserverName, iRuleName string) error {
757812
return err
758813
}
759814

760-
commonIRuleName := fmt.Sprintf("%s/%s", f5.partitionPath, iRuleName)
815+
commonIRuleName := path.Join("/", f5.partitionPath, iRuleName)
761816

762817
for _, name := range res.Rules {
763818
if name == commonIRuleName {
@@ -770,8 +825,9 @@ func (f5 *f5LTM) ensureVserverHasIRule(vserverName, iRuleName string) error {
770825

771826
glog.V(4).Infof("Adding iRule %s to vserver %s...", iRuleName, vserverName)
772827

828+
sslPassthroughIRulePath := path.Join(f5.partitionPath, sslPassthroughIRuleName)
773829
vserverRulesPayload := f5VserverIRules{
774-
Rules: []string{sslPassthroughIRuleName},
830+
Rules: []string{sslPassthroughIRulePath},
775831
}
776832

777833
err = f5.patch(vserverUrl, vserverRulesPayload, nil)
@@ -788,10 +844,8 @@ func (f5 *f5LTM) ensureVserverHasIRule(vserverName, iRuleName string) error {
788844
func (f5 *f5LTM) checkPartitionPathExists(pathName string) (bool, error) {
789845
glog.V(4).Infof("Checking if partition path %q exists...", pathName)
790846

791-
// F5 iControl REST API expects / characters in the path to be
792-
// escaped as ~.
793847
uri := fmt.Sprintf("https://%s/mgmt/tm/sys/folder/%s",
794-
f5.host, strings.Replace(pathName, "/", "~", -1))
848+
f5.host, encodeiControlUriPathComponent(pathName))
795849

796850
err := f5.get(uri, nil)
797851
if err != nil {
@@ -1012,9 +1066,10 @@ func (f5 *f5LTM) CreatePool(poolname string) error {
10121066
// From @Miciah: In the future, we should allow the administrator
10131067
// to specify a different monitor to use.
10141068
payload := f5Pool{
1015-
Mode: "round-robin",
1016-
Monitor: "min 1 of /Common/http /Common/https",
1017-
Name: poolname,
1069+
Mode: "round-robin",
1070+
Monitor: "min 1 of /Common/http /Common/https",
1071+
Partition: f5.partitionPath,
1072+
Name: poolname,
10181073
}
10191074

10201075
err := f5.post(url, payload, nil)
@@ -1036,7 +1091,8 @@ func (f5 *f5LTM) CreatePool(poolname string) error {
10361091
// DeletePool deletes the specified pool from F5 BIG-IP, and deletes
10371092
// f5.poolMembers[poolname].
10381093
func (f5 *f5LTM) DeletePool(poolname string) error {
1039-
url := fmt.Sprintf("https://%s/mgmt/tm/ltm/pool/%s", f5.host, poolname)
1094+
url := fmt.Sprintf("https://%s/mgmt/tm/ltm/pool/%s", f5.host,
1095+
f5.iControlUriResourceId(poolname))
10401096

10411097
err := f5.delete(url, nil)
10421098
if err != nil {
@@ -1062,7 +1118,7 @@ func (f5 *f5LTM) GetPoolMembers(poolname string) (map[string]bool, error) {
10621118
}
10631119

10641120
url := fmt.Sprintf("https://%s/mgmt/tm/ltm/pool/%s/members",
1065-
f5.host, poolname)
1121+
f5.host, f5.iControlUriResourceId(poolname))
10661122

10671123
res := f5PoolMemberset{}
10681124

@@ -1125,7 +1181,7 @@ func (f5 *f5LTM) AddPoolMember(poolname, member string) error {
11251181
glog.V(4).Infof("Adding pool member %s to pool %s.", member, poolname)
11261182

11271183
url := fmt.Sprintf("https://%s/mgmt/tm/ltm/pool/%s/members",
1128-
f5.host, poolname)
1184+
f5.host, f5.iControlUriResourceId(poolname))
11291185

11301186
payload := f5PoolMember{
11311187
Name: member,
@@ -1164,7 +1220,7 @@ func (f5 *f5LTM) DeletePoolMember(poolname, member string) error {
11641220
}
11651221

11661222
url := fmt.Sprintf("https://%s/mgmt/tm/ltm/pool/%s/members/%s",
1167-
f5.host, poolname, member)
1223+
f5.host, f5.iControlUriResourceId(poolname), member)
11681224

11691225
err = f5.delete(url, nil)
11701226
if err != nil {
@@ -1187,7 +1243,7 @@ func (f5 *f5LTM) getRoutes(policyname string) (map[string]bool, error) {
11871243
}
11881244

11891245
url := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s/rules",
1190-
f5.host, policyname)
1246+
f5.host, f5.iControlUriResourceId(policyname))
11911247

11921248
res := f5PolicyRuleset{}
11931249

@@ -1257,8 +1313,9 @@ func (f5 *f5LTM) addRoute(policyname, routename, poolname, hostname,
12571313
pathname string) error {
12581314
success := false
12591315

1316+
policyResourceId := f5.iControlUriResourceId(policyname)
12601317
rulesUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s/rules",
1261-
f5.host, policyname)
1318+
f5.host, policyResourceId)
12621319

12631320
rulesPayload := f5Rule{
12641321
Name: routename,
@@ -1288,7 +1345,7 @@ func (f5 *f5LTM) addRoute(policyname, routename, poolname, hostname,
12881345
}()
12891346

12901347
conditionUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s/rules/%s/conditions",
1291-
f5.host, policyname, routename)
1348+
f5.host, policyResourceId, routename)
12921349

12931350
conditionPayload := f5RuleCondition{
12941351
Name: "0",
@@ -1330,7 +1387,7 @@ func (f5 *f5LTM) addRoute(policyname, routename, poolname, hostname,
13301387
}
13311388

13321389
actionUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s/rules/%s/actions",
1333-
f5.host, policyname, routename)
1390+
f5.host, policyResourceId, routename)
13341391

13351392
actionPayload := f5RuleAction{
13361393
Name: "0",
@@ -1523,7 +1580,7 @@ func (f5 *f5LTM) DeletePassthroughRoute(routename string) error {
15231580
// policy.
15241581
func (f5 *f5LTM) deleteRoute(policyname, routename string) error {
15251582
ruleUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/policy/%s/rules/%s",
1526-
f5.host, policyname, routename)
1583+
f5.host, f5.iControlUriResourceId(policyname), routename)
15271584

15281585
err := f5.delete(ruleUrl, nil)
15291586
if err != nil {
@@ -1844,7 +1901,7 @@ func (f5 *f5LTM) associateClientSslProfileWithVserver(profilename,
18441901
profilename, vservername)
18451902

18461903
vserverProfileUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s/profiles",
1847-
f5.host, vservername)
1904+
f5.host, f5.iControlUriVserverId(vservername))
18481905

18491906
vserverProfilePayload := f5VserverProfilePayload{
18501907
Name: profilename,
@@ -1862,7 +1919,7 @@ func (f5 *f5LTM) associateServerSslProfileWithVserver(profilename,
18621919
profilename, vservername)
18631920

18641921
vserverProfileUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s/profiles",
1865-
f5.host, vservername)
1922+
f5.host, f5.iControlUriVserverId(vservername))
18661923

18671924
vserverProfilePayload := f5VserverProfilePayload{
18681925
Name: profilename,
@@ -1890,7 +1947,7 @@ func (f5 *f5LTM) deleteCertParts(routename string,
18901947
routename, f5.httpsVserver)
18911948
serverSslProfileName := fmt.Sprintf("%s-server-ssl-profile", routename)
18921949
serverSslVserverProfileUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s/profiles/%s",
1893-
f5.host, f5.httpsVserver, serverSslProfileName)
1950+
f5.host, f5.iControlUriVserverId(f5.httpsVserver), serverSslProfileName)
18941951
err := f5.delete(serverSslVserverProfileUrl, nil)
18951952
if err != nil {
18961953
// Iff the profile is not associated with the vserver, we can continue on to
@@ -1925,7 +1982,7 @@ func (f5 *f5LTM) deleteCertParts(routename string,
19251982
" from vserver %s...", routename, f5.httpsVserver)
19261983
clientSslProfileName := fmt.Sprintf("%s-client-ssl-profile", routename)
19271984
clientSslVserverProfileUrl := fmt.Sprintf("https://%s/mgmt/tm/ltm/virtual/%s/profiles/%s",
1928-
f5.host, f5.httpsVserver, clientSslProfileName)
1985+
f5.host, f5.iControlUriVserverId(f5.httpsVserver), clientSslProfileName)
19291986
err := f5.delete(clientSslVserverProfileUrl, nil)
19301987
if err != nil {
19311988
// Iff the profile is not associated with the vserver, we can continue on

pkg/router/f5/plugin.go

+5
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,11 @@ func (p *F5Plugin) HandleEndpoints(eventType watch.EventType,
279279

280280
glog.V(4).Infof("Deleting pool %s", poolname)
281281

282+
// Note: deletePool will throw errors if the route
283+
// has not been deleted as the policy would
284+
// still refer to the pool. That is ok as the
285+
// pool will still get deleted when the route
286+
// gets deleted.
282287
err = p.deletePool(poolname)
283288
if err != nil {
284289
return err

0 commit comments

Comments
 (0)