Skip to content

Conversation

@ShubhamRasal
Copy link
Contributor

@ShubhamRasal ShubhamRasal commented Nov 27, 2025

This PR adds support for auto discovery. With the -ad flag, you no longer need to provide a provider config manually—it automatically detects environment variables or IAM attachments on VMs/pods and uses the appropriate authentication method.
Testing checklist:

  • aws
  • gcp
  • k8s
  • azure

Summary by CodeRabbit

Release Notes

  • New Features

    • Added automatic cloud provider discovery from environment configurations, supporting Kubernetes, AWS, GCP, and Azure detection.
    • Introduced --auto-discovery flag to enable provider auto-detection without requiring explicit configuration files.
  • Bug Fixes

    • Added defensive nil check to prevent crashes when runner initialization fails.
  • Improvements

    • Enhanced credential chain handling for AWS provider to automatically use IMDS and ECS task role credentials when available.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 27, 2025

Walkthrough

This pull request introduces auto-discovery functionality that detects cloud provider configurations from environment variables and runtime settings. The feature adds a new AutoDiscovery mechanism spanning multiple files, integrates provider discovery into the runner's initialization path, and updates inventory creation to handle graceful provider initialization failures.

Changes

Cohort / File(s) Summary
Main Entry Point
cmd/cloudlist/main.go
Adds defensive nil check before invoking runner.Enumerate to prevent nil reference errors
Auto-Discovery Mechanism
internal/runner/autodiscovery.go
New file implementing comprehensive cloud provider auto-discovery for Kubernetes (in-cluster and kubeconfig), AWS (IMDS, ECS task role, environment), GCP (metadata service, application credentials), and Azure (Managed Identity, CLI config) with multiple discovery paths, timeouts, and contextual error handling
Options Configuration
internal/runner/options.go
Adds AutoDiscovery boolean field and --auto-discovery (-ad) command-line flag to enable provider auto-discovery during option parsing
Runner Integration
internal/runner/runner.go
Integrates auto-discovery path in New method; routes to discovery when AutoDiscovery is enabled; gracefully initializes inventory with NewWithOptions when auto-discovery is active; applies conditional provider defaults logic
Inventory Graceful Failure
pkg/inventory/inventory.go
Introduces NewWithOptions constructor supporting graceful failure handling for provider initialization; failed providers are skipped with logging instead of halting enumeration
AWS Provider Updates
pkg/providers/aws/aws.go
Updates credential validation to make credentials optional when use_imds or use_ecs_task_role flags are enabled; falls back to AWS SDK default credential chain
Kubernetes Provider Updates
pkg/providers/k8s/kubernetes.go
Adds incluster_mode option to support in-cluster Kubernetes detection via rest.InClusterConfig(); branches config resolution to handle in-cluster, kubeconfig file, and encoded paths

Sequence Diagram

sequenceDiagram
    participant Runner
    participant AutoDiscovery
    participant ProviderDiscoverers as K8s/AWS/GCP/Azure
    participant Inventory
    participant Providers

    Runner->>Runner: New(options) called with AutoDiscovery enabled
    
    alt AutoDiscovery enabled
        Runner->>AutoDiscovery: NewAutoDiscovery(options)
        
        AutoDiscovery->>ProviderDiscoverers: discoverKubernetes()
        ProviderDiscoverers-->>AutoDiscovery: OptionBlock (k8s config)
        
        AutoDiscovery->>ProviderDiscoverers: discoverAWS()
        ProviderDiscoverers-->>AutoDiscovery: OptionBlock (AWS credentials)
        
        AutoDiscovery->>ProviderDiscoverers: discoverGCP()
        ProviderDiscoverers-->>AutoDiscovery: OptionBlock (GCP config)
        
        AutoDiscovery->>ProviderDiscoverers: discoverAzure()
        ProviderDiscoverers-->>AutoDiscovery: OptionBlock (Azure identity)
        
        AutoDiscovery-->>Runner: Discovered provider configurations
    else
        Runner->>Runner: Load provider config from file (existing path)
    end
    
    Runner->>Inventory: NewWithOptions(discoveredConfig, graceful=true, verbose)
    
    Inventory->>Providers: Create each provider
    
    alt Provider creation succeeds
        Providers-->>Inventory: Provider instance
    else Provider creation fails
        Inventory->>Inventory: Record failure, log, continue (graceful mode)
    end
    
    Inventory-->>Runner: Initialized Inventory with available providers
    
    Runner->>Inventory: Enumerate()
    Inventory->>Providers: Run()
    Providers-->>Inventory: Results
    Inventory-->>Runner: Enumeration complete
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • internal/runner/autodiscovery.go: Review the multiple discovery methods for each cloud provider (Kubernetes, AWS, GCP, Azure), including IMDS token handling, timeouts, credential chain logic, and contextual error handling
  • internal/runner/runner.go: Verify correct branching between auto-discovery and config-file paths; ensure proper error propagation and logging
  • pkg/inventory/inventory.go: Validate graceful failure semantics and ensure failed providers are correctly skipped without breaking enumeration
  • pkg/providers/aws/aws.go: Confirm credential chain logic; verify optional credential handling aligns with IMDS/ECS paths
  • pkg/providers/k8s/kubernetes.go: Ensure in-cluster config path properly branches and handles errors
  • Integration testing across all modified components to confirm provider discovery, initialization, and enumeration workflows

Poem

🐰 A discovery hop, providers leap and bound,
Cloud configurations all around,
From Kube to AWS, each corner explored,
Auto-detection's graceful reward,
Graceful failures, no crash in sight,
Cloudlist hops into the night!
🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 'Self discovery mode' accurately reflects the main objective of the PR, which introduces auto-discovery functionality enabling automatic detection of cloud providers without requiring a provider config file.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch self-discovery-mode

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

@ShubhamRasal ShubhamRasal self-assigned this Dec 8, 2025
@ShubhamRasal ShubhamRasal marked this pull request as ready for review December 8, 2025 06:27
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
internal/runner/autodiscovery.go (1)

70-92: Consider cross-platform KUBECONFIG path separator.

Line 80 splits KUBECONFIG on :, but Windows uses ; as the path separator. Consider using filepath.ListSeparator for cross-platform compatibility.

-		if strings.Contains(kubeconfigPath, ":") {
-			kubeconfigPath = strings.Split(kubeconfigPath, ":")[0]
+		if strings.Contains(kubeconfigPath, string(filepath.ListSeparator)) {
+			kubeconfigPath = strings.Split(kubeconfigPath, string(filepath.ListSeparator))[0]
 		}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0c9fc3 and ef08d5f.

📒 Files selected for processing (7)
  • cmd/cloudlist/main.go (1 hunks)
  • internal/runner/autodiscovery.go (1 hunks)
  • internal/runner/options.go (2 hunks)
  • internal/runner/runner.go (4 hunks)
  • pkg/inventory/inventory.go (3 hunks)
  • pkg/providers/aws/aws.go (2 hunks)
  • pkg/providers/k8s/kubernetes.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
pkg/providers/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/providers/**/*.go: All providers must implement the schema.Provider interface with methods: Name(), ID(), Resources(ctx), Services()
For complex providers, keep service-specific logic in separate files (e.g., instances.go, dns.go, route53.go, s3.go, eks.go) and return *schema.Resources merged by the main Resources()
Parse provider configuration via block.GetMetadata(key); support environment variables using $VAR syntax; return &schema.ErrNoSuchKey{Name: key} for missing required config
Respect service filtering: Services() must list supported services, and providers should honor -s filters when gathering resources
Always pass and honor context.Context in Resources() and long-running API calls to support cancellation
Do not manually deduplicate resources; use Resources.Append() to rely on schema’s ResourceDeduplicator
Each emitted resource must have at least one of IP or DNS populated; empty resources are invalid
Treat provider config id as a user-defined identifier for filtering, not a cloud resource ID

Files:

  • pkg/providers/k8s/kubernetes.go
  • pkg/providers/aws/aws.go
pkg/providers/*/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Each provider directory must include a main file named .go defining New(block schema.OptionBlock) and Resources(ctx) orchestration

Files:

  • pkg/providers/k8s/kubernetes.go
  • pkg/providers/aws/aws.go
pkg/inventory/inventory.go

📄 CodeRabbit inference engine (CLAUDE.md)

pkg/inventory/inventory.go: Register every new provider in nameToProvider() using a case mapping from provider name to implementation
Keep service names consistent: entries in each provider’s Services() must match the inventory Providers map
When adding a provider, also update the Providers map with the provider and its supported services

Files:

  • pkg/inventory/inventory.go
🧬 Code graph analysis (4)
pkg/providers/aws/aws.go (1)
pkg/schema/schema.go (1)
  • ErrNoSuchKey (166-168)
internal/runner/options.go (1)
internal/runner/autodiscovery.go (1)
  • AutoDiscovery (19-21)
pkg/inventory/inventory.go (2)
internal/runner/options.go (1)
  • Options (22-39)
pkg/schema/schema.go (1)
  • Options (176-176)
internal/runner/autodiscovery.go (2)
internal/runner/options.go (1)
  • Options (22-39)
pkg/schema/schema.go (1)
  • OptionBlock (195-195)
🔇 Additional comments (25)
cmd/cloudlist/main.go (1)

14-16: LGTM!

The nil check prevents a potential panic when auto-discovery returns no providers. The early return is appropriate.

internal/runner/options.go (2)

38-38: LGTM!

The AutoDiscovery field is properly documented and integrates cleanly with the existing Options structure.


81-81: LGTM!

The flag definition is clear and follows the existing pattern with both long and short forms.

pkg/providers/k8s/kubernetes.go (3)

31-31: LGTM!

The constant follows the existing naming pattern for configuration options.


39-43: LGTM!

The validation logic correctly checks for all three configuration options and provides a helpful error message.


57-61: LGTM!

The in-cluster configuration path is correctly implemented using rest.InClusterConfig() with proper error wrapping. This enables Kubernetes provider discovery when running inside a pod.

pkg/providers/aws/aws.go (2)

49-69: LGTM!

The credential handling correctly makes credentials optional when using IMDS or ECS task roles, allowing the AWS SDK to use its default credential chain. The error handling properly returns &schema.ErrNoSuchKey when required credentials are missing in non-metadata scenarios.


147-152: LGTM!

Only setting credentials when both AccessKey and SecretKey are non-empty allows the AWS SDK to fall back to its default credential chain (IMDS, ECS task role, environment variables, credentials file). This is the correct approach for auto-discovery mode.

pkg/inventory/inventory.go (2)

38-40: LGTM!

Delegating to NewWithOptions maintains backward compatibility while enabling the new graceful failure behavior.


42-79: LGTM!

The graceful failure handling is well-implemented. Failed providers are tracked and logged appropriately based on the verbose setting, allowing enumeration to continue with successfully initialized providers. This is essential for auto-discovery mode where some providers may not be available.

internal/runner/runner.go (3)

27-53: LGTM!

The auto-discovery integration is well-structured. The code appropriately bypasses provider config file reading when auto-discovery is enabled, provides helpful hints when no providers are discovered, and gracefully returns nil to signal no providers available.


64-66: LGTM!

Correctly prevents default providers from being added when auto-discovery is active, allowing only discovered providers to be used.


107-125: LGTM!

The graceful failure mode for auto-discovery is correctly implemented. Using NewWithOptions with graceful failure allows partial success, and the check for empty providers prevents proceeding with no valid providers. This provides a better user experience in auto-discovery scenarios.

internal/runner/autodiscovery.go (12)

18-26: LGTM!

The AutoDiscovery struct and constructor are simple and well-defined.


28-68: LGTM!

The discovery orchestration logic is clean and well-structured. Using getProvidersToCheck allows filtering by user-specified providers or defaulting to all supported providers.


94-102: LGTM!

The in-cluster mode detection correctly checks for the service account token file and returns appropriate configuration for Kubernetes pods.


104-119: LGTM!

The kubeconfig file discovery logic appropriately checks for file existence before returning the configuration.


121-177: LGTM!

The AWS discovery implements a sensible priority order: IMDS → ECS credentials → environment variables → credentials file. The verbose logging about AWS profiles and credentials files helps users understand why discovery might not succeed.


179-234: LGTM!

The IMDS detection correctly implements IMDSv2 with token-based authentication first, then falls back to IMDSv1. The 2-second timeout is appropriate for metadata service calls. Both IMDSv2 and IMDSv1 paths properly validate role availability before returning configuration.


236-259: LGTM!

The IMDSv2 role validation correctly uses the token header and checks for a non-empty response.


261-279: LGTM!

The ECS credentials detection correctly checks both AWS_CONTAINER_CREDENTIALS_RELATIVE_URI and AWS_CONTAINER_CREDENTIALS_FULL_URI environment variables, covering different ECS configuration scenarios.


325-367: LGTM!

The GCP metadata service detection correctly checks for the service account token endpoint with proper headers and validates the JSON response structure. The 2-second timeout is appropriate.


369-421: LGTM!

The Azure discovery implements a comprehensive priority order: Managed Identity → environment variables → Azure CLI. The verbose logging helps users understand configuration requirements.


423-523: LGTM!

The Azure Managed Identity detection is comprehensive, covering App Service/Functions MSI, Container Instance MSI, and VM/AKS IMDS. Each path correctly validates the response and extracts the subscription ID when available. The HTTP requests properly use context with timeout and close response bodies.


281-323: ADC fallback for empty GCP service account key is already implemented.

The registerWithOptions() function in pkg/providers/gcp/auth.go (lines 187-200) explicitly handles empty credentials: when len(serviceAccountKey) == 0 (which occurs when gcp_service_account_key is an empty string from the metadata service), the code falls back to google.FindDefaultCredentials(), which uses Application Default Credentials (ADC). This behavior is documented in comments at pkg/providers/gcp/gcp.go lines 190-192 and implemented as designed. The concern raised in the review is already addressed by the existing codebase.

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