Skip to content

get services from API, removing sidecar requirement#772

Open
matthyx wants to merge 1 commit intomainfrom
service-disco
Open

get services from API, removing sidecar requirement#772
matthyx wants to merge 1 commit intomainfrom
service-disco

Conversation

@matthyx
Copy link
Copy Markdown
Contributor

@matthyx matthyx commented Apr 3, 2026

Summary by CodeRabbit

  • Chores
    • Service discovery now supports the API_URL environment variable for dynamic endpoint configuration, defaulting to api.armosec.io when unset.

Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

The system transitions service URL loading from file-based discovery to API-based discovery. The scan failure reporter initialization now derives the service endpoint from an API_URL environment variable (defaulting to api.armosec.io), and the LoadServiceURLs function is updated to accept an API URL and use service discovery v3 client instead of file-based v2 approach.

Changes

Cohort / File(s) Summary
Service Discovery Migration
cmd/main.go, pkg/config/config.go
Transition from file-based to API-based service discovery. Main initialization now sources API endpoint from API_URL environment variable with fallback default. LoadServiceURLs() function signature changed to accept apiURL parameter and uses ServiceDiscoveryClientV3 instead of file-based v2 client.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 No more files in the dusty config,
Now we dance with the API's frock!
From api.armosec.io we take our cue,
Service discovery, fresh and new.
The rabbit hops on, with endpoints in view! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: replacing sidecar-based service discovery with direct API calls.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch service-disco

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/config/config.go (1)

293-295: Wrap client-construction errors with API URL context.

At Line 295, returning the raw error makes debugging harder upstream. Include apiURL in the error to make misconfiguration/root-cause visible.

Proposed patch
 func LoadServiceURLs(apiURL string) (schema.IBackendServices, error) {
 	client, err := servicediscoveryv3.NewServiceDiscoveryClientV3(apiURL)
 	if err != nil {
-		return nil, err
+		return nil, fmt.Errorf("create service discovery client for apiURL %q: %w", apiURL, err)
 	}
 	return servicediscovery.GetServices(client)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/config/config.go` around lines 293 - 295, The call to
servicediscoveryv3.NewServiceDiscoveryClientV3(apiURL) returns a raw error that
is returned as-is (return nil, err); change this to wrap the error with the
apiURL context so callers can see which API endpoint failed (e.g., replace the
plain return with a wrapped error using fmt.Errorf or errors.Wrapf mentioning
apiURL), and add the necessary import if missing; keep the existing client/err
variables and only modify the error return site.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/main.go`:
- Around line 402-405: The current LoadServiceURLs call swallows svcErr when
service discovery fails; update the block around LoadServiceURLs so that if
svcErr != nil you emit a warning via the logger (include svcErr.Error()) and
only proceed to create failureReporter when svcErr == nil and
services.GetReportReceiverHttpUrl() != ""; also log a warning if svcErr == nil
but services.GetReportReceiverHttpUrl() is empty to indicate a missing
configured URL; reference the LoadServiceURLs call, the svcErr variable,
services.GetReportReceiverHttpUrl(), and failureReporter when making these
changes.
- Around line 398-401: The current apiURL variable may be a bare hostname which
breaks NewServiceDiscoveryClientV3() because it expects an absolute URL; change
the default to include a scheme (e.g., "https://api.armosec.io") and normalize
any user-provided API_URL by parsing it (using url.Parse) and prepending
"https://" when the scheme is empty before passing to
NewServiceDiscoveryClientV3(); update the apiURL assignment/normalization logic
around the apiURL variable to perform this fix.

---

Nitpick comments:
In `@pkg/config/config.go`:
- Around line 293-295: The call to
servicediscoveryv3.NewServiceDiscoveryClientV3(apiURL) returns a raw error that
is returned as-is (return nil, err); change this to wrap the error with the
apiURL context so callers can see which API endpoint failed (e.g., replace the
plain return with a wrapped error using fmt.Errorf or errors.Wrapf mentioning
apiURL), and add the necessary import if missing; keep the existing client/err
variables and only modify the error return site.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 28210547-e38c-497e-9cd0-97df6382a2db

📥 Commits

Reviewing files that changed from the base of the PR and between 9a09420 and ec9e6c4.

📒 Files selected for processing (2)
  • cmd/main.go
  • pkg/config/config.go

Comment on lines +398 to +401
apiURL := os.Getenv("API_URL")
if apiURL == "" {
apiURL = "api.armosec.io"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In github.com/kubescape/backend/pkg/servicediscovery/v3, does NewServiceDiscoveryClientV3 require an absolute URL including scheme (e.g., https://...), or does it accept bare hostnames like api.armosec.io?

💡 Result:

NewServiceDiscoveryClientV3 in github.com/kubescape/backend/pkg/servicediscovery/v3 likely requires an absolute URL including scheme. Evidence from Kubescape operator usage shows service discovery fetching from https://api.armosec.io/api/v1/servicediscovery, indicating HTTPS absolute URLs are used. Bare hostnames like api.armosec.io are used in contexts like firewall rules but curl commands prepend https://, suggesting the client expects full URLs. No source code found explicitly stating bare hostnames are accepted, and standard Go HTTP clients typically require schemes for absolute URLs.

Citations:


🏁 Script executed:

# Find and read cmd/main.go around lines 398-401
cat -n cmd/main.go | sed -n '395,405p'

Repository: kubescape/node-agent

Length of output: 776


🏁 Script executed:

# Search for NewServiceDiscoveryClientV3 to understand its signature and usage
rg "NewServiceDiscoveryClientV3" -A 3 -B 1

Repository: kubescape/node-agent

Length of output: 348


🏁 Script executed:

# Look for how apiURL is used after being set
rg "apiURL" cmd/main.go -A 2 -B 2

Repository: kubescape/node-agent

Length of output: 695


🏁 Script executed:

# Check LoadServiceURLs implementation
rg "func LoadServiceURLs" -A 10 pkg/config/config.go

Repository: kubescape/node-agent

Length of output: 446


🏁 Script executed:

# Check if servicediscoveryv3 is from an external module and its go.mod
cat go.mod | grep -i servicediscovery

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Look for any URL normalization or scheme-handling in the codebase
rg "https://" cmd/main.go | head -20

Repository: kubescape/node-agent

Length of output: 46


🏁 Script executed:

# Check if there are other places where api.armosec.io is set and how
rg "armosec.io" -B 2 -A 2

Repository: kubescape/node-agent

Length of output: 6609


🏁 Script executed:

# Search for other calls to LoadServiceURLs
rg "LoadServiceURLs" -B 2 -A 2

Repository: kubescape/node-agent

Length of output: 823


🏁 Script executed:

# Check imports in cmd/main.go to see if strings is available
head -50 cmd/main.go | grep -E "^import|strings"

Repository: kubescape/node-agent

Length of output: 83


🏁 Script executed:

# Check if there are tests for LoadServiceURLs or config
fd "config.*test" --type f

Repository: kubescape/node-agent

Length of output: 89


🏁 Script executed:

# Check config_test.go to see if there are tests for LoadServiceURLs
cat -n pkg/config/config_test.go | head -50

Repository: kubescape/node-agent

Length of output: 2052


🏁 Script executed:

# Search for how the scheme is handled elsewhere in similar code
rg "://" pkg/config/ -B 1 -A 1

Repository: kubescape/node-agent

Length of output: 1890


Add URL scheme to default API_URL and normalize user-provided values.

Line 400 defaults to api.armosec.io without a scheme. When passed to NewServiceDiscoveryClientV3(), this bare hostname will fail service discovery (which requires an absolute URL), preventing scan-failure reporting from being enabled.

Additionally, users who provide a custom API_URL environment variable without a scheme will encounter the same failure.

Proposed patch
 	apiURL := os.Getenv("API_URL")
 	if apiURL == "" {
-		apiURL = "api.armosec.io"
+		apiURL = "https://api.armosec.io"
+	} else if !strings.Contains(apiURL, "://") {
+		apiURL = "https://" + apiURL
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/main.go` around lines 398 - 401, The current apiURL variable may be a
bare hostname which breaks NewServiceDiscoveryClientV3() because it expects an
absolute URL; change the default to include a scheme (e.g.,
"https://api.armosec.io") and normalize any user-provided API_URL by parsing it
(using url.Parse) and prepending "https://" when the scheme is empty before
passing to NewServiceDiscoveryClientV3(); update the apiURL
assignment/normalization logic around the apiURL variable to perform this fix.

Comment on lines +402 to 405
if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Don’t swallow service-discovery errors silently.

At Line 402, svcErr is ignored on failure. Add a warning log so misconfiguration/network issues are diagnosable.

Proposed patch
 	if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
 		failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
 		logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
+	} else if svcErr != nil {
+		logger.L().Warning("scan failure reporting disabled: unable to load backend services", helpers.Error(svcErr), helpers.String("apiURL", apiURL))
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
}
if services, svcErr := config.LoadServiceURLs(apiURL); svcErr == nil && services.GetReportReceiverHttpUrl() != "" {
failureReporter = sbommanagerv1.NewHTTPSbomFailureReporter(services.GetReportReceiverHttpUrl(), accessKey, clusterData.AccountID, clusterData.ClusterName)
logger.L().Info("scan failure reporting enabled", helpers.String("eventReceiverURL", services.GetReportReceiverHttpUrl()))
} else if svcErr != nil {
logger.L().Warning("scan failure reporting disabled: unable to load backend services", helpers.Error(svcErr), helpers.String("apiURL", apiURL))
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/main.go` around lines 402 - 405, The current LoadServiceURLs call
swallows svcErr when service discovery fails; update the block around
LoadServiceURLs so that if svcErr != nil you emit a warning via the logger
(include svcErr.Error()) and only proceed to create failureReporter when svcErr
== nil and services.GetReportReceiverHttpUrl() != ""; also log a warning if
svcErr == nil but services.GetReportReceiverHttpUrl() is empty to indicate a
missing configured URL; reference the LoadServiceURLs call, the svcErr variable,
services.GetReportReceiverHttpUrl(), and failureReporter when making these
changes.

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.

1 participant