Skip to content

Feat: Add support for stickyness policy - #88

Merged
DaanHoogland merged 2 commits into
mainfrom
feat-add-stickyness-policy
Oct 7, 2026
Merged

DaanHoogland merged 2 commits into
mainfrom
feat-add-stickyness-policy

Conversation

@vishesh92

@vishesh92 vishesh92 commented Dec 2, 2025 •

Copy link
Copy Markdown
Member

This needs changes in this PR: apache/cloudstack-go#133

Fixes #75

@vishesh92
vishesh92 marked this pull request as draft December 2, 2025 09:17
@vishesh92 vishesh92 added this to the 1.2.0 milestone Dec 4, 2025
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from f25a1e7 to 207f378 Compare December 12, 2025 07:33
@codecov-commenter

codecov-commenter commented Dec 12, 2025 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.84979% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.97%. Comparing base (7d27f2f) to head (435a548).

Files with missing lines Patch % Lines
cloudstack_loadbalancer.go 94.84% 7 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #88      +/-   ##
==========================================
+ Coverage   67.04%   71.97%   +4.93%     
==========================================
  Files           5        5              
  Lines        1250     1470     +220     
==========================================
+ Hits          838     1058     +220     
+ Misses        365      361       -4     
- Partials       47       51       +4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vishesh92 vishesh92 modified the milestones: 1.2.0, 1.3.0 Dec 16, 2025
Copilot AI lite review requested due to automatic review settings August 20, 2026 09:26
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from 207f378 to 6b74579 Compare August 20, 2026 09:26
@vishesh92
vishesh92 marked this pull request as ready for review August 20, 2026 09:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds support for configuring CloudStack Load Balancer stickiness policy via Kubernetes Service annotations (fixing the request in #75), and updates module dependencies to use a CloudStack Go SDK version that supports the required stickiness-policy API parameters.

Changes:

  • Introduces Service annotations for stickiness method name + params and reconciles stickiness policies during EnsureLoadBalancer.
  • Extends load balancer discovery to also fetch existing stickiness policies for rules.
  • Bumps github.com/apache/cloudstack-go/v2 to v2.19.1 and updates Go module dependencies accordingly.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.

File Description
cloudstack_loadbalancer.go Adds stickiness annotations, policy reconciliation logic, and stickiness policy listing/CRUD.
go.mod Bumps CloudStack Go SDK to v2.19.1 and adjusts dependency classification.
go.sum Updates checksums for the bumped CloudStack Go SDK version.
Suppressed comments (2)

cloudstack_loadbalancer.go:833

  • CreateLBStickinessPolicy response is assumed to contain at least one Stickinesspolicy entry; if the API returns an empty slice this will panic. Add a defensive check and return an explicit error (and drop the commented-out return).
	return &cloudstack.LBStickinessPolicyStickinesspolicy{
		Methodname: stickynessPolicy.Stickinesspolicy[0].Methodname,
		Params:     stickynessPolicy.Stickinesspolicy[0].Params,
		Id:         stickynessPolicy.Stickinesspolicy[0].Id,
		Name:       stickynessPolicy.Stickinesspolicy[0].Name,

cloudstack_loadbalancer.go:1282

  • parseStickynessParams trims the full key=value token but not the key/value themselves, so annotations like "cookie = abc" will produce a key of "cookie " and won’t match expected params. Trim both sides when populating the map.
		if len(parts) == 2 {
			params[parts[0]] = parts[1]
		}

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread cloudstack_loadbalancer.go Outdated
Comment thread cloudstack_loadbalancer.go Outdated
Comment thread cloudstack_loadbalancer.go Outdated
Comment thread cloudstack_loadbalancer.go Outdated
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from 6b74579 to 95d6b1d Compare August 27, 2026 13:15
Copilot AI review requested due to automatic review settings August 27, 2026 13:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings August 31, 2026 06:15
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from 95d6b1d to 63947d8 Compare August 31, 2026 06:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from 63947d8 to c314d28 Compare September 18, 2026 05:29
Copilot AI review requested due to automatic review settings September 18, 2026 05:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Orchestration-path test coverage and the documented comment/example corrections remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (1)

cloudstack_loadbalancer.go:198

  • The new tests cover the helper methods independently, but do not exercise this orchestration path for a new rule, a parameter change, or annotation removal. A regression in the ordering/map cleanup around delete-and-recreate could therefore pass all added tests; add an EnsureLoadBalancer test with mocked list/create/delete policy calls.
			stickinessPolicy, stickinessPolicyNeedsUpdate, err := lb.checkStickinessPolicy(lbRule, service)
			if err != nil {
				return nil, err
			}
			if stickinessPolicyNeedsUpdate {
  • Files reviewed: 4/5 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread README.md Outdated
Comment thread cloudstack_loadbalancer.go Outdated
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from c314d28 to 84c27e0 Compare September 18, 2026 06:10
Copilot AI review requested due to automatic review settings September 18, 2026 06:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Clean up the load-balancer rule when stickiness policy creation fails before approval.

Get a fresh assessment by requesting another Copilot review.

Review details
  • Files reviewed: 6/7 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread cloudstack_loadbalancer.go Outdated
Copilot AI review requested due to automatic review settings September 18, 2026 06:42
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from 84c27e0 to efe1fd3 Compare September 18, 2026 06:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved critical and moderate load-balancer reconciliation issues remain, along with a documentation inconsistency.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

README.md:242

  • This example adds length=52 to AppCookie, but the preceding contract lists cookie-name for AppCookie and says CloudStack rejects unknown parameters. As written, the documentation advertises a configuration that can fail with the documented sync error; remove length=52 or expand the supported-key description only if this is a valid CloudStack parameter.
    service.beta.kubernetes.io/cloudstack-load-balancer-stickiness-method-param: "cookie-name=JSESSIONID,length=52"

cloudstack_loadbalancer.go:519

  • getLoadBalancer is also called by UpdateLoadBalancer, which only reconciles backend hosts. This adds one listLBStickinessPolicies API request per rule to every node/update reconciliation, even when no stickiness annotation is set, and makes host-only updates fail if this optional policy lookup is unavailable. Load policies only in the Ensure/Delete paths or otherwise avoid this per-rule lookup in the shared discovery path.
		lbStickinessPoliciesParams := cs.client.LoadBalancer.NewListLBStickinessPoliciesParams()
		lbStickinessPoliciesParams.SetLbruleid(lbRule.Id)
		lbStickinessPolicies, err := cs.client.LoadBalancer.ListLBStickinessPolicies(lbStickinessPoliciesParams)
  • Files reviewed: 6/7 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread cloudstack_loadbalancer.go Outdated
Copilot AI review requested due to automatic review settings September 18, 2026 08:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved issues remain in value round-tripping, rejected replacement retries, and rollback validation.

Get a fresh assessment by requesting another Copilot review.

Review details

Suppressed comments (2)

cloudstack_loadbalancer.go:874

  • When the replacement is rejected, EnsureLoadBalancer returns this error (as the new e2e test expects), so the service controller retries with the same invalid annotation. Each retry deletes and recreates the previously valid policy, repeatedly resetting HAProxy affinity state and changing the policy ID even though the desired change was not accepted. Avoid repeating this destructive replacement for an unchanged rejected configuration (for example, by caching/short-circuiting permanent validation failures or adding a non-destructive preflight).
	if err := lb.deleteStickinessPolicy(existing.Id); err != nil {
		return err
	}

	if _, err := lb.createStickinessPolicy(lbRuleName, lbRule.Id, service); err != nil {
		return lb.restoreStickinessPolicy(lbRuleName, lbRule.Id, existing, err)

cloudstack_loadbalancer.go:887

  • The rollback path treats any nil-error response as a successful restore, but CloudStack can return an empty Stickinesspolicy list; the normal creation path already treats that response as an error at lines 910-911. In that case a rejected replacement leaves the rule without the old policy while reporting only the original failure, contradicting the rollback guarantee. Validate the restore response before declaring the previous policy recovered.
	if _, err := lb.LoadBalancer.CreateLBStickinessPolicy(p); err != nil {
		return fmt.Errorf("%v (restoring the previous stickiness policy failed too: %v)", cause, err)
  • Files reviewed: 7/8 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread cloudstack_loadbalancer.go Outdated
Copilot AI lite review requested due to automatic review settings October 6, 2026 09:17
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from ca4f5c6 to d4e61ce Compare October 6, 2026 09:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Two moderate issues remain in stickiness policy replacement and fallback flag handling.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
Resolved since last review (1)

Comment thread cloudstack_loadbalancer.go
@vishesh92
vishesh92 force-pushed the feat-add-stickyness-policy branch from d4e61ce to 83b07d4 Compare October 6, 2026 16:37
@Damans227

Copy link
Copy Markdown

tested this on a kvm lab with a 1.24 cluster running this PR's provider (83b07d4). both methods work end to end.

LbCookie on port 80, SourceBased on port 8090. cmk list lbstickinesspolicies for the two rules:

"methodname": "LbCookie",    "params": {"cookie-name": "SERVERID", "nocache": "true"}
"methodname": "SourceBased", "params": {"expire": "30m", "tablesize": "200k"}

router haproxy config:

listen 10_0_60_84-80
	server 10_0_60_84-80_0 10.1.1.55:31150 check cookie 10_1_1_55-31150
	server 10_0_60_84-80_1 10.1.1.153:31150 check cookie 10_1_1_153-31150
	cookie SERVERID insert  nocache
listen 10_0_60_85-8090
	stick-table type ip size 200k expire 30m
	stick on src

10 requests each, two app copies on separate nodes:

--- LbCookie, no cookie kept:
      5 Hostname: whoami-589b5665ff-98l7m
      5 Hostname: whoami-589b5665ff-llrqn
--- LbCookie, cookie kept:
     10 Hostname: whoami-589b5665ff-llrqn
--- SourceBased, same client:
     10 Hostname: whoami-589b5665ff-llrqn

setting cookie-name=APPID replaced the policy (set-cookie: APPID=10_1_1_55-31150). removing the annotation removed the policy and requests split again.

bad input fails and cloudstack is left as is:

stickiness method LbCookie only works on plain HTTP ports: set appProtocol: http on them
stickiness method "Bogus" in annotation service.beta.kubernetes.io/cloudstack-load-balancer-stickiness-method-name is not supported on this network

@DaanHoogland DaanHoogland left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

clgtm, (but I don't like inline comments)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

Two moderate issues remain in stickiness capability validation and failure-safe policy reconciliation.

Review effort: Lite
Findings: None

Resolved since last review (1)

@DaanHoogland

Copy link
Copy Markdown
Contributor

merging on Daman's test report (and my review)

@DaanHoogland
DaanHoogland merged commit 0bd7887 into main Oct 7, 2026
13 checks passed
@DaanHoogland
DaanHoogland deleted the feat-add-stickyness-policy branch October 7, 2026 07:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Setting Load Balancer stickiness method with annotation

5 participants