Skip to content

Instantly share code, notes, and snippets.

@dims
Last active August 29, 2025 12:16
Show Gist options
  • Save dims/1fc254d0e4d043ef18bbc84596785de2 to your computer and use it in GitHub Desktop.
Save dims/1fc254d0e4d043ef18bbc84596785de2 to your computer and use it in GitHub Desktop.

Revisions

  1. dims revised this gist Aug 29, 2025. 1 changed file with 439 additions and 46 deletions.
    485 changes: 439 additions & 46 deletions conformance-audit.md
    Original file line number Diff line number Diff line change
    @@ -13,6 +13,40 @@ The conformance audit process automatically tracks API endpoint usage through au
    3. **Endpoint Tracking Files**: YAML files that categorize endpoints as pending, ineligible, or conformance-ready
    4. **CI Jobs**: Automated jobs that run the analysis and report on compliance

    ## Conformance Audit Workflow

    The conformance audit system operates through a continuous integration pipeline that validates API endpoint coverage:

    ```
    ┌─────────────────┐ ┌────────────────┐ ┌──────────────────┐
    │ swagger.json │────│ Periodic CI │────│ Baseline Audit │
    │ Changes │ │ Job Runs │ │ Data Generated │
    └─────────────────┘ └────────────────┘ └──────────────────┘
    ┌─────────────────┐ ┌────────────────┐ ┌──────────────────┘
    │ Pull Request │────│ Presubmit CI │────│
    │ Submitted │ │ Job Triggers │ │
    └─────────────────┘ └────────────────┘ │
    ┌─────────────────┐ ┌────────────────┐ ┌──────────────────┐
    │ Endpoint Files │◄───│ Analysis & │◄───│ Comparison │
    │ Updated │ │ Validation │ │ Against Baseline │
    └─────────────────┘ └────────────────┘ └──────────────────┘
    ```

    ### Detailed Process Flow

    1. **API Development**: Developers add new endpoints to the Kubernetes API
    2. **Swagger Generation**: The OpenAPI specification (`swagger.json`) is updated automatically
    3. **PR Submission**: Changes are submitted as pull requests
    4. **Trigger Analysis**: Modifications to `swagger.json` trigger the presubmit audit job
    5. **Audit Collection**: Conformance tests run and generate comprehensive audit logs
    6. **Endpoint Mapping**: Scripts map audit entries to swagger operation IDs
    7. **Baseline Comparison**: PR results are compared against the latest periodic job baseline
    8. **Gap Identification**: New stable endpoints without conformance coverage are flagged
    9. **Enforcement**: Contributors must categorize endpoints appropriately
    10. **Validation**: Updated tracking files are validated for completeness

    ## CI Jobs

    ### Periodic Job: `ci-kubernetes-audit-kind-conformance`
    @@ -28,10 +62,36 @@ The conformance audit process automatically tracks API endpoint usage through au
    - Parses logs to create endpoint usage reports

    **Artifacts generated**:
    - `audit*.log`: Raw audit log files (~90-100MB)
    - `audit-endpoints.txt`: Human-readable endpoint usage summary (~27KB)
    - `audit-operations.json`: JSON mapping of operations to audit entries (~2MB)
    - `policy.yaml`: Audit policy configuration
    - `audit*.log`: Raw audit log files (~90-100MB) - Complete Kubernetes API audit trail
    - `audit-endpoints.txt`: Human-readable endpoint usage summary (~27KB) - Sorted by usage frequency
    - `audit-operations.json`: JSON mapping of operations to audit entries (~2MB) - Sample data for each operation
    - `policy.yaml`: Audit policy configuration - Defines which events to capture

    **Example audit-endpoints.txt output**:
    ```
    Total unique endpoints: 714
    Total calls: 87,241
    readCoreV1NamespacedPodStatus: 15234 calls
    listCoreV1NamespacedEvent: 8921 calls
    createCoreV1NamespacedEvent: 7345 calls
    patchCoreV1NamespacedPod: 5678 calls
    ...
    ```

    **Example audit-operations.json structure**:
    ```json
    {
    "readCoreV1NamespacedPodStatus": {
    "count": 15234,
    "sample": {
    "verb": "get",
    "uri": "/api/v1/namespaces/default/pods/test-pod/status",
    "user": "system:serviceaccount:default:test-runner"
    }
    }
    }
    ```

    **Monitoring**: [TestGrid Dashboard](https://testgrid.k8s.io/sig-arch-conformance#kind-conformance-audit)

    @@ -67,6 +127,20 @@ Endpoints that should eventually be covered by conformance tests but are not yet
    - Resource management operations (pod resizing, device classes)
    - Core API operations not yet covered

    **Example entries**:
    ```yaml
    # Pod resizing functionality
    - readCoreV1NamespacedPodStatus
    - patchCoreV1NamespacedPod

    # Dynamic Resource Allocation
    - createResourceV1alpha3NamespacedResourceClaim
    - listResourceV1alpha3NamespacedResourceClaim
    - readResourceV1alpha3NamespacedResourceClaim
    ```
    **Entry format**: Simple list of operation IDs from swagger.json that correspond to stable API endpoints that should have conformance test coverage but don't yet.
    ### Ineligible Endpoints
    Endpoints explicitly excluded from conformance testing for valid technical or policy reasons.
    @@ -82,6 +156,23 @@ Endpoints explicitly excluded from conformance testing for valid technical or po

    Each entry includes the endpoint name, exclusion reason, and link to relevant issue discussion.

    **Example entries**:
    ```yaml
    - endpoint: connectCoreV1DeleteNodeProxy
    reason: "Unable to be tested, and likely soon deprecated"
    issue: "https://github.com/kubernetes/kubernetes/issues/12345"
    - endpoint: readAuthorizationV1NamespacedLocalSubjectAccessReview
    reason: "Optional feature - not all distros implement RBAC authorization"
    issue: "https://github.com/kubernetes/kubernetes/issues/67890"
    - endpoint: connectCoreV1GetNamespacedPodPortforward
    reason: "Explicitly designed to be a debug feature"
    issue: "https://github.com/kubernetes/kubernetes/issues/24680"
    ```

    **Entry format**: Structured YAML with endpoint name, justification, and reference to community discussion.

    ## Audit Analysis Scripts

    ### `audit_log_parser.py`
    @@ -99,11 +190,33 @@ Each entry includes the endpoint name, exclusion reason, and link to relevant is
    - `audit-endpoints.txt`: Sorted list of endpoints with usage counts
    - `audit-operations.json`: Sample audit entries for each operation

    **Common errors**:
    - Network issues downloading swagger specification
    - Malformed JSON in audit log files
    - Missing or unreadable audit log files
    - Unexpected log entry formats
    **Command line usage**:
    ```bash
    # Basic usage with single audit log
    python3 audit_log_parser.py --audit-logs audit.log
    # Process multiple audit log files
    python3 audit_log_parser.py --audit-logs audit-*.log
    # Custom swagger URL and sorting
    python3 audit_log_parser.py --audit-logs audit.log \
    --swagger-url https://custom.k8s.io/swagger.json \
    --sort count
    # Output to specific file
    python3 audit_log_parser.py --audit-logs audit.log \
    --output results/
    ```

    **Common errors and solutions**:
    - **`URLError: [SSL: CERTIFICATE_VERIFY_FAILED]`**: Network issues downloading swagger specification
    - *Solution*: Check network connectivity and proxy settings
    - **`json.JSONDecodeError: Expecting value`**: Malformed JSON in audit log files
    - *Solution*: Verify audit log format and check for truncated files
    - **`FileNotFoundError: [Errno 2] No such file`**: Missing or unreadable audit log files
    - *Solution*: Verify file paths and permissions
    - **`KeyError: 'operationId'`**: Unexpected log entry formats
    - *Solution*: Ensure audit logs are from conformance test runs with proper policy

    ### `kubernetes_api_analysis.py`

    @@ -120,31 +233,88 @@ Each entry includes the endpoint name, exclusion reason, and link to relevant is
    - **Removed operations**: Previously audited endpoints no longer called
    - **Stable unused**: GA endpoints not exercised by conformance tests

    **Common errors**:
    - Missing `gsutil` CLI tool
    - Permissions issues accessing GCS buckets
    - Network connectivity problems
    - Swagger specification parsing failures
    **Command line usage**:
    ```bash
    # Basic comparison against latest CI baseline
    python3 kubernetes_api_analysis.py
    ## Enforcement Process
    # Use specific baseline file (skip auto-download)
    python3 kubernetes_api_analysis.py --baseline-file ci-audit-endpoints.txt
    ### For Pull Request Authors
    # Custom output directory
    python3 kubernetes_api_analysis.py --output-dir analysis-results/
    # Detailed verbose output
    python3 kubernetes_api_analysis.py --verbose
    ```

    When the presubmit job identifies issues, contributors must:
    **Sample output**:
    ```
    Downloading latest CI audit data...
    Found CI run: 1961316246318223360 (2025-08-29)

    Comparing operations:
    - New operations in PR: 9
    * createResourceV1alpha3NamespacedResourceClaim
    * readResourceV1alpha3NamespacedResourceClaim
    * listResourceV1alpha3ResourceSlice

    - Removed operations: 0
    - Stable operations not exercised: 127
    ```
    **Common errors and solutions**:
    - **`Command 'gsutil' not found`**: Missing `gsutil` CLI tool
    - *Solution*: Install Google Cloud SDK or use `--baseline-file` option
    - **`AccessDenied: 403 Insufficient Permission`**: Permissions issues accessing GCS buckets
    - *Solution*: Run `gcloud auth login` or use service account authentication
    - **`ConnectionError: HTTPSConnectionPool`**: Network connectivity problems
    - *Solution*: Check firewall/proxy settings for GCS access
    - **`swagger.json parsing failed`**: Swagger specification parsing failures
    - *Solution*: Verify swagger.json format and ensure it's accessible
    ## Step-by-Step Resolution Guides
    ### Marking Endpoints as Ineligible
    **Problem**: Your PR adds endpoints that shouldn't be part of conformance testing.
    **Step-by-step resolution**:
    1. **Document the reasoning**:
    ```yaml
    # Add to ineligible_endpoints.yaml
    - endpoint: connectCoreV1GetNamespacedPodExec
    reason: "Debug feature requiring special cluster permissions"
    issue: "https://github.com/kubernetes/kubernetes/issues/12345"
    ```

    2. **Create or reference issue**:
    ```markdown
    Title: Conformance exemption: Pod exec endpoint

    Body: The connectCoreV1GetNamespacedPodExec endpoint should be
    exempt from conformance testing because:

    1. It's primarily a debug/development feature
    2. Requires special RBAC permissions that conformance tests avoid
    3. Implementation varies significantly across distributions
    ```

    3. **Follow established patterns**:
    - Review existing ineligible entries for similar reasoning
    - Ensure your exemption follows community precedent
    - Get SIG approval for controversial exemptions

    1. **Stable endpoints not in pending_eligible_endpoints.yaml**:
    - Add the endpoint to `pending_eligible_endpoints.yaml`
    - Include justification for why conformance testing is deferred
    - Create or reference issue for future conformance test development
    ## Enforcement Process

    ### For Pull Request Authors

    2. **Endpoints in pending_eligible_endpoints.yaml that are now tested**:
    - Remove the endpoint from `pending_eligible_endpoints.yaml`
    - Verify the endpoint is properly covered by new conformance tests
    When the presubmit job identifies issues, contributors must follow the appropriate scenario guide above. The system enforces:

    3. **New ineligible endpoints**:
    - Add to `ineligible_endpoints.yaml` with clear reasoning
    - Link to discussion or issue explaining the exclusion
    - Ensure the exclusion follows established patterns
    1. **Stable endpoints not in pending_eligible_endpoints.yaml**: Must be added to pending list or have conformance tests
    2. **Endpoints in pending_eligible_endpoints.yaml that are now tested**: Must be removed from pending list
    3. **New ineligible endpoints**: Must be documented in ineligible list with justification

    ### Error Messages and Resolution

    @@ -156,9 +326,128 @@ When the presubmit job identifies issues, contributors must:
    - **Cause**: Endpoint now has conformance test coverage
    - **Resolution**: Remove from pending list as no longer needed

    **"Operation count mismatch between PR and CI baseline"**
    - **Cause**: API endpoints added/removed without proper categorization
    - **Resolution**: Review endpoint changes and update tracking files accordingly
    ## Technical Implementation Details

    ### Audit Log Collection

    The conformance audit system relies on comprehensive Kubernetes audit logging during test execution:

    **Audit Policy Configuration**:
    ```yaml
    # policy.yaml - Captures all API server requests
    apiVersion: audit.k8s.io/v1
    kind: Policy
    rules:
    - level: Request
    namespaces: ["default", "kube-system"]
    verbs: ["get", "list", "create", "update", "patch", "delete"]
    resources:
    - group: ""
    resources: ["*"]
    - group: "apps"
    resources: ["*"]
    ```
    **KIND Cluster Configuration**:
    ```yaml
    # kind-config.yaml - Enables audit logging
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
    kubeadmConfigPatches:
    - |
    kind: ClusterConfiguration
    apiServer:
    extraArgs:
    audit-log-path: /var/log/audit.log
    audit-policy-file: /etc/kubernetes/audit-policy.yaml
    audit-log-maxage: "30"
    audit-log-maxbackup: "3"
    audit-log-maxsize: "100"
    extraVolumes:
    - name: audit-policy
    hostPath: /etc/kubernetes/audit-policy.yaml
    mountPath: /etc/kubernetes/audit-policy.yaml
    readOnly: true
    pathType: File
    ```
    ### Script Architecture
    **audit_log_parser.py workflow**:
    1. **Download swagger.json**: Fetches latest OpenAPI specification
    2. **Parse operation mappings**: Builds lookup table of operationId → HTTP method/path
    3. **Process audit logs**: Parses each JSON log entry
    4. **Map to operations**: Matches audit entries to swagger operations using URI patterns
    5. **Generate statistics**: Counts usage and creates sample data
    6. **Output results**: Writes human-readable and machine-readable reports
    **kubernetes_api_analysis.py workflow**:
    1. **Discover baseline**: Searches GCS for latest CI audit data
    2. **Download artifacts**: Retrieves baseline audit-endpoints.txt
    3. **Parse local data**: Processes current PR's audit results
    4. **Compare datasets**: Identifies additions, removals, and stable unused endpoints
    5. **Generate report**: Outputs detailed comparison analysis
    ### Data Flow Architecture
    ```
    ┌─────────────────┐
    │ Kubernetes API │
    │ Server (KIND) │
    └─────────────────┘
    │ HTTP requests during tests
    ┌─────────────────┐
    │ Audit Log │
    │ (JSON format) │
    └─────────────────┘
    │ Raw audit events
    ┌─────────────────┐ ┌─────────────────┐
    │ audit_log_ │◄───│ swagger.json │
    │ parser.py │ │ (OpenAPI spec) │
    └─────────────────┘ └─────────────────┘
    │ Parsed operation counts
    ┌─────────────────┐ ┌─────────────────┐
    │ audit-endpoints │ │ audit-operations│
    │ .txt (summary) │ │ .json (samples) │
    └─────────────────┘ └─────────────────┘
    │ Current PR data
    ┌─────────────────┐ ┌─────────────────┐
    │ kubernetes_api_ │◄───│ CI Baseline │
    │ analysis.py │ │ (from GCS) │
    └─────────────────┘ └─────────────────┘
    │ Comparison analysis
    ┌─────────────────┐
    │ Change Report │
    │ (console output)│
    └─────────────────┘
    ```

    ### CI Integration Points

    **Presubmit trigger conditions**:
    - Changes to `api/openapi-spec/swagger.json`
    - Modifications in conformance test directories
    - Updates to endpoint classification files

    **Job execution environment**:
    - Container: `gcr.io/k8s-staging-test-infra/krte`
    - Resources: 2 CPU cores, 9GB RAM
    - Timeout: 150 minutes
    - Storage: 100GB for KIND images and audit logs

    **Artifact collection**:
    ```bash
    # CI job uploads artifacts to GCS
    gsutil -m cp -r artifacts/audit/* \
    gs://kubernetes-ci-logs/pr-logs/pull/${PULL_NUMBER}/pull-kubernetes-audit-kind-conformance/${BUILD_ID}/artifacts/audit/
    ```

    ## Troubleshooting

    @@ -205,24 +494,128 @@ python3 kubernetes_api_analysis.py

    ### For API Developers

    - **Plan conformance tests early**: Consider test coverage during API design
    - **Update tracking files promptly**: Don't let endpoints accumulate in pending status
    - **Provide clear justifications**: Document reasons for ineligible classifications
    - **Test locally**: Run audit scripts before submitting PRs
    **Update tracking files promptly**:
    ```bash
    # Good workflow - immediate tracking
    git add api/openapi-spec/swagger.json
    git add test/conformance/testdata/pending_eligible_endpoints.yaml
    git commit -m "Add new stable endpoint to pending conformance list
    The createAppsV1NamespacedDeployment endpoint is now stable but
    lacks conformance test coverage. Tracked in issue #12345."
    ```

    **Provide clear justifications**:
    ```yaml
    # Good documentation in ineligible_endpoints.yaml
    - endpoint: connectCoreV1GetNamespacedPodPortforward
    reason: "Debug feature: requires special permissions, varies by implementation"
    issue: "https://github.com/kubernetes/kubernetes/issues/24680"

    # Poor documentation
    - endpoint: someEndpoint
    reason: "doesn't work" # Too vague
    issue: "" # Missing reference
    ```
    **Test locally before submitting**:
    ```bash
    # Complete local validation workflow
    # 1. Run conformance tests with audit logging
    kind create cluster --config kind-audit-config.yaml
    export KUBECONFIG="$(kind get kubeconfig-path)"
    go test ./test/e2e/... --ginkgo.focus="Conformance"

    # 2. Parse audit logs
    python3 audit_log_parser.py --audit-logs /tmp/audit.log

    # 3. Compare against baseline
    python3 kubernetes_api_analysis.py --baseline-file previous-endpoints.txt

    # 4. Verify endpoint categorization
    diff -u previous-pending.yaml test/conformance/testdata/pending_eligible_endpoints.yaml
    ```

    ## Frequently Asked Questions

    ### For Maintainers
    ### General Questions

    - **Monitor CI job health**: Address persistent failures promptly
    - **Review categorization**: Ensure endpoint classifications remain accurate
    - **Update documentation**: Keep troubleshooting guides current
    - **Coordinate with SIGs**: Work with feature owners on conformance test development
    **Q: Why is conformance audit enforcement necessary?**
    A: Without systematic enforcement, stable APIs can reach GA status without adequate test coverage, creating technical debt and potential compatibility issues across Kubernetes distributions. The audit system ensures every stable endpoint is either tested or explicitly documented as exempt.

    **Q: How often do the CI jobs run?**
    A: The periodic job runs automatically on a schedule to maintain baseline data. The presubmit job triggers only when `swagger.json` or related conformance files are modified in pull requests.

    **Q: Can I disable the audit check for my PR?**
    A: No, the conformance audit is mandatory for API changes. However, you can satisfy the requirements by appropriately categorizing endpoints in the tracking files rather than writing tests immediately.

    ### Technical Questions

    **Q: Why doesn't the audit pick up my API endpoint usage?**
    A: Common causes:
    - Endpoint not called during conformance test execution
    - Audit logging policy doesn't capture your API group
    - URI pattern matching failed (check for typos in swagger.json)
    - Test runs in non-audited namespace

    **Q: How do I test the audit scripts locally?**
    A: Complete local workflow:
    ```bash
    # 1. Set up KIND cluster with audit logging
    kind create cluster --config kind-audit-config.yaml

    # 2. Run conformance tests
    go test ./test/e2e/... --ginkgo.focus="Conformance" --provider=skeleton

    # 3. Extract audit logs from KIND container
    docker cp kind-control-plane:/var/log/audit.log ./audit.log

    # 4. Run parser
    python3 audit_log_parser.py --audit-logs audit.log

    # 5. Compare against CI baseline
    python3 kubernetes_api_analysis.py
    ```

    ### Process Questions

    **Q: How long should endpoints stay in pending_eligible_endpoints.yaml?**
    A: No strict time limit, but best practice is to resolve within 1-2 release cycles. Long-pending endpoints should be evaluated for potential ineligibility or prioritized for test development.

    **Q: Who decides if an endpoint should be ineligible?**
    A: The relevant SIG makes the initial determination, but controversial decisions should involve SIG Architecture. All decisions must be documented with clear reasoning.

    **Q: Can alpha/beta endpoints be in the audit system?**
    A: The audit system focuses on stable (GA) endpoints, but alpha/beta endpoints may appear in audit logs if used by conformance tests. They should not be added to tracking files until reaching stability.

    **Q: What happens if I ignore the audit failures?**
    A: Pull requests with audit failures should not be merged. The presubmit is a required check that must pass before code integration.

    ## Resources

    - [Conformance Test Requirements](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)
    - [CI Job Configuration](https://github.com/kubernetes/test-infra/blob/master/config/jobs/kubernetes/sig-arch/conformance-audit.yaml)
    - [Audit Scripts](https://github.com/kubernetes/test-infra/tree/master/experiment/audit)
    - [TestGrid Monitoring](https://testgrid.k8s.io/sig-arch-conformance)
    - [Script Usage Examples](https://gist.github.com/dims/1fc254d0e4d043ef18bbc84596785de2/raw/73ae40e831367a757e8e2b47ff10836286db7d03/README.md)
    ### Essential Documentation
    - [Conformance Test Requirements](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md) - Complete testing guidelines
    - [OpenAPI Specification](https://github.com/kubernetes/kubernetes/blob/master/api/openapi-spec/swagger.json) - Source of truth for API definitions
    - [Conformance Test Suite](https://github.com/kubernetes/kubernetes/tree/master/test/conformance) - Current test implementations

    ### CI and Monitoring
    - [CI Job Configuration](https://github.com/kubernetes/test-infra/blob/master/config/jobs/kubernetes/sig-arch/conformance-audit.yaml) - Job definitions and triggers
    - [TestGrid Dashboard](https://testgrid.k8s.io/sig-arch-conformance) - Real-time job status and history
    - [Audit Scripts](https://github.com/kubernetes/test-infra/tree/master/experiment/audit) - Analysis tool source code
    - [Script Usage Guide](https://gist.github.com/dims/1fc254d0e4d043ef18bbc84596785de2/raw/73ae40e831367a757e8e2b47ff10836286db7d03/README.md) - Practical examples

    ### Data Files
    - [Current Conformance Tests](https://github.com/kubernetes/kubernetes/blob/master/test/conformance/testdata/conformance.yaml) - Active test inventory
    - [Pending Endpoints](https://github.com/kubernetes/kubernetes/blob/master/test/conformance/testdata/pending_eligible_endpoints.yaml) - Awaiting test coverage
    - [Ineligible Endpoints](https://github.com/kubernetes/kubernetes/blob/master/test/conformance/testdata/ineligible_endpoints.yaml) - Explicitly excluded from testing

    ### Community
    - **SIG Architecture**: Primary owner of conformance audit system
    - **CNCF Conformance WG**: Policy and certification oversight
    - **Kubernetes Slack**: `#sig-architecture` and `#conformance` channels for questions

    ---

    The conformance audit system represents a crucial safeguard in Kubernetes development, ensuring that the project's commitment to API stability and comprehensive testing remains intact as the platform evolves.
    The conformance audit system represents a crucial safeguard in Kubernetes development, ensuring that the project's commitment to API stability and comprehensive testing remains
    intact as the platform evolves. By automatically tracking API coverage and enforcing systematic categorization of endpoints, this system helps maintain the high quality
    and compatibility standards that make Kubernetes a reliable platform for diverse deployment environments.
  2. dims renamed this gist Aug 29, 2025. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. dims revised this gist Aug 29, 2025. 1 changed file with 228 additions and 0 deletions.
    228 changes: 228 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,228 @@
    # Kubernetes Conformance Audit

    The Kubernetes conformance audit system ensures that new API endpoints reaching General Availability (GA) are properly covered by conformance tests, preventing technical debt accumulation and maintaining API testing integrity across the project.

    ## Overview

    The conformance audit process automatically tracks API endpoint usage through audit logs and compares it against conformance test coverage, flagging gaps that need attention from contributors and maintainers.

    ### Key Components

    1. **Swagger/OpenAPI Specification**: The authoritative definition of Kubernetes APIs in [`swagger.json`](https://github.com/kubernetes/kubernetes/blob/master/api/openapi-spec/swagger.json)
    2. **Audit Log Analysis**: Scripts that parse Kubernetes audit logs to identify API endpoint usage
    3. **Endpoint Tracking Files**: YAML files that categorize endpoints as pending, ineligible, or conformance-ready
    4. **CI Jobs**: Automated jobs that run the analysis and report on compliance

    ## CI Jobs

    ### Periodic Job: `ci-kubernetes-audit-kind-conformance`

    **Purpose**: Establishes the baseline for API endpoint coverage by running conformance tests and generating audit logs.

    **When it runs**: Scheduled periodically to maintain current baseline data

    **What it does**:
    - Creates a KIND (Kubernetes in Docker) cluster
    - Runs all 425+ conformance tests
    - Generates audit logs of API endpoint usage during test execution
    - Parses logs to create endpoint usage reports

    **Artifacts generated**:
    - `audit*.log`: Raw audit log files (~90-100MB)
    - `audit-endpoints.txt`: Human-readable endpoint usage summary (~27KB)
    - `audit-operations.json`: JSON mapping of operations to audit entries (~2MB)
    - `policy.yaml`: Audit policy configuration

    **Monitoring**: [TestGrid Dashboard](https://testgrid.k8s.io/sig-arch-conformance#kind-conformance-audit)

    ### Presubmit Job: `pull-kubernetes-audit-kind-conformance`

    **Purpose**: Analyzes changes in pull requests to identify new API endpoints that need conformance test coverage.

    **When it runs**: Triggered automatically when `swagger.json` is modified in a pull request

    **What it does**:
    - Runs the same conformance tests as the periodic job
    - Compares audit results against the latest periodic job baseline
    - Identifies newly added, removed, or stable-but-untested endpoints
    - Validates endpoint categorization in tracking files

    **Additional analysis**:
    - Highlights API operation differences between PR and baseline
    - Checks for proper categorization of endpoints
    - Reports on conformance test gaps

    **Monitoring**: [TestGrid Dashboard](https://testgrid.k8s.io/sig-arch-conformance#presubmit-kind-conformance-audit)

    ## Endpoint Classification System

    ### Conformance-Eligible Endpoints

    Endpoints that should eventually be covered by conformance tests but are not yet tested.

    **File**: [`pending_eligible_endpoints.yaml`](https://github.com/kubernetes/kubernetes/blob/master/test/conformance/testdata/pending_eligible_endpoints.yaml)

    **Contains**: API endpoints awaiting conformance test development, typically for:
    - Recently added GA features
    - Resource management operations (pod resizing, device classes)
    - Core API operations not yet covered

    ### Ineligible Endpoints

    Endpoints explicitly excluded from conformance testing for valid technical or policy reasons.

    **File**: [`ineligible_endpoints.yaml`](https://github.com/kubernetes/kubernetes/blob/master/test/conformance/testdata/ineligible_endpoints.yaml)

    **Categories**:
    - **Deprecated endpoints**: Soon-to-be-removed functionality
    - **Optional features**: Components not required in all Kubernetes distributions (NetworkPolicy, HPA)
    - **Debug features**: Development and troubleshooting tools (port forwarding, pod attach)
    - **Administrative endpoints**: Operations that distributions may restrict for security
    - **Unstable features**: APIs that lack stable implementations across providers

    Each entry includes the endpoint name, exclusion reason, and link to relevant issue discussion.

    ## Audit Analysis Scripts

    ### `audit_log_parser.py`

    **Purpose**: Parses Kubernetes audit logs and maps entries to official API specifications.

    **Key functions**:
    - Downloads current `swagger.json` specification
    - Processes audit log JSON entries
    - Maps log entries to OpenAPI operation IDs
    - Generates usage statistics and operation samples

    **Outputs**:
    - Console report with endpoint counts and matches
    - `audit-endpoints.txt`: Sorted list of endpoints with usage counts
    - `audit-operations.json`: Sample audit entries for each operation

    **Common errors**:
    - Network issues downloading swagger specification
    - Malformed JSON in audit log files
    - Missing or unreadable audit log files
    - Unexpected log entry formats

    ### `kubernetes_api_analysis.py`

    **Purpose**: Compares audit results between pull requests and CI baseline to identify API changes.

    **Key functions**:
    - Downloads latest CI audit data from Google Cloud Storage
    - Compares local PR audit results against CI baseline
    - Identifies added, removed, and stable-but-unused operations
    - Provides detailed change analysis

    **Analysis types**:
    - **New operations**: API endpoints introduced in the PR
    - **Removed operations**: Previously audited endpoints no longer called
    - **Stable unused**: GA endpoints not exercised by conformance tests

    **Common errors**:
    - Missing `gsutil` CLI tool
    - Permissions issues accessing GCS buckets
    - Network connectivity problems
    - Swagger specification parsing failures

    ## Enforcement Process

    ### For Pull Request Authors

    When the presubmit job identifies issues, contributors must:

    1. **Stable endpoints not in pending_eligible_endpoints.yaml**:
    - Add the endpoint to `pending_eligible_endpoints.yaml`
    - Include justification for why conformance testing is deferred
    - Create or reference issue for future conformance test development

    2. **Endpoints in pending_eligible_endpoints.yaml that are now tested**:
    - Remove the endpoint from `pending_eligible_endpoints.yaml`
    - Verify the endpoint is properly covered by new conformance tests

    3. **New ineligible endpoints**:
    - Add to `ineligible_endpoints.yaml` with clear reasoning
    - Link to discussion or issue explaining the exclusion
    - Ensure the exclusion follows established patterns

    ### Error Messages and Resolution

    **"Stable endpoint X not found in pending_eligible_endpoints.yaml"**
    - **Cause**: New GA endpoint lacks conformance test coverage
    - **Resolution**: Add endpoint to pending list or create conformance test

    **"Endpoint X found in pending_eligible_endpoints.yaml but is being tested"**
    - **Cause**: Endpoint now has conformance test coverage
    - **Resolution**: Remove from pending list as no longer needed

    **"Operation count mismatch between PR and CI baseline"**
    - **Cause**: API endpoints added/removed without proper categorization
    - **Resolution**: Review endpoint changes and update tracking files accordingly

    ## Troubleshooting

    ### CI Job Failures

    **Build failures**: Check build logs for:
    - KIND cluster creation issues
    - Test execution failures
    - Script execution errors
    - Artifact generation problems

    **Analysis failures**: Common issues:
    - Swagger specification download problems
    - Audit log parsing errors
    - GCS access permission issues
    - File format inconsistencies

    ### Script Execution Issues

    **Local development**:
    ```bash
    # Run audit log parser
    python3 audit_log_parser.py --audit-logs audit.log

    # Compare against CI baseline
    python3 kubernetes_api_analysis.py
    ```

    **Requirements**:
    - Python 3.x
    - Network access for downloading specifications
    - `gsutil` installed for GCS operations
    - Valid audit log files in JSON format

    ### Common Resolution Steps

    1. **Check network connectivity** for specification downloads
    2. **Verify file permissions** for audit logs and output files
    3. **Validate JSON format** of audit log entries
    4. **Ensure gsutil authentication** for GCS access
    5. **Review script error output** for specific failure details

    ## Best Practices

    ### For API Developers

    - **Plan conformance tests early**: Consider test coverage during API design
    - **Update tracking files promptly**: Don't let endpoints accumulate in pending status
    - **Provide clear justifications**: Document reasons for ineligible classifications
    - **Test locally**: Run audit scripts before submitting PRs

    ### For Maintainers

    - **Monitor CI job health**: Address persistent failures promptly
    - **Review categorization**: Ensure endpoint classifications remain accurate
    - **Update documentation**: Keep troubleshooting guides current
    - **Coordinate with SIGs**: Work with feature owners on conformance test development

    ## Resources

    - [Conformance Test Requirements](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/conformance-tests.md)
    - [CI Job Configuration](https://github.com/kubernetes/test-infra/blob/master/config/jobs/kubernetes/sig-arch/conformance-audit.yaml)
    - [Audit Scripts](https://github.com/kubernetes/test-infra/tree/master/experiment/audit)
    - [TestGrid Monitoring](https://testgrid.k8s.io/sig-arch-conformance)
    - [Script Usage Examples](https://gist.github.com/dims/1fc254d0e4d043ef18bbc84596785de2/raw/73ae40e831367a757e8e2b47ff10836286db7d03/README.md)

    The conformance audit system represents a crucial safeguard in Kubernetes development, ensuring that the project's commitment to API stability and comprehensive testing remains intact as the platform evolves.
  4. dims revised this gist Aug 26, 2025. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,8 @@ Tools for analyzing Kubernetes API coverage from E2E test audit logs.

    Copy the two python scripts from https://github.com/kubernetes/test-infra/tree/master/experiment/audit to your local directory

    The example below uses https://github.com/kubernetes/kubernetes/pull/133132 which is a PR to add a new DRA test to conformance.

    ## Quick Start

    1. **Download audit logs from GCS:**
  5. dims revised this gist Aug 26, 2025. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -2,6 +2,8 @@

    Tools for analyzing Kubernetes API coverage from E2E test audit logs.

    Copy the two python scripts from https://github.com/kubernetes/test-infra/tree/master/experiment/audit to your local directory

    ## Quick Start

    1. **Download audit logs from GCS:**
  6. dims revised this gist Aug 26, 2025. 3 changed files with 186 additions and 1578 deletions.
    188 changes: 186 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,187 @@
    # Kubernetes API Audit Log Analysis

    Tools for analyzing Kubernetes API coverage from E2E test audit logs.

    ## Quick Start

    1. **Download audit logs from GCS:**
    ```bash
    gsutil -m cp -R gs://kubernetes-ci-logs/pr-logs/pull/133132/pull-kubernetes-audit-kind-conformance/1960293546019786752/artifacts/audit/ .
    ```

    2. **Parse audit logs:**
    ```bash
    python3 audit_log_parser.py --audit-logs audit/audit*.log --output audit/audit-endpoints.txt --audit-operations-json audit/audit-operations.json
    ```

    ```commandline
    Loading ineligible endpoints from: https://raw.githubusercontent.com/kubernetes/kubernetes/master/test/conformance/testdata/ineligible_endpoints.yaml
    Loaded 99 ineligible endpoints
    Loading Swagger specification from: https://raw.githubusercontent.com/kubernetes/kubernetes/refs/heads/master/api/openapi-spec/swagger.json
    Using cached Swagger specification
    Extracting resource types from Swagger specification...
    Extracted 68 resource types from Swagger spec
    Building path to operation mapping...
    Loaded 1050 API operations from Swagger spec
    Found 203 deprecated operations
    Parsing 2 audit log file(s):
    [1/2] audit/audit-2025-08-26T12-04-42.943.log
    [2/2] audit/audit.log
    Processing file 1/2: audit/audit-2025-08-26T12-04-42.943.log
    Processed 10000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 20000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 30000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 40000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 50000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 60000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 70000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 80000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 90000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Processed 100000 lines from audit/audit-2025-08-26T12-04-42.943.log...
    Completed audit/audit-2025-08-26T12-04-42.943.log: 106851 entries processed
    Processing file 2/2: audit/audit.log
    Processed 10000 lines from audit/audit.log...
    Processed 20000 lines from audit/audit.log...
    Processed 30000 lines from audit/audit.log...
    Processed 40000 lines from audit/audit.log...
    Processed 50000 lines from audit/audit.log...
    Processed 60000 lines from audit/audit.log...
    Processed 70000 lines from audit/audit.log...
    Processed 80000 lines from audit/audit.log...
    Completed audit/audit.log: 89464 entries processed
    Parsing complete:
    Total log entries: 196315
    Swagger-based matches: 87105
    Fallback matches: 731
    Unique endpoints found: 715
    Total API calls: 87836
    Skipped entries: 108479
    Results written to: audit/audit-endpoints.txt
    Generated audit/audit-operations.json with 602 operations and 1739 sample audit entries
    ```

    3. **Compare against CI baseline:**
    ```bash
    python3 kubernetes_api_analysis.py --pull-audit-endpoints audit/audit-endpoints.txt
    ```

    ```commandline
    Kubernetes API Operations Analysis
    ==================================
    Step 1: Extracting operationIds from swagger.json...
    Swagger URL: https://raw.githubusercontent.com/kubernetes/kubernetes/refs/heads/master/api/openapi-spec/swagger.json
    Output file: swagger_operations.txt
    Downloading swagger specification...
    Extracted 1062 operationIds to swagger_operations.txt
    No CI audit endpoints file specified, auto-discovering latest from GCS...
    Searching for latest CI audit run...
    Enumerating directories in gs://kubernetes-ci-logs/logs/ci-kubernetes-audit-kind-conformance...
    Found directory with finished.json: gs://kubernetes-ci-logs/logs/ci-kubernetes-audit-kind-conformance/1960318661684105216/
    Found audit file at: gs://kubernetes-ci-logs/logs/ci-kubernetes-audit-kind-conformance/1960318661684105216/artifacts/audit/audit-endpoints.txt
    Downloaded to: ci-audit-kind-conformance-audit-endpoints.txt
    Step 2: Comparing audit endpoint files...
    CI File: ci-audit-kind-conformance-audit-endpoints.txt
    Pull File: audit/audit-endpoints.txt
    Extracting operations from audit files (filtering by swagger operations)...
    SUMMARY
    =======
    Total Operations in Swagger: 1062
    Operations in CI: 508
    Operations in Pull: 517
    Operations Added: 9
    Operations Removed: 0
    Net Change: +9
    OPERATIONS ADDED IN PULL (NOT IN CI)
    ====================================
    Count: 9
    1. createResourceV1DeviceClass
    2. createResourceV1NamespacedResourceClaim
    3. createResourceV1NamespacedResourceClaimTemplate
    4. createResourceV1ResourceSlice
    5. deleteResourceV1DeviceClass
    6. deleteResourceV1NamespacedResourceClaim
    7. readResourceV1NamespacedResourceClaim
    8. replaceResourceV1NamespacedResourceClaim
    9. replaceResourceV1NamespacedResourceClaimStatus
    OPERATIONS REMOVED FROM PULL (IN CI BUT NOT PULL)
    =================================================
    Count: 0
    No operations removed.
    STABLE ENDPOINTS NOT FOUND IN PULL AUDIT LOG
    ============================================
    Count: 29
    These are stable, non-deprecated API endpoints defined in the Swagger spec
    but not exercised in the pull request audit log:
    1. connectCoreV1PostNamespacedPodExec
    2. connectCoreV1PostNamespacedPodPortforward
    3. createStorageV1VolumeAttributesClass
    4. deleteResourceV1CollectionDeviceClass
    5. deleteResourceV1NamespacedResourceClaimTemplate
    6. deleteResourceV1ResourceSlice
    7. deleteStorageV1CollectionVolumeAttributesClass
    8. deleteStorageV1VolumeAttributesClass
    9. getResourceV1APIResources
    10. listResourceV1ResourceClaimTemplateForAllNamespaces
    11. listStorageV1VolumeAttributesClass
    12. patchCoreV1NamespacedPodResize
    13. patchResourceV1DeviceClass
    14. patchResourceV1NamespacedResourceClaim
    15. patchResourceV1NamespacedResourceClaimStatus
    16. patchResourceV1NamespacedResourceClaimTemplate
    17. patchResourceV1ResourceSlice
    18. patchStorageV1VolumeAttributesClass
    19. readCoreV1NamespacedPodResize
    20. readResourceV1DeviceClass
    21. readResourceV1NamespacedResourceClaimStatus
    22. readResourceV1NamespacedResourceClaimTemplate
    23. readResourceV1ResourceSlice
    24. readStorageV1VolumeAttributesClass
    25. replaceCoreV1NamespacedPodResize
    26. replaceResourceV1DeviceClass
    27. replaceResourceV1NamespacedResourceClaimTemplate
    28. replaceResourceV1ResourceSlice
    29. replaceStorageV1VolumeAttributesClass
    Analysis complete!
    Generated files:
    - swagger_operations.txt (swagger operations list)
    ```
    ## Outputs

    ### audit_log_parser.py
    - **`audit/audit-endpoints.txt`**: Human-readable report (602 operations, 79K API calls)
    - **`audit/audit-operations.json`**: JSON with up to 5 audit samples per operation

    ### kubernetes_api_analysis.py
    - **Console output**: Comparison showing added/removed operations vs CI baseline
    - **`swagger_operations.txt`**: Complete list of 1062 Swagger operations

    ## How It Works

    Each operation flows through this pipeline:
    ```
    python3 audit_log_parser_swagger.py ./1957781493858177024/artifacts/audit/audit*.log
    ```
    swagger.json → audit_log_parser.py → audit-endpoints.txt → kubernetes_api_analysis.py
    ↓ ↓ ↓ ↓
    POST /apis/ requestURI match Line 98: | 1 "OPERATIONS ADDED"
    resource... → operationId (1 API call) (new in this PR)
    ```

    Example: `createResourceV1NamespacedResourceClaimTemplate`
    - **Swagger**: `POST /apis/resource.k8s.io/v1/namespaces/{namespace}/resourceclaimtemplates`
    - **Audit Log**: `requestURI: "/apis/resource.k8s.io/v1/namespaces/dra-9508/resourceclaimtemplates"`
    - **Parser**: Maps URI → operation ID via pattern matching
    - **Output**: Shows as "ADDED" (found in PR, missing from CI baseline)
    624 changes: 0 additions & 624 deletions audit_log_parser_swagger.py
    Original file line number Diff line number Diff line change
    @@ -1,624 +0,0 @@
    #!/usr/bin/env python3
    """
    Kubernetes Audit Log Parser with Swagger/OpenAPI Integration
    This script parses a Kubernetes audit log file and generates a list of
    Kubernetes API endpoints using the official Swagger/OpenAPI specification
    for accurate endpoint naming.
    Usage: python3 audit_log_parser_swagger.py <audit_log_file> [--output <output_file>] [--swagger-url <url>]
    """

    import json
    import re
    import sys
    import urllib.request
    import urllib.parse
    from collections import Counter
    from pathlib import Path
    import argparse
    import time


    class SwaggerEndpointMapper:
    """Maps Kubernetes API paths to proper OpenAPI operation IDs using Swagger spec.
    Requires a valid Swagger specification to operate - fails hard if not available.
    """

    def __init__(self, swagger_url=None):
    self.swagger_url = swagger_url or "https://raw.githubusercontent.com/kubernetes/kubernetes/refs/heads/master/api/openapi-spec/swagger.json"
    self.swagger_spec = None
    self.path_to_operation = {}
    self.known_resource_types = set()
    self.load_swagger_spec()

    def load_swagger_spec(self):
    """Load and parse the Kubernetes Swagger/OpenAPI specification."""
    print(f"Loading Swagger specification from: {self.swagger_url}")

    try:
    # Try to load from cache first
    cache_file = Path("kubernetes_swagger_cache.json")
    if cache_file.exists():
    cache_age = time.time() - cache_file.stat().st_mtime
    if cache_age < 3600: # Cache for 1 hour
    print("Using cached Swagger specification")
    with open(cache_file, 'r') as f:
    self.swagger_spec = json.load(f)
    self._extract_resource_types()
    self._build_path_mapping()
    return

    # Download fresh specification
    with urllib.request.urlopen(self.swagger_url, timeout=30) as response:
    self.swagger_spec = json.load(response)

    # Cache the specification
    with open(cache_file, 'w') as f:
    json.dump(self.swagger_spec, f, indent=2)

    print("Swagger specification loaded successfully")
    self._extract_resource_types()
    self._build_path_mapping()

    except urllib.error.URLError as e:
    print(f"Error downloading Swagger spec: {e}")
    print("Cannot proceed without Swagger specification")
    sys.exit(1)
    except json.JSONDecodeError as e:
    print(f"Error parsing Swagger JSON: {e}")
    print("Cannot proceed without valid Swagger specification")
    sys.exit(1)
    except Exception as e:
    print(f"Unexpected error loading Swagger spec: {e}")
    print("Cannot proceed without Swagger specification")
    sys.exit(1)

    def _build_path_mapping(self):
    """Build mapping from API paths and HTTP methods to OpenAPI operation IDs."""
    if not self.swagger_spec or 'paths' not in self.swagger_spec:
    return

    print("Building path to operation mapping...")

    for path, path_info in self.swagger_spec['paths'].items():
    for method, operation in path_info.items():
    if method.lower() in ['get', 'post', 'put', 'patch', 'delete'] and 'operationId' in operation:
    operation_id = operation['operationId']

    # Normalize the path for matching
    normalized_path = self._normalize_swagger_path(path)
    key = f"{method.lower()}:{normalized_path}"
    self.path_to_operation[key] = operation_id

    print(f"Loaded {len(self.path_to_operation)} API operations from Swagger spec")

    def _extract_resource_types(self):
    """Extract resource types from Swagger paths to avoid hardcoding."""
    if not self.swagger_spec or 'paths' not in self.swagger_spec:
    return

    print("Extracting resource types from Swagger specification...")

    # Extract resource types from paths
    for path, path_info in self.swagger_spec['paths'].items():
    # Skip non-resource paths
    if not path.startswith('/api') or '/watch/' in path:
    continue

    # Parse path segments
    segments = [s for s in path.split('/') if s]

    for i, segment in enumerate(segments):
    # Look for resource type patterns in paths
    # Resource types are typically:
    # 1. In paths like /api/v1/{resource} or /apis/group/version/{resource}
    # 2. In paths like /api/v1/namespaces/{namespace}/{resource}
    # 3. Plural nouns that aren't parameters

    if (segment and
    not segment.startswith('{') and
    not '.' in segment and
    not segment.startswith('v') and
    segment not in ['api', 'apis', 'namespaces', 'status', 'scale', 'binding',
    'proxy', 'log', 'exec', 'attach', 'portforward', 'eviction',
    'ephemeralcontainers', 'finalize', 'watch']):

    # Check if this looks like a resource type (plural noun at end of path or before {name})
    next_segment = segments[i+1] if i+1 < len(segments) else None

    # It's likely a resource type if:
    # 1. It's the last segment in the path (collection operations)
    # 2. The next segment is {name} or a parameter
    # 3. It's followed by a subresource
    if (not next_segment or
    next_segment.startswith('{') or
    next_segment in ['status', 'scale', 'binding', 'proxy', 'log', 'exec',
    'attach', 'portforward', 'eviction', 'ephemeralcontainers', 'finalize']):

    # Additional validation: should be a plural noun (heuristic)
    if len(segment) > 2 and segment.endswith('s') and segment != 'namespaces':
    self.known_resource_types.add(segment)

    # Add some critical ones that might be missed by heuristics
    critical_resources = {
    'nodes', 'namespaces', 'componentstatuses' # These don't always follow plural patterns
    }
    self.known_resource_types.update(critical_resources)

    print(f"Extracted {len(self.known_resource_types)} resource types from Swagger spec")

    def _normalize_swagger_path(self, path):
    """Normalize Swagger path template for matching against audit log URIs."""
    # Replace common Swagger path parameters with our placeholders
    normalized = path

    # Replace parameter templates
    normalized = re.sub(r'\{namespace\}', '{namespace}', normalized)
    normalized = re.sub(r'\{name\}', '{name}', normalized)
    normalized = re.sub(r'\{node\}', '{node}', normalized)
    normalized = re.sub(r'\{path\}', '{path}', normalized)

    return normalized

    def _normalize_audit_path(self, uri):
    """Normalize audit log URI for matching against Swagger paths."""
    # Remove query parameters
    uri = uri.split('?')[0]

    # Replace actual values with parameter placeholders
    normalized = re.sub(r'/namespaces/[^/]+', '/namespaces/{namespace}', uri)
    normalized = re.sub(r'/nodes/[^/]+(?=/|$)', '/nodes/{node}', normalized)

    # Replace resource names with {name} placeholder
    # Split the path and process each segment
    parts = normalized.split('/')
    result_parts = []

    for i, part in enumerate(parts):
    if i == 0 and part == '':
    result_parts.append(part)
    continue

    # Skip known path segments that shouldn't be replaced
    if part in ['api', 'apis', 'namespaces', 'status', 'scale', 'binding', 'proxy',
    'log', 'exec', 'attach', 'portforward', 'eviction', 'ephemeralcontainers',
    'watch', 'finalize', '{namespace}', '{node}', '{name}']:
    result_parts.append(part)
    continue

    # Skip API group and version segments (contain dots or start with v)
    if '.' in part or re.match(r'^v\d+', part):
    result_parts.append(part)
    continue

    # Determine if this part should be replaced with {name}
    # It should be replaced if it's after a resource type and looks like an instance name
    is_resource_name = False

    if i > 0:
    prev_part = parts[i-1]

    # This is a resource name if the previous part is a known resource type
    if prev_part in self.known_resource_types:
    # And this part looks like a resource instance name (not a subresource)
    if (part not in ['status', 'scale', 'binding', 'proxy', 'log', 'exec',
    'attach', 'portforward', 'eviction', 'ephemeralcontainers', 'finalize'] and
    not part.startswith('{')):
    is_resource_name = True

    if is_resource_name:
    result_parts.append('{name}')
    else:
    result_parts.append(part)

    return '/'.join(result_parts)

    def _k8s_verb_to_http_method(self, k8s_verb, uri):
    """Convert Kubernetes audit verb to HTTP method for Swagger lookup."""
    k8s_verb = k8s_verb.lower()

    # Map Kubernetes verbs to HTTP methods
    verb_mapping = {
    'get': 'get',
    'list': 'get',
    'watch': 'get',
    'create': 'post',
    'update': 'put',
    'patch': 'patch',
    'delete': 'delete',
    'deletecollection': 'delete',
    'connect': 'get', # For exec, attach, proxy, etc.
    }

    return verb_mapping.get(k8s_verb, k8s_verb)

    def get_operation_id(self, method, uri):
    """Get the OpenAPI operation ID for a given HTTP method and URI."""
    if not self.swagger_spec:
    return None

    # Convert Kubernetes verb to HTTP method
    http_method = self._k8s_verb_to_http_method(method, uri).lower()
    normalized_uri = self._normalize_audit_path(uri)
    key = f"{http_method}:{normalized_uri}"

    # Direct match
    if key in self.path_to_operation:
    return self.path_to_operation[key]

    # Try some common variations
    variations = [
    # Try without trailing slash
    key.rstrip('/'),
    # Try with trailing slash if not present
    key if key.endswith('/') else key + '/',
    ]

    for variation in variations:
    if variation in self.path_to_operation:
    return self.path_to_operation[variation]

    # For specific resource instance operations, try with {name} placeholder
    if '/{name}' not in normalized_uri and http_method == 'get':
    # Try adding {name} for individual resource gets
    name_variation = f"{http_method}:{normalized_uri}/{{name}}"
    if name_variation in self.path_to_operation:
    return self.path_to_operation[name_variation]

    # Fuzzy matching for complex cases
    return self._fuzzy_match_operation(http_method, normalized_uri)

    def _fuzzy_match_operation(self, method, uri):
    """Try to find a matching operation using fuzzy matching."""
    method_prefix = f"{method}:"

    # Find all operations for this method
    matching_ops = [key for key in self.path_to_operation.keys() if key.startswith(method_prefix)]

    # Score matches based on path similarity
    best_match = None
    best_score = 0

    for op_key in matching_ops:
    op_path = op_key[len(method_prefix):]
    score = self._path_similarity(uri, op_path)
    if score > best_score and score > 0.7: # Require 70% similarity
    best_score = score
    best_match = op_key

    return self.path_to_operation.get(best_match) if best_match else None

    def _path_similarity(self, path1, path2):
    """Calculate similarity between two API paths."""
    parts1 = [p for p in path1.split('/') if p]
    parts2 = [p for p in path2.split('/') if p]

    if len(parts1) != len(parts2):
    return 0

    matches = 0
    for p1, p2 in zip(parts1, parts2):
    if p1 == p2 or p1 == '{name}' or p2 == '{name}' or p1 == '{namespace}' or p2 == '{namespace}':
    matches += 1

    return matches / len(parts1) if parts1 else 0


    def convert_to_k8s_endpoint_fallback(verb, uri):
    """
    Fallback method: Convert HTTP verb and URI to Kubernetes endpoint format.
    Used when Swagger specification is not available.
    """
    # This is the same logic as the original script
    uri = uri.split('?')[0]
    uri = re.sub(r'/namespaces/[^/]+', '/namespaces/{namespace}', uri)
    uri = re.sub(r'/nodes/[^/]+', '/nodes/{node}', uri)

    verb = verb.lower()

    # Handle core API v1
    if uri.startswith('/api/v1/'):
    resource_part = uri[8:] # Remove /api/v1/

    if resource_part.startswith('namespaces/{namespace}/'):
    remaining = resource_part[23:]
    resource = remaining.split('/')[0]

    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource) and not '.' in resource:
    parts = remaining.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale', 'log', 'exec', 'attach', 'portforward', 'proxy', 'binding', 'eviction', 'ephemeralcontainers']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}CoreV1Namespaced{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}CoreV1Namespaced{resource_name}'

    else:
    resource = resource_part.split('/')[0]
    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource) and not '.' in resource:
    parts = resource_part.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}CoreV1{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}CoreV1{resource_name}'

    # Handle APIs group
    elif uri.startswith('/apis/'):
    match = re.match(r'/apis/([^/]+)/([^/]+)/(.*)', uri)
    if match:
    group, version, rest = match.groups()

    group_clean = group.replace('.k8s.io', '').replace('.', '').replace('-', '')
    group_clean = re.sub(r'[^a-zA-Z0-9]', '', group_clean)
    version_clean = version[0].upper() + version[1:] if len(version) > 1 else version.upper()

    if rest.startswith('namespaces/{namespace}/'):
    remaining = rest[23:]
    resource = remaining.split('/')[0]

    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource):
    parts = remaining.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale', 'binding']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}Namespaced{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}Namespaced{resource_name}'

    else:
    resource = rest.split('/')[0]
    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource):
    parts = rest.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}{resource_name}'

    return None


    def parse_audit_logs(file_paths, swagger_mapper=None):
    """
    Parse multiple audit log files and extract Kubernetes endpoints with counts.
    Args:
    file_paths (list): List of paths to audit log files
    swagger_mapper (SwaggerEndpointMapper): Mapper for converting to operation IDs
    Returns:
    tuple: (Counter of endpoint counts, stats dict)
    """
    endpoint_counts = Counter()
    total_entries = 0
    skipped_entries = 0
    swagger_matches = 0
    fallback_matches = 0
    total_files = len(file_paths)

    print(f"Parsing {total_files} audit log file(s):")
    for i, file_path in enumerate(file_paths, 1):
    print(f" [{i}/{total_files}] {file_path}")
    print()

    for file_index, file_path in enumerate(file_paths, 1):
    print(f"Processing file {file_index}/{total_files}: {file_path}")

    try:
    with open(file_path, 'r') as file:
    file_entries = 0
    for line_num, line in enumerate(file, 1):
    if line_num % 10000 == 0:
    print(f" Processed {line_num} lines from {file_path}...")

    line = line.strip()
    if not line:
    continue

    try:
    entry = json.loads(line)
    total_entries += 1
    file_entries += 1

    verb = entry.get('verb', '')
    request_uri = entry.get('requestURI', '')

    if verb and request_uri:
    # Use Swagger-based mapping (required)
    operation_id = swagger_mapper.get_operation_id(verb, request_uri)
    if operation_id:
    endpoint_counts[operation_id] += 1
    swagger_matches += 1
    else:
    # Try fallback parsing for edge cases
    fallback_endpoint = convert_to_k8s_endpoint_fallback(verb, request_uri)
    if fallback_endpoint:
    endpoint_counts[fallback_endpoint] += 1
    fallback_matches += 1
    else:
    skipped_entries += 1
    else:
    skipped_entries += 1

    except json.JSONDecodeError:
    skipped_entries += 1
    continue
    except Exception as e:
    skipped_entries += 1
    continue

    print(f" Completed {file_path}: {file_entries} entries processed")

    except FileNotFoundError:
    print(f"Error: File {file_path} not found")
    continue
    except Exception as e:
    print(f"Error reading file {file_path}: {e}")
    continue

    stats = {
    'total_entries': total_entries,
    'swagger_matches': swagger_matches,
    'fallback_matches': fallback_matches,
    'skipped_entries': skipped_entries,
    'unique_endpoints': len(endpoint_counts),
    'total_api_calls': sum(endpoint_counts.values())
    }

    print(f"\nParsing complete:")
    print(f" Total log entries: {total_entries}")
    print(f" Swagger-based matches: {swagger_matches}")
    print(f" Fallback matches: {fallback_matches}")
    print(f" Unique endpoints found: {len(endpoint_counts)}")
    print(f" Total API calls: {sum(endpoint_counts.values())}")
    print(f" Skipped entries: {skipped_entries}")

    return endpoint_counts, stats


    def write_results(endpoint_counts, stats, swagger_mapper=None, output_file=None, sort_by='count'):
    """
    Write results to file or stdout.
    Args:
    endpoint_counts (Counter): Endpoint counts
    stats (dict): Parsing statistics
    swagger_mapper (SwaggerEndpointMapper): Mapper for finding missing endpoints
    output_file (str, optional): Output file path
    sort_by (str): Sort method - 'count' (descending) or 'name' (alphabetical)
    """
    if sort_by == 'count':
    sorted_endpoints = endpoint_counts.most_common()
    sort_desc = "sorted by count (descending)"
    elif sort_by == 'name':
    sorted_endpoints = sorted(endpoint_counts.items(), key=lambda x: x[0].lower())
    sort_desc = "sorted alphabetically"
    else:
    sorted_endpoints = endpoint_counts.most_common()
    sort_desc = "sorted by count (descending)"

    output = []
    output.append("Kubernetes API Endpoints Found in Audit Log (Swagger-Enhanced)")
    output.append("=" * 70)
    output.append(f"Total unique endpoints: {stats['unique_endpoints']}")
    output.append(f"Total API calls: {stats['total_api_calls']}")
    output.append(f"Swagger-based matches: {stats['swagger_matches']}")
    output.append(f"Fallback matches: {stats['fallback_matches']}")
    output.append(f"Skipped entries: {stats['skipped_entries']}")
    output.append(f"Results {sort_desc}")
    output.append("")
    output.append("Endpoint Name (OpenAPI Operation ID) | Count")
    output.append("-" * 70)

    for endpoint, count in sorted_endpoints:
    output.append(f"{endpoint} | {count}")

    # Find and display missing endpoints from Swagger spec
    if swagger_mapper and swagger_mapper.path_to_operation:
    all_swagger_operations = set(swagger_mapper.path_to_operation.values())
    found_operations = set(endpoint_counts.keys())

    # Only count operations that are actually from Swagger (not fallback)
    swagger_found = found_operations & all_swagger_operations
    missing_operations = all_swagger_operations - swagger_found

    # Filter out alpha and beta versions from missing operations
    stable_missing_operations = {
    op for op in missing_operations
    if not any(version in op for version in ['V1alpha', 'V1beta', 'V2alpha', 'V2beta', 'V3alpha', 'V3beta', 'alpha', 'beta'])
    }

    if stable_missing_operations:
    filtered_count = len(missing_operations) - len(stable_missing_operations)

    output.append("")
    output.append("=" * 70)
    output.append("STABLE ENDPOINTS NOT FOUND IN AUDIT LOG")
    output.append("=" * 70)
    output.append(f"Total missing stable endpoints: {len(stable_missing_operations)}")
    if filtered_count > 0:
    output.append(f"(Filtered out {filtered_count} alpha/beta endpoints)")
    output.append(f"These are stable API endpoints defined in the Swagger spec but not exercised in this audit log:")
    output.append("")

    # Sort missing operations alphabetically
    for operation in sorted(stable_missing_operations):
    output.append(f"{operation} | NOT FOUND")

    result_text = "\n".join(output)

    if output_file:
    try:
    with open(output_file, 'w') as f:
    f.write(result_text)
    print(f"\nResults written to: {output_file}")
    except Exception as e:
    print(f"Error writing to file: {e}")
    print("\nResults:")
    print(result_text)
    else:
    print("\nResults:")
    print(result_text)


    def main():
    """Main function to parse command line arguments and run the parser."""
    parser = argparse.ArgumentParser(
    description='Parse Kubernetes audit log using official Swagger/OpenAPI specification',
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog="""
    Examples:
    python3 audit_log_parser_swagger.py audit.log
    python3 audit_log_parser_swagger.py audit1.log audit2.log
    python3 audit_log_parser_swagger.py audit.log --output results.txt
    python3 audit_log_parser_swagger.py audit*.log --sort count --output results.txt
    python3 audit_log_parser_swagger.py audit.log --swagger-url https://custom-swagger.json
    """
    )

    parser.add_argument('audit_logs', nargs='+', help='Path(s) to Kubernetes audit log file(s)')
    parser.add_argument('-o', '--output', help='Output file (default: print to stdout)')
    parser.add_argument('--swagger-url', help='Custom Swagger/OpenAPI specification URL')
    parser.add_argument('--sort', choices=['count', 'name'], default='name',
    help='Sort results by count (descending) or name (alphabetical). Default: name')

    args = parser.parse_args()

    # Initialize Swagger mapper
    swagger_mapper = SwaggerEndpointMapper(args.swagger_url)

    # Verify Swagger spec is loaded (will have already exited if not)
    if not swagger_mapper.swagger_spec:
    print("Error: Failed to load Swagger specification")
    sys.exit(1)

    # Parse the audit log(s)
    endpoint_counts, stats = parse_audit_logs(args.audit_logs, swagger_mapper)

    if not endpoint_counts:
    print("No endpoints found or error parsing file")
    sys.exit(1)

    # Write results
    write_results(endpoint_counts, stats, swagger_mapper, args.output, args.sort)


    if __name__ == '__main__':
    main()
    952 changes: 0 additions & 952 deletions endpoints.log
    Original file line number Diff line number Diff line change
    @@ -1,952 +0,0 @@
    Loading Swagger specification from: https://raw.githubusercontent.com/kubernetes/kubernetes/refs/heads/master/api/openapi-spec/swagger.json
    Using cached Swagger specification
    Extracting resource types from Swagger specification...
    Extracted 68 resource types from Swagger spec
    Building path to operation mapping...
    Loaded 1050 API operations from Swagger spec
    Parsing 2 audit log file(s):
    [1/2] ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log
    [2/2] ./1957781493858177024/artifacts/audit/audit.log

    Processing file 1/2: ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log
    Processed 10000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 20000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 30000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 40000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 50000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 60000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 70000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 80000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 90000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 100000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Completed ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log: 106451 entries processed
    Processing file 2/2: ./1957781493858177024/artifacts/audit/audit.log
    Processed 10000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 20000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 30000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 40000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 50000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 60000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 70000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 80000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Completed ./1957781493858177024/artifacts/audit/audit.log: 89604 entries processed

    Parsing complete:
    Total log entries: 196055
    Swagger-based matches: 178855
    Fallback matches: 2214
    Unique endpoints found: 652
    Total API calls: 181069
    Skipped entries: 14986

    Results:
    Kubernetes API Endpoints Found in Audit Log (Swagger-Enhanced)
    ======================================================================
    Total unique endpoints: 652
    Total API calls: 181069
    Swagger-based matches: 178855
    Fallback matches: 2214
    Skipped entries: 14986
    Results sorted alphabetically

    Endpoint Name (OpenAPI Operation ID) | Count
    ----------------------------------------------------------------------
    connectCoreV1DeleteNamespacedPodProxy | 3
    connectCoreV1DeleteNamespacedServiceProxy | 3
    connectCoreV1GetNamespacedPodAttach | 3
    connectCoreV1GetNamespacedPodExec | 324
    connectCoreV1GetNamespacedPodPortforward | 18
    connectCoreV1GetNamespacedPodProxy | 618
    connectCoreV1GetNamespacedPodProxyWithPath | 24
    connectCoreV1GetNamespacedServiceProxy | 369
    connectCoreV1GetNamespacedServiceProxyWithPath | 9
    connectCoreV1PatchNamespacedPodProxy | 3
    connectCoreV1PatchNamespacedServiceProxy | 3
    connectCoreV1PostNamespacedPodAttach | 3
    connectCoreV1PostNamespacedPodProxy | 3
    connectCoreV1PostNamespacedServiceProxy | 3
    connectCoreV1PutNamespacedPodProxy | 3
    connectCoreV1PutNamespacedServiceProxy | 3
    createAdmissionregistrationV1MutatingWebhookConfiguration | 42
    createAdmissionregistrationV1ValidatingAdmissionPolicy | 12
    createAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 12
    createAdmissionregistrationV1ValidatingWebhookConfiguration | 48
    createApiextensionsV1CustomResourceDefinition | 86
    createApiregistrationV1APIService | 134
    createAppsV1NamespacedControllerRevision | 56
    createAppsV1NamespacedDaemonSet | 20
    createAppsV1NamespacedDeployment | 150
    createAppsV1NamespacedReplicaSet | 196
    createAppsV1NamespacedStatefulSet | 16
    createAuthenticationV1TokenReview | 4
    createAuthorizationV1NamespacedLocalSubjectAccessReview | 2
    createAuthorizationV1SelfSubjectAccessReview | 2
    createAuthorizationV1SubjectAccessReview | 144
    createBatchV1NamespacedCronJob | 12
    createBatchV1NamespacedJob | 38
    createCertificatesV1CertificateSigningRequest | 12
    createCoordinationV1NamespacedLease | 16
    createCoreV1Namespace | 934
    createCoreV1NamespacedConfigMap | 2242
    createCoreV1NamespacedEndpoints | 588
    createCoreV1NamespacedEvent | 9924
    createCoreV1NamespacedLimitRange | 6
    createCoreV1NamespacedPersistentVolumeClaim | 6
    createCoreV1NamespacedPod | 1928
    createCoreV1NamespacedPodBinding | 1754
    createCoreV1NamespacedPodEviction | 14
    createCoreV1NamespacedPodsProxy | 3
    createCoreV1NamespacedPodTemplate | 1610
    createCoreV1NamespacedReplicationController | 40
    createCoreV1NamespacedResourceQuota | 30
    createCoreV1NamespacedSecret | 122
    createCoreV1NamespacedService | 566
    createCoreV1NamespacedServiceAccount | 1032
    createCoreV1NamespacedServiceAccountToken | 1970
    createCoreV1NamespacedServicesProxy | 3
    createCoreV1Node | 10
    createCoreV1PersistentVolume | 6
    createCrdpublishopenapitestemptyexamplecomV1NamespacedE2e-test-crd-publish-openapi-8330-1665-crds | 4
    createCrdpublishopenapitestfooexamplecomV1NamespacedE2e-test-crd-publish-openapi-2854-1670-crds | 14
    createCrdpublishopenapitestunknownatrootexamplecomV1NamespacedE2e-test-crd-publish-openapi-9207-892-crds | 4
    createCrdpublishopenapitestunknowninnestedexamplecomV1NamespacedE2e-test-crd-publish-openapi-3566-3325-crds | 4
    createDiscoveryV1NamespacedEndpointSlice | 568
    createEventsV1NamespacedEvent | 26
    createFlowcontrolApiserverV1FlowSchema | 28
    createFlowcontrolApiserverV1PriorityLevelConfiguration | 22
    createGroup48wp2examplecomV1NamespacedTestcrds | 2
    createGroupdwcnjexamplecomV1NamespacedTestcrds | 2
    createMygroupexamplecomV1beta1Foobf2gqas | 4
    createMygroupexamplecomV1beta1Fooblhwqas | 2
    createMygroupexamplecomV1beta1Fooq5jtpas | 2
    createMygroupexamplecomV1beta1Foormzg6as | 2
    createMygroupexamplecomV1beta1Foot5gjfas | 2
    createMygroupexamplecomV1beta1Fooxfm79as | 2
    createMygroupexamplecomV1beta1Noxus | 6
    createNetworkingV1IngressClass | 6
    createNetworkingV1IPAddress | 548
    createNetworkingV1NamespacedIngress | 6
    createNetworkingV1ServiceCIDR | 2
    createNodeV1RuntimeClass | 14
    createPolicyV1NamespacedPodDisruptionBudget | 14
    createRbacAuthorizationV1ClusterRole | 148
    createRbacAuthorizationV1ClusterRoleBinding | 126
    createRbacAuthorizationV1NamespacedRole | 24
    createRbacAuthorizationV1NamespacedRoleBinding | 76
    createResourceV1DeviceClass | 14
    createResourceV1NamespacedResourceClaim | 2
    createResourceV1NamespacedResourceClaimTemplate | 2
    createResourceV1ResourceSlice | 2
    createSchedulingV1PriorityClass | 46
    createStableexamplecomV1NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    createStableexamplecomV1NamespacedE2e-test-crd-webhook-7868-6055-crds | 4
    createStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 8
    createStableexamplecomV2NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    createStableexamplecomV2NamespacedE2e-test-crd-webhook-7868-6055-crds | 2
    createStorageV1CSIDriver | 6
    createStorageV1CSINode | 10
    createStorageV1NamespacedCSIStorageCapacity | 8
    createStorageV1StorageClass | 6
    createStorageV1VolumeAttachment | 8
    createWardleexamplecomV1alpha1NamespacedFlunders | 6
    createWebhookexamplecomV1NamespacedE2e-test-webhook-1487-2867-crds | 2
    createWebhookexamplecomV1NamespacedE2e-test-webhook-4601-6171-crds | 4
    createWebhookexamplecomV1NamespacedE2e-test-webhook-6901-9215-crds | 2
    createWebhookexamplecomV1NamespacedE2e-test-webhook-7787-791-crds | 2
    deleteAdmissionregistrationV1CollectionMutatingWebhookConfiguration | 2
    deleteAdmissionregistrationV1CollectionValidatingAdmissionPolicy | 4
    deleteAdmissionregistrationV1CollectionValidatingAdmissionPolicyBinding | 4
    deleteAdmissionregistrationV1CollectionValidatingWebhookConfiguration | 2
    deleteAdmissionregistrationV1MutatingWebhookConfiguration | 22
    deleteAdmissionregistrationV1ValidatingAdmissionPolicy | 8
    deleteAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 8
    deleteAdmissionregistrationV1ValidatingWebhookConfiguration | 34
    deleteApiextensionsV1CollectionCustomResourceDefinition | 2
    deleteApiextensionsV1CustomResourceDefinition | 64
    deleteApiregistrationV1APIService | 94
    deleteApiregistrationV1CollectionAPIService | 2
    deleteAppsV1CollectionNamespacedControllerRevision | 922
    deleteAppsV1CollectionNamespacedDaemonSet | 922
    deleteAppsV1CollectionNamespacedDeployment | 922
    deleteAppsV1CollectionNamespacedReplicaSet | 922
    deleteAppsV1CollectionNamespacedStatefulSet | 922
    deleteAppsV1NamespacedControllerRevision | 70
    deleteAppsV1NamespacedDaemonSet | 14
    deleteAppsV1NamespacedDeployment | 162
    deleteAppsV1NamespacedReplicaSet | 158
    deleteAppsV1NamespacedStatefulSet | 14
    deleteAutoscalingV2CollectionNamespacedHorizontalPodAutoscaler | 920
    deleteAutoscalingV2NamespacedHorizontalPodAutoscaler | 6
    deleteBatchV1CollectionNamespacedCronJob | 922
    deleteBatchV1CollectionNamespacedJob | 922
    deleteBatchV1NamespacedCronJob | 10
    deleteBatchV1NamespacedJob | 12
    deleteCertificatesV1alpha1NamespacedPodCertificateRequest | 4
    deleteCertificatesV1CertificateSigningRequest | 2
    deleteCertificatesV1CollectionCertificateSigningRequest | 2
    deletecollectionCrdpublishopenapitestcommongroupexamplecomV4NamespacedE2e-test-crd-publish-openapi-7000-8380-crds | 4
    deletecollectionCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-2355-crds | 8
    deletecollectionCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-8996-crds | 8
    deletecollectionCrdpublishopenapitestfooexamplecomV1NamespacedE2e-test-crd-publish-openapi-856-6904-crds | 2
    deletecollectionCrdpublishopenapitestmultitosingleverexamplecomV5NamespacedE2e-test-crd-publish-openapi-1641-8360-crds | 4
    deletecollectionCrdpublishopenapitestmultiverexamplecomV3NamespacedE2e-test-crd-publish-openapi-1056-355-crds | 4
    deletecollectionCrdpublishopenapitestunknowninnestedexamplecomV1NamespacedE2e-test-crd-publish-openapi-3566-3325-crds | 2
    deletecollectionCrdpublishopenapitestwaldoexamplecomV1beta1NamespacedE2e-test-crd-publish-openapi-856-3228-crds | 2
    deletecollectionStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 16
    deletecollectionStableexamplecomV2NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    deletecollectionStableexamplecomV2NamespacedE2e-test-crd-webhook-7868-6055-crds | 2
    deletecollectionWebhookexamplecomV1NamespacedE2e-test-webhook-4601-6171-crds | 2
    deletecollectionWebhookexamplecomV1NamespacedE2e-test-webhook-6901-9215-crds | 4
    deletecollectionWebhookexamplecomV2NamespacedE2e-test-webhook-1487-2867-crds | 4
    deletecollectionWebhookexamplecomV2NamespacedE2e-test-webhook-7787-791-crds | 2
    deleteCoordinationV1CollectionNamespacedLease | 922
    deleteCoordinationV1NamespacedLease | 2
    deleteCoreV1CollectionNamespacedConfigMap | 922
    deleteCoreV1CollectionNamespacedEndpoints | 922
    deleteCoreV1CollectionNamespacedEvent | 922
    deleteCoreV1CollectionNamespacedLimitRange | 922
    deleteCoreV1CollectionNamespacedPersistentVolumeClaim | 922
    deleteCoreV1CollectionNamespacedPod | 1210
    deleteCoreV1CollectionNamespacedPodTemplate | 922
    deleteCoreV1CollectionNamespacedReplicationController | 924
    deleteCoreV1CollectionNamespacedResourceQuota | 922
    deleteCoreV1CollectionNamespacedSecret | 922
    deleteCoreV1CollectionNamespacedService | 922
    deleteCoreV1CollectionNamespacedServiceAccount | 922
    deleteCoreV1CollectionPersistentVolume | 2
    deleteCoreV1Namespace | 928
    deleteCoreV1NamespacedConfigMap | 230
    deleteCoreV1NamespacedEndpoints | 674
    deleteCoreV1NamespacedEvent | 2
    deleteCoreV1NamespacedLimitRange | 2
    deleteCoreV1NamespacedPersistentVolumeClaim | 6
    deleteCoreV1NamespacedPod | 1846
    deleteCoreV1NamespacedPodsProxy | 3
    deleteCoreV1NamespacedPodTemplate | 2
    deleteCoreV1NamespacedReplicationController | 20
    deleteCoreV1NamespacedResourceQuota | 2
    deleteCoreV1NamespacedSecret | 64
    deleteCoreV1NamespacedService | 106
    deleteCoreV1NamespacedServiceAccount | 6
    deleteCoreV1NamespacedServicesProxy | 3
    deleteCoreV1Node | 2
    deleteCoreV1PersistentVolume | 6
    deleteDiscoveryV1CollectionNamespacedEndpointSlice | 922
    deleteDiscoveryV1NamespacedEndpointSlice | 190
    deleteEventsV1CollectionNamespacedEvent | 922
    deleteEventsV1NamespacedEvent | 2
    deleteFlowcontrolApiserverV1CollectionFlowSchema | 4
    deleteFlowcontrolApiserverV1CollectionPriorityLevelConfiguration | 4
    deleteFlowcontrolApiserverV1FlowSchema | 2
    deleteFlowcontrolApiserverV1PriorityLevelConfiguration | 2
    deleteMygroupexamplecomV1beta1Fooblhwqas | 2
    deleteMygroupexamplecomV1beta1Fooq5jtpas | 2
    deleteMygroupexamplecomV1beta1Foormzg6as | 2
    deleteMygroupexamplecomV1beta1Foot5gjfas | 2
    deleteMygroupexamplecomV1beta1Fooxfm79as | 2
    deleteMygroupexamplecomV1beta1Noxus | 6
    deleteNetworkingV1CollectionIngressClass | 2
    deleteNetworkingV1CollectionIPAddress | 2
    deleteNetworkingV1CollectionNamespacedIngress | 922
    deleteNetworkingV1CollectionNamespacedNetworkPolicy | 920
    deleteNetworkingV1IngressClass | 2
    deleteNetworkingV1IPAddress | 544
    deleteNetworkingV1NamespacedIngress | 2
    deleteNodeV1CollectionRuntimeClass | 2
    deleteNodeV1RuntimeClass | 8
    deletePolicyV1CollectionNamespacedPodDisruptionBudget | 922
    deletePolicyV1NamespacedPodDisruptionBudget | 4
    deleteRbacAuthorizationV1ClusterRole | 6
    deleteRbacAuthorizationV1ClusterRoleBinding | 12
    deleteRbacAuthorizationV1CollectionNamespacedRole | 920
    deleteRbacAuthorizationV1CollectionNamespacedRoleBinding | 920
    deleteRbacAuthorizationV1NamespacedRoleBinding | 54
    deleteResourceV1CollectionNamespacedResourceClaim | 920
    deleteResourceV1CollectionNamespacedResourceClaimTemplate | 920
    deleteResourceV1CollectionResourceSlice | 10
    deleteResourceV1DeviceClass | 14
    deleteResourceV1NamespacedResourceClaim | 2
    deleteSchedulingV1CollectionPriorityClass | 2
    deleteSchedulingV1PriorityClass | 38
    deleteStorageV1CollectionCSIDriver | 2
    deleteStorageV1CollectionCSINode | 2
    deleteStorageV1CollectionNamespacedCSIStorageCapacity | 922
    deleteStorageV1CollectionStorageClass | 2
    deleteStorageV1CollectionVolumeAttachment | 2
    deleteStorageV1CSIDriver | 2
    deleteStorageV1CSINode | 2
    deleteStorageV1NamespacedCSIStorageCapacity | 2
    deleteStorageV1StorageClass | 2
    deleteStorageV1VolumeAttachment | 4
    getAdmissionregistrationAPIGroup | 8
    getAdmissionregistrationV1APIResources | 8
    getApiextensionsAPIGroup | 4
    getApiextensionsV1APIResources | 4
    getApiregistrationAPIGroup | 2
    getApiregistrationV1APIResources | 2
    getAPIVersions | 2224
    getAppsV1APIResources | 4
    getAuthenticationAPIGroup | 2
    getAuthenticationV1APIResources | 2
    getAuthorizationAPIGroup | 2
    getAuthorizationV1APIResources | 2
    getAutoscalingAPIGroup | 2
    getAutoscalingV1APIResources | 2
    getAutoscalingV2APIResources | 2
    getBatchAPIGroup | 2
    getBatchV1APIResources | 2
    getCertificatesAPIGroup | 4
    getCertificatesV1APIResources | 4
    getCodeVersion | 16
    getCoordinationAPIGroup | 2
    getCoordinationV1APIResources | 2
    getCoreAPIVersions | 2218
    getCoreV1APIResources | 2
    getCoreV1NamespacedPodsProxy | 204
    getCoreV1NamespacedServicesProxy | 6
    getDiscoveryAPIGroup | 4
    getDiscoveryV1APIResources | 4
    getEventsAPIGroup | 2
    getEventsV1APIResources | 4
    getFlowcontrolApiserverAPIGroup | 6
    getFlowcontrolApiserverV1APIResources | 4
    getMygroupexamplecomV1beta1Foobf2gqas | 4
    getNetworkingAPIGroup | 6
    getNetworkingV1APIResources | 6
    getNodeAPIGroup | 4
    getNodeV1APIResources | 4
    getPolicyAPIGroup | 2
    getPolicyV1APIResources | 2
    getRbacAuthorizationAPIGroup | 2
    getResourceAPIGroup | 2
    getSchedulingAPIGroup | 2
    getSchedulingV1APIResources | 2
    getServiceAccountIssuerOpenIDConfiguration | 2
    getServiceAccountIssuerOpenIDKeyset | 2
    getStorageAPIGroup | 4
    getStorageV1APIResources | 4
    listAdmissionregistrationV1MutatingWebhookConfiguration | 91
    listAdmissionregistrationV1ValidatingAdmissionPolicy | 93
    listAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 93
    listAdmissionregistrationV1ValidatingWebhookConfiguration | 94
    listApiextensionsV1CustomResourceDefinition | 88
    listApiregistrationV1APIService | 91
    listAppsV1ControllerRevisionForAllNamespaces | 43
    listAppsV1DaemonSetForAllNamespaces | 52
    listAppsV1DeploymentForAllNamespaces | 53
    listAppsV1NamespacedControllerRevision | 940
    listAppsV1NamespacedDaemonSet | 960
    listAppsV1NamespacedDeployment | 984
    listAppsV1NamespacedReplicaSet | 1143
    listAppsV1NamespacedStatefulSet | 942
    listAppsV1ReplicaSetForAllNamespaces | 100
    listAppsV1StatefulSetForAllNamespaces | 98
    listAutoscalingV2HorizontalPodAutoscalerForAllNamespaces | 41
    listAutoscalingV2NamespacedHorizontalPodAutoscaler | 920
    listBatchV1CronJobForAllNamespaces | 46
    listBatchV1JobForAllNamespaces | 48
    listBatchV1NamespacedCronJob | 927
    listBatchV1NamespacedJob | 999
    listCertificatesV1CertificateSigningRequest | 74
    listCoordinationV1LeaseForAllNamespaces | 43
    listCoordinationV1NamespacedLease | 967
    listCoreV1ConfigMapForAllNamespaces | 43
    listCoreV1EndpointsForAllNamespaces | 45
    listCoreV1EventForAllNamespaces | 8
    listCoreV1LimitRangeForAllNamespaces | 85
    listCoreV1Namespace | 377
    listCoreV1NamespacedConfigMap | 6094
    listCoreV1NamespacedEndpoints | 932
    listCoreV1NamespacedEvent | 944
    listCoreV1NamespacedLimitRange | 1587
    listCoreV1NamespacedPersistentVolumeClaim | 948
    listCoreV1NamespacedPod | 3188
    listCoreV1NamespacedPodTemplate | 1134
    listCoreV1NamespacedReplicationController | 937
    listCoreV1NamespacedResourceQuota | 1001
    listCoreV1NamespacedSecret | 1190
    listCoreV1NamespacedService | 947
    listCoreV1NamespacedServiceAccount | 5383
    listCoreV1Node | 2244
    listCoreV1PersistentVolume | 206
    listCoreV1PersistentVolumeClaimForAllNamespaces | 177
    listCoreV1PodForAllNamespaces | 838
    listCoreV1PodTemplateForAllNamespaces | 42
    listCoreV1ReplicationControllerForAllNamespaces | 94
    listCoreV1ResourceQuotaForAllNamespaces | 95
    listCoreV1SecretForAllNamespaces | 85
    listCoreV1ServiceAccountForAllNamespaces | 92
    listCoreV1ServiceForAllNamespaces | 580
    listCrdpublishopenapitestcommongroupexamplecomV4NamespacedE2e-test-crd-publish-openapi-7000-8380-crds | 4
    listCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-2355-crds | 8
    listCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-8996-crds | 8
    listCrdpublishopenapitestfooexamplecomV1NamespacedE2e-test-crd-publish-openapi-856-6904-crds | 2
    listCrdpublishopenapitestmultitosingleverexamplecomV5NamespacedE2e-test-crd-publish-openapi-1641-8360-crds | 4
    listCrdpublishopenapitestmultiverexamplecomV3NamespacedE2e-test-crd-publish-openapi-1056-355-crds | 4
    listCrdpublishopenapitestunknowninnestedexamplecomV1E2e-test-crd-publish-openapi-3566-3325-crds | 190
    listCrdpublishopenapitestunknowninnestedexamplecomV1NamespacedE2e-test-crd-publish-openapi-3566-3325-crds | 2
    listCrdpublishopenapitestwaldoexamplecomV1beta1NamespacedE2e-test-crd-publish-openapi-856-3228-crds | 2
    listDiscoveryV1EndpointSliceForAllNamespaces | 322
    listDiscoveryV1NamespacedEndpointSlice | 1072
    listEventsV1EventForAllNamespaces | 4
    listEventsV1NamespacedEvent | 930
    listFlowcontrolApiserverV1FlowSchema | 92
    listFlowcontrolApiserverV1PriorityLevelConfiguration | 101
    listGroupdwcnjexamplecomV1Testcrds | 22
    listMygroupexamplecomV1beta1Noxus | 174
    listMygroupexamplecomV1Foormzg6as | 40
    listNetworkingV1IngressClass | 93
    listNetworkingV1IngressForAllNamespaces | 46
    listNetworkingV1IPAddress | 97
    listNetworkingV1NamespacedIngress | 929
    listNetworkingV1NamespacedNetworkPolicy | 920
    listNetworkingV1NetworkPolicyForAllNamespaces | 170
    listNetworkingV1ServiceCIDR | 282
    listNodeV1RuntimeClass | 240
    listPolicyV1NamespacedPodDisruptionBudget | 938
    listPolicyV1PodDisruptionBudgetForAllNamespaces | 88
    listRbacAuthorizationV1ClusterRole | 88
    listRbacAuthorizationV1ClusterRoleBinding | 86
    listRbacAuthorizationV1NamespacedRole | 920
    listRbacAuthorizationV1NamespacedRoleBinding | 920
    listRbacAuthorizationV1RoleBindingForAllNamespaces | 81
    listRbacAuthorizationV1RoleForAllNamespaces | 87
    listResourceV1DeviceClass | 89
    listResourceV1NamespacedResourceClaim | 924
    listResourceV1NamespacedResourceClaimTemplate | 920
    listResourceV1ResourceClaimForAllNamespaces | 88
    listResourceV1ResourceClaimTemplateForAllNamespaces | 41
    listResourceV1ResourceSlice | 136
    listSchedulingV1PriorityClass | 89
    listStableexamplecomV1NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 4
    listStableexamplecomV1NamespacedE2e-test-crd-webhook-7868-6055-crds | 2
    listStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 26
    listStableexamplecomV2NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    listStableexamplecomV2NamespacedE2e-test-crd-webhook-7868-6055-crds | 4
    listStorageV1CSIDriver | 275
    listStorageV1CSINode | 97
    listStorageV1CSIStorageCapacityForAllNamespaces | 91
    listStorageV1NamespacedCSIStorageCapacity | 929
    listStorageV1StorageClass | 177
    listStorageV1VolumeAttachment | 140
    listStorageV1VolumeAttributesClass | 44
    listWardleexamplecomV1alpha1NamespacedFlunders | 12
    listWebhookexamplecomV1E2e-test-webhook-6901-9215-crds | 218
    listWebhookexamplecomV1NamespacedE2e-test-webhook-4601-6171-crds | 2
    listWebhookexamplecomV1NamespacedE2e-test-webhook-6901-9215-crds | 4
    listWebhookexamplecomV2NamespacedE2e-test-webhook-1487-2867-crds | 4
    listWebhookexamplecomV2NamespacedE2e-test-webhook-7787-791-crds | 2
    patchAdmissionregistrationV1MutatingWebhookConfiguration | 2
    patchAdmissionregistrationV1ValidatingAdmissionPolicy | 2
    patchAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 2
    patchAdmissionregistrationV1ValidatingAdmissionPolicyStatus | 14
    patchAdmissionregistrationV1ValidatingWebhookConfiguration | 2
    patchApiextensionsV1CustomResourceDefinition | 8
    patchApiextensionsV1CustomResourceDefinitionStatus | 2
    patchApiregistrationV1APIService | 4
    patchApiregistrationV1APIServiceStatus | 2
    patchAppsV1NamespacedControllerRevision | 2
    patchAppsV1NamespacedDaemonSet | 8
    patchAppsV1NamespacedDaemonSetStatus | 2
    patchAppsV1NamespacedDeployment | 8
    patchAppsV1NamespacedDeploymentScale | 2
    patchAppsV1NamespacedDeploymentStatus | 4
    patchAppsV1NamespacedReplicaSet | 10
    patchAppsV1NamespacedReplicaSetScale | 2
    patchAppsV1NamespacedReplicaSetStatus | 2
    patchAppsV1NamespacedStatefulSet | 4
    patchAppsV1NamespacedStatefulSetScale | 2
    patchAppsV1NamespacedStatefulSetStatus | 2
    patchAutoscalingV2NamespacedHorizontalPodAutoscaler | 2
    patchBatchV1NamespacedCronJob | 2
    patchBatchV1NamespacedCronJobStatus | 2
    patchBatchV1NamespacedJob | 2
    patchBatchV1NamespacedJobStatus | 2
    patchCertificatesV1CertificateSigningRequest | 2
    patchCertificatesV1CertificateSigningRequestApproval | 2
    patchCertificatesV1CertificateSigningRequestStatus | 2
    patchCoordinationV1NamespacedLease | 2
    patchCoreV1Namespace | 70
    patchCoreV1NamespacedConfigMap | 4
    patchCoreV1NamespacedEndpoints | 2
    patchCoreV1NamespacedEvent | 852
    patchCoreV1NamespacedLimitRange | 2
    patchCoreV1NamespacedPersistentVolumeClaim | 2
    patchCoreV1NamespacedPersistentVolumeClaimStatus | 2
    patchCoreV1NamespacedPod | 548
    patchCoreV1NamespacedPodEphemeralcontainers | 4
    patchCoreV1NamespacedPodsProxy | 3
    patchCoreV1NamespacedPodStatus | 5108
    patchCoreV1NamespacedPodTemplate | 2
    patchCoreV1NamespacedReplicationController | 16
    patchCoreV1NamespacedReplicationControllerScale | 6
    patchCoreV1NamespacedReplicationControllerStatus | 2
    patchCoreV1NamespacedResourceQuota | 4
    patchCoreV1NamespacedResourceQuotaStatus | 4
    patchCoreV1NamespacedSecret | 2
    patchCoreV1NamespacedService | 2
    patchCoreV1NamespacedServiceAccount | 2
    patchCoreV1NamespacedServicesProxy | 3
    patchCoreV1NamespacedServiceStatus | 2
    patchCoreV1NamespaceStatus | 2
    patchCoreV1Node | 44
    patchCoreV1NodeStatus | 1530
    patchCoreV1PersistentVolume | 2
    patchCoreV1PersistentVolumeStatus | 2
    patchDiscoveryV1NamespacedEndpointSlice | 2
    patchEventsV1NamespacedEvent | 2
    patchFlowcontrolApiserverV1FlowSchema | 2
    patchFlowcontrolApiserverV1FlowSchemaStatus | 34
    patchFlowcontrolApiserverV1PriorityLevelConfiguration | 2
    patchFlowcontrolApiserverV1PriorityLevelConfigurationStatus | 2
    patchMygroupexamplecomV1beta1Fooblhwqas | 2
    patchMygroupexamplecomV1beta1Fooq5jtpas | 2
    patchMygroupexamplecomV1beta1Foormzg6as | 2
    patchMygroupexamplecomV1beta1Foot5gjfas | 2
    patchMygroupexamplecomV1beta1Fooxfm79as | 2
    patchMygroupexamplecomV1beta1Noxus | 4
    patchNetworkingV1IngressClass | 2
    patchNetworkingV1IPAddress | 2
    patchNetworkingV1NamespacedIngress | 2
    patchNetworkingV1NamespacedIngressStatus | 2
    patchNetworkingV1ServiceCIDR | 4
    patchNetworkingV1ServiceCIDRStatus | 4
    patchNodeV1RuntimeClass | 2
    patchPolicyV1NamespacedPodDisruptionBudget | 4
    patchPolicyV1NamespacedPodDisruptionBudgetStatus | 2
    patchRbacAuthorizationV1ClusterRole | 14
    patchSchedulingV1PriorityClass | 4
    patchStorageV1CSIDriver | 2
    patchStorageV1CSINode | 2
    patchStorageV1NamespacedCSIStorageCapacity | 2
    patchStorageV1StorageClass | 2
    patchStorageV1VolumeAttachment | 4
    patchStorageV1VolumeAttachmentStatus | 2
    readAdmissionregistrationV1MutatingWebhookConfiguration | 8
    readAdmissionregistrationV1ValidatingAdmissionPolicy | 8
    readAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 6
    readAdmissionregistrationV1ValidatingAdmissionPolicyStatus | 2
    readAdmissionregistrationV1ValidatingWebhookConfiguration | 8
    readApiextensionsV1CustomResourceDefinition | 6
    readApiextensionsV1CustomResourceDefinitionStatus | 2
    readApiregistrationV1APIService | 6
    readApiregistrationV1APIServiceStatus | 10
    readAppsV1NamespacedControllerRevision | 82
    readAppsV1NamespacedDaemonSet | 48
    readAppsV1NamespacedDaemonSetStatus | 2
    readAppsV1NamespacedDeployment | 354
    readAppsV1NamespacedDeploymentScale | 2
    readAppsV1NamespacedDeploymentStatus | 6
    readAppsV1NamespacedReplicaSet | 308
    readAppsV1NamespacedReplicaSetScale | 2
    readAppsV1NamespacedReplicaSetStatus | 2
    readAppsV1NamespacedStatefulSet | 132
    readAppsV1NamespacedStatefulSetScale | 2
    readAppsV1NamespacedStatefulSetStatus | 2
    readAutoscalingV2NamespacedHorizontalPodAutoscaler | 4
    readBatchV1NamespacedCronJob | 434
    readBatchV1NamespacedCronJobStatus | 2
    readBatchV1NamespacedJob | 194
    readBatchV1NamespacedJobStatus | 2
    readCertificatesV1CertificateSigningRequest | 4
    readCertificatesV1CertificateSigningRequestApproval | 2
    readCertificatesV1CertificateSigningRequestStatus | 2
    readCoordinationV1NamespacedLease | 30
    readCoreV1Namespace | 2238
    readCoreV1NamespacedConfigMap | 80
    readCoreV1NamespacedEndpoints | 1256
    readCoreV1NamespacedEvent | 6
    readCoreV1NamespacedLimitRange | 4
    readCoreV1NamespacedPersistentVolumeClaim | 12
    readCoreV1NamespacedPersistentVolumeClaimStatus | 2
    readCoreV1NamespacedPod | 18038
    readCoreV1NamespacedPodEphemeralcontainers | 4
    readCoreV1NamespacedPodLog | 1131
    readCoreV1NamespacedPodStatus | 2
    readCoreV1NamespacedPodTemplate | 6
    readCoreV1NamespacedReplicationController | 646
    readCoreV1NamespacedReplicationControllerScale | 10
    readCoreV1NamespacedReplicationControllerStatus | 2
    readCoreV1NamespacedResourceQuota | 172
    readCoreV1NamespacedResourceQuotaStatus | 2
    readCoreV1NamespacedSecret | 8
    readCoreV1NamespacedService | 76
    readCoreV1NamespacedServiceAccount | 208
    readCoreV1NamespacedServiceStatus | 2
    readCoreV1NamespaceStatus | 4
    readCoreV1Node | 202
    readCoreV1PersistentVolume | 14
    readCoreV1PersistentVolumeStatus | 2
    readDiscoveryV1NamespacedEndpointSlice | 1786
    readEventsV1NamespacedEvent | 6
    readFlowcontrolApiserverV1FlowSchema | 10
    readFlowcontrolApiserverV1FlowSchemaStatus | 2
    readFlowcontrolApiserverV1PriorityLevelConfiguration | 8
    readFlowcontrolApiserverV1PriorityLevelConfigurationStatus | 2
    readNetworkingV1IngressClass | 4
    readNetworkingV1IPAddress | 4
    readNetworkingV1NamespacedIngress | 8
    readNetworkingV1NamespacedIngressStatus | 2
    readNetworkingV1ServiceCIDR | 4
    readNetworkingV1ServiceCIDRStatus | 2
    readNodeV1RuntimeClass | 10
    readPolicyV1NamespacedPodDisruptionBudget | 62
    readPolicyV1NamespacedPodDisruptionBudgetStatus | 8
    readRbacAuthorizationV1ClusterRole | 150
    readRbacAuthorizationV1ClusterRoleBinding | 102
    readRbacAuthorizationV1NamespacedRole | 16
    readRbacAuthorizationV1NamespacedRoleBinding | 16
    readResourceV1NamespacedResourceClaim | 4
    readSchedulingV1PriorityClass | 8
    readStorageV1CSIDriver | 10
    readStorageV1CSINode | 38
    readStorageV1NamespacedCSIStorageCapacity | 4
    readStorageV1StorageClass | 6
    readStorageV1VolumeAttachment | 8
    readStorageV1VolumeAttachmentStatus | 2
    replaceAdmissionregistrationV1MutatingWebhookConfiguration | 4
    replaceAdmissionregistrationV1ValidatingAdmissionPolicy | 2
    replaceAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 2
    replaceAdmissionregistrationV1ValidatingAdmissionPolicyStatus | 2
    replaceAdmissionregistrationV1ValidatingWebhookConfiguration | 4
    replaceApiextensionsV1CustomResourceDefinition | 4
    replaceApiextensionsV1CustomResourceDefinitionStatus | 316
    replaceApiregistrationV1APIService | 2
    replaceApiregistrationV1APIServiceStatus | 4
    replaceAppsV1NamespacedControllerRevision | 10
    replaceAppsV1NamespacedDaemonSet | 4
    replaceAppsV1NamespacedDaemonSetStatus | 140
    replaceAppsV1NamespacedDeployment | 10
    replaceAppsV1NamespacedDeploymentScale | 2
    replaceAppsV1NamespacedDeploymentStatus | 800
    replaceAppsV1NamespacedReplicaSet | 46
    replaceAppsV1NamespacedReplicaSetScale | 2
    replaceAppsV1NamespacedReplicaSetStatus | 812
    replaceAppsV1NamespacedStatefulSet | 30
    replaceAppsV1NamespacedStatefulSetScale | 2
    replaceAppsV1NamespacedStatefulSetStatus | 344
    replaceAutoscalingV2NamespacedHorizontalPodAutoscaler | 2
    replaceBatchV1NamespacedCronJob | 2
    replaceBatchV1NamespacedCronJobStatus | 12
    replaceBatchV1NamespacedJob | 2
    replaceBatchV1NamespacedJobStatus | 154
    replaceCertificatesV1CertificateSigningRequest | 2
    replaceCertificatesV1CertificateSigningRequestApproval | 8
    replaceCertificatesV1CertificateSigningRequestStatus | 8
    replaceCoordinationV1NamespacedLease | 17076
    replaceCoreV1Namespace | 2
    replaceCoreV1NamespacedConfigMap | 106
    replaceCoreV1NamespacedEndpoints | 406
    replaceCoreV1NamespacedEvent | 2
    replaceCoreV1NamespacedLimitRange | 2
    replaceCoreV1NamespacedPersistentVolumeClaim | 18
    replaceCoreV1NamespacedPersistentVolumeClaimStatus | 10
    replaceCoreV1NamespacedPod | 32
    replaceCoreV1NamespacedPodEphemeralcontainers | 2
    replaceCoreV1NamespacedPodStatus | 4
    replaceCoreV1NamespacedPodTemplate | 2
    replaceCoreV1NamespacedReplicationController | 2
    replaceCoreV1NamespacedReplicationControllerScale | 2
    replaceCoreV1NamespacedReplicationControllerStatus | 774
    replaceCoreV1NamespacedResourceQuota | 2
    replaceCoreV1NamespacedResourceQuotaStatus | 100
    replaceCoreV1NamespacedSecret | 14
    replaceCoreV1NamespacedService | 24
    replaceCoreV1NamespacedServiceAccount | 2
    replaceCoreV1NamespacedServiceStatus | 2
    replaceCoreV1NamespaceFinalize | 1736
    replaceCoreV1NamespaceStatus | 942
    replaceCoreV1Node | 18
    replaceCoreV1NodeStatus | 22
    replaceCoreV1PersistentVolume | 16
    replaceCoreV1PersistentVolumeStatus | 22
    replaceDiscoveryV1NamespacedEndpointSlice | 512
    replaceEventsV1NamespacedEvent | 2
    replaceFlowcontrolApiserverV1FlowSchema | 2
    replaceFlowcontrolApiserverV1FlowSchemaStatus | 4
    replaceFlowcontrolApiserverV1PriorityLevelConfiguration | 2
    replaceFlowcontrolApiserverV1PriorityLevelConfigurationStatus | 2
    replaceNetworkingV1IngressClass | 2
    replaceNetworkingV1IPAddress | 2
    replaceNetworkingV1NamespacedIngress | 2
    replaceNetworkingV1NamespacedIngressStatus | 2
    replaceNetworkingV1ServiceCIDR | 2
    replaceNodeV1RuntimeClass | 2
    replacePolicyV1NamespacedPodDisruptionBudget | 4
    replacePolicyV1NamespacedPodDisruptionBudgetStatus | 78
    replaceResourceV1NamespacedResourceClaim | 4
    replaceResourceV1NamespacedResourceClaimStatus | 4
    replaceSchedulingV1PriorityClass | 4
    replaceStorageV1CSIDriver | 2
    replaceStorageV1CSINode | 2
    replaceStorageV1NamespacedCSIStorageCapacity | 2
    replaceStorageV1StorageClass | 2
    replaceStorageV1VolumeAttachment | 4
    replaceStorageV1VolumeAttachmentStatus | 2
    updateCoreV1NamespacedPodsProxy | 3
    updateCoreV1NamespacedServicesProxy | 3
    watchCrdpublishopenapitestunknowninnestedexamplecomV1E2e-test-crd-publish-openapi-3566-3325-crds | 291
    watchGroup48wp2examplecomV1NamespacedTestcrds | 3
    watchGroupdwcnjexamplecomV1NamespacedTestcrds | 3
    watchGroupdwcnjexamplecomV1Testcrds | 39
    watchMygroupexamplecomV1beta1Fooblhwqas | 3
    watchMygroupexamplecomV1beta1Fooq5jtpas | 3
    watchMygroupexamplecomV1beta1Foormzg6as | 3
    watchMygroupexamplecomV1beta1Foot5gjfas | 3
    watchMygroupexamplecomV1beta1Fooxfm79as | 3
    watchMygroupexamplecomV1beta1Noxus | 276
    watchMygroupexamplecomV1Fooblhwqas | 3
    watchMygroupexamplecomV1Fooq5jtpas | 3
    watchMygroupexamplecomV1Foormzg6as | 69
    watchMygroupexamplecomV1Foot5gjfas | 3
    watchMygroupexamplecomV1Fooxfm79as | 3
    watchStableexamplecomV1NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 3
    watchStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 12
    watchWebhookexamplecomV1E2e-test-webhook-6901-9215-crds | 333

    ======================================================================
    STABLE ENDPOINTS NOT FOUND IN AUDIT LOG
    ======================================================================
    Total missing stable endpoints: 239
    (Filtered out 261 alpha/beta endpoints)
    These are stable API endpoints defined in the Swagger spec but not exercised in this audit log:

    connectCoreV1DeleteNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1DeleteNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1DeleteNodeProxy | NOT FOUND
    connectCoreV1DeleteNodeProxyWithPath | NOT FOUND
    connectCoreV1GetNodeProxy | NOT FOUND
    connectCoreV1GetNodeProxyWithPath | NOT FOUND
    connectCoreV1PatchNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1PatchNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1PatchNodeProxy | NOT FOUND
    connectCoreV1PatchNodeProxyWithPath | NOT FOUND
    connectCoreV1PostNamespacedPodExec | NOT FOUND
    connectCoreV1PostNamespacedPodPortforward | NOT FOUND
    connectCoreV1PostNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1PostNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1PostNodeProxy | NOT FOUND
    connectCoreV1PostNodeProxyWithPath | NOT FOUND
    connectCoreV1PutNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1PutNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1PutNodeProxy | NOT FOUND
    connectCoreV1PutNodeProxyWithPath | NOT FOUND
    createAuthenticationV1SelfSubjectReview | NOT FOUND
    createAuthorizationV1SelfSubjectRulesReview | NOT FOUND
    createAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    createAutoscalingV2NamespacedHorizontalPodAutoscaler | NOT FOUND
    createCoreV1NamespacedBinding | NOT FOUND
    createNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    createStorageV1VolumeAttributesClass | NOT FOUND
    deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler | NOT FOUND
    deleteAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    deleteCoreV1CollectionNode | NOT FOUND
    deleteNetworkingV1CollectionServiceCIDR | NOT FOUND
    deleteNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    deleteNetworkingV1ServiceCIDR | NOT FOUND
    deleteRbacAuthorizationV1CollectionClusterRole | NOT FOUND
    deleteRbacAuthorizationV1CollectionClusterRoleBinding | NOT FOUND
    deleteRbacAuthorizationV1NamespacedRole | NOT FOUND
    deleteResourceV1CollectionDeviceClass | NOT FOUND
    deleteResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    deleteResourceV1ResourceSlice | NOT FOUND
    deleteStorageV1CollectionVolumeAttributesClass | NOT FOUND
    deleteStorageV1VolumeAttributesClass | NOT FOUND
    getAppsAPIGroup | NOT FOUND
    getInternalApiserverAPIGroup | NOT FOUND
    getRbacAuthorizationV1APIResources | NOT FOUND
    getResourceV1APIResources | NOT FOUND
    getStoragemigrationAPIGroup | NOT FOUND
    listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces | NOT FOUND
    listAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    listCoreV1ComponentStatus | NOT FOUND
    logFileHandler | NOT FOUND
    logFileListHandler | NOT FOUND
    patchAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    patchAutoscalingV2NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    patchCoreV1NamespacedPodResize | NOT FOUND
    patchNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    patchRbacAuthorizationV1ClusterRoleBinding | NOT FOUND
    patchRbacAuthorizationV1NamespacedRole | NOT FOUND
    patchRbacAuthorizationV1NamespacedRoleBinding | NOT FOUND
    patchResourceV1DeviceClass | NOT FOUND
    patchResourceV1NamespacedResourceClaim | NOT FOUND
    patchResourceV1NamespacedResourceClaimStatus | NOT FOUND
    patchResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    patchResourceV1ResourceSlice | NOT FOUND
    patchStorageV1VolumeAttributesClass | NOT FOUND
    readAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    readAutoscalingV2NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    readCoreV1ComponentStatus | NOT FOUND
    readCoreV1NamespacedPodResize | NOT FOUND
    readCoreV1NodeStatus | NOT FOUND
    readNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    readResourceV1DeviceClass | NOT FOUND
    readResourceV1NamespacedResourceClaimStatus | NOT FOUND
    readResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    readResourceV1ResourceSlice | NOT FOUND
    readStorageV1VolumeAttributesClass | NOT FOUND
    replaceAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    replaceAutoscalingV2NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    replaceCoreV1NamespacedPodResize | NOT FOUND
    replaceNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    replaceNetworkingV1ServiceCIDRStatus | NOT FOUND
    replaceRbacAuthorizationV1ClusterRole | NOT FOUND
    replaceRbacAuthorizationV1ClusterRoleBinding | NOT FOUND
    replaceRbacAuthorizationV1NamespacedRole | NOT FOUND
    replaceRbacAuthorizationV1NamespacedRoleBinding | NOT FOUND
    replaceResourceV1DeviceClass | NOT FOUND
    replaceResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    replaceResourceV1ResourceSlice | NOT FOUND
    replaceStorageV1VolumeAttributesClass | NOT FOUND
    watchAdmissionregistrationV1MutatingWebhookConfiguration | NOT FOUND
    watchAdmissionregistrationV1MutatingWebhookConfigurationList | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicy | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicyBinding | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicyBindingList | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicyList | NOT FOUND
    watchAdmissionregistrationV1ValidatingWebhookConfiguration | NOT FOUND
    watchAdmissionregistrationV1ValidatingWebhookConfigurationList | NOT FOUND
    watchApiextensionsV1CustomResourceDefinition | NOT FOUND
    watchApiextensionsV1CustomResourceDefinitionList | NOT FOUND
    watchApiregistrationV1APIService | NOT FOUND
    watchApiregistrationV1APIServiceList | NOT FOUND
    watchAppsV1ControllerRevisionListForAllNamespaces | NOT FOUND
    watchAppsV1DaemonSetListForAllNamespaces | NOT FOUND
    watchAppsV1DeploymentListForAllNamespaces | NOT FOUND
    watchAppsV1NamespacedControllerRevision | NOT FOUND
    watchAppsV1NamespacedControllerRevisionList | NOT FOUND
    watchAppsV1NamespacedDaemonSet | NOT FOUND
    watchAppsV1NamespacedDaemonSetList | NOT FOUND
    watchAppsV1NamespacedDeployment | NOT FOUND
    watchAppsV1NamespacedDeploymentList | NOT FOUND
    watchAppsV1NamespacedReplicaSet | NOT FOUND
    watchAppsV1NamespacedReplicaSetList | NOT FOUND
    watchAppsV1NamespacedStatefulSet | NOT FOUND
    watchAppsV1NamespacedStatefulSetList | NOT FOUND
    watchAppsV1ReplicaSetListForAllNamespaces | NOT FOUND
    watchAppsV1StatefulSetListForAllNamespaces | NOT FOUND
    watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces | NOT FOUND
    watchAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    watchAutoscalingV1NamespacedHorizontalPodAutoscalerList | NOT FOUND
    watchAutoscalingV2HorizontalPodAutoscalerListForAllNamespaces | NOT FOUND
    watchAutoscalingV2NamespacedHorizontalPodAutoscaler | NOT FOUND
    watchAutoscalingV2NamespacedHorizontalPodAutoscalerList | NOT FOUND
    watchBatchV1CronJobListForAllNamespaces | NOT FOUND
    watchBatchV1JobListForAllNamespaces | NOT FOUND
    watchBatchV1NamespacedCronJob | NOT FOUND
    watchBatchV1NamespacedCronJobList | NOT FOUND
    watchBatchV1NamespacedJob | NOT FOUND
    watchBatchV1NamespacedJobList | NOT FOUND
    watchCertificatesV1CertificateSigningRequest | NOT FOUND
    watchCertificatesV1CertificateSigningRequestList | NOT FOUND
    watchCoordinationV1LeaseListForAllNamespaces | NOT FOUND
    watchCoordinationV1NamespacedLease | NOT FOUND
    watchCoordinationV1NamespacedLeaseList | NOT FOUND
    watchCoreV1ConfigMapListForAllNamespaces | NOT FOUND
    watchCoreV1EndpointsListForAllNamespaces | NOT FOUND
    watchCoreV1EventListForAllNamespaces | NOT FOUND
    watchCoreV1LimitRangeListForAllNamespaces | NOT FOUND
    watchCoreV1Namespace | NOT FOUND
    watchCoreV1NamespaceList | NOT FOUND
    watchCoreV1NamespacedConfigMap | NOT FOUND
    watchCoreV1NamespacedConfigMapList | NOT FOUND
    watchCoreV1NamespacedEndpoints | NOT FOUND
    watchCoreV1NamespacedEndpointsList | NOT FOUND
    watchCoreV1NamespacedEvent | NOT FOUND
    watchCoreV1NamespacedEventList | NOT FOUND
    watchCoreV1NamespacedLimitRange | NOT FOUND
    watchCoreV1NamespacedLimitRangeList | NOT FOUND
    watchCoreV1NamespacedPersistentVolumeClaim | NOT FOUND
    watchCoreV1NamespacedPersistentVolumeClaimList | NOT FOUND
    watchCoreV1NamespacedPod | NOT FOUND
    watchCoreV1NamespacedPodList | NOT FOUND
    watchCoreV1NamespacedPodTemplate | NOT FOUND
    watchCoreV1NamespacedPodTemplateList | NOT FOUND
    watchCoreV1NamespacedReplicationController | NOT FOUND
    watchCoreV1NamespacedReplicationControllerList | NOT FOUND
    watchCoreV1NamespacedResourceQuota | NOT FOUND
    watchCoreV1NamespacedResourceQuotaList | NOT FOUND
    watchCoreV1NamespacedSecret | NOT FOUND
    watchCoreV1NamespacedSecretList | NOT FOUND
    watchCoreV1NamespacedService | NOT FOUND
    watchCoreV1NamespacedServiceAccount | NOT FOUND
    watchCoreV1NamespacedServiceAccountList | NOT FOUND
    watchCoreV1NamespacedServiceList | NOT FOUND
    watchCoreV1Node | NOT FOUND
    watchCoreV1NodeList | NOT FOUND
    watchCoreV1PersistentVolume | NOT FOUND
    watchCoreV1PersistentVolumeClaimListForAllNamespaces | NOT FOUND
    watchCoreV1PersistentVolumeList | NOT FOUND
    watchCoreV1PodListForAllNamespaces | NOT FOUND
    watchCoreV1PodTemplateListForAllNamespaces | NOT FOUND
    watchCoreV1ReplicationControllerListForAllNamespaces | NOT FOUND
    watchCoreV1ResourceQuotaListForAllNamespaces | NOT FOUND
    watchCoreV1SecretListForAllNamespaces | NOT FOUND
    watchCoreV1ServiceAccountListForAllNamespaces | NOT FOUND
    watchCoreV1ServiceListForAllNamespaces | NOT FOUND
    watchDiscoveryV1EndpointSliceListForAllNamespaces | NOT FOUND
    watchDiscoveryV1NamespacedEndpointSlice | NOT FOUND
    watchDiscoveryV1NamespacedEndpointSliceList | NOT FOUND
    watchEventsV1EventListForAllNamespaces | NOT FOUND
    watchEventsV1NamespacedEvent | NOT FOUND
    watchEventsV1NamespacedEventList | NOT FOUND
    watchFlowcontrolApiserverV1FlowSchema | NOT FOUND
    watchFlowcontrolApiserverV1FlowSchemaList | NOT FOUND
    watchFlowcontrolApiserverV1PriorityLevelConfiguration | NOT FOUND
    watchFlowcontrolApiserverV1PriorityLevelConfigurationList | NOT FOUND
    watchNetworkingV1IPAddress | NOT FOUND
    watchNetworkingV1IPAddressList | NOT FOUND
    watchNetworkingV1IngressClass | NOT FOUND
    watchNetworkingV1IngressClassList | NOT FOUND
    watchNetworkingV1IngressListForAllNamespaces | NOT FOUND
    watchNetworkingV1NamespacedIngress | NOT FOUND
    watchNetworkingV1NamespacedIngressList | NOT FOUND
    watchNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    watchNetworkingV1NamespacedNetworkPolicyList | NOT FOUND
    watchNetworkingV1NetworkPolicyListForAllNamespaces | NOT FOUND
    watchNetworkingV1ServiceCIDR | NOT FOUND
    watchNetworkingV1ServiceCIDRList | NOT FOUND
    watchNodeV1RuntimeClass | NOT FOUND
    watchNodeV1RuntimeClassList | NOT FOUND
    watchPolicyV1NamespacedPodDisruptionBudget | NOT FOUND
    watchPolicyV1NamespacedPodDisruptionBudgetList | NOT FOUND
    watchPolicyV1PodDisruptionBudgetListForAllNamespaces | NOT FOUND
    watchRbacAuthorizationV1ClusterRole | NOT FOUND
    watchRbacAuthorizationV1ClusterRoleBinding | NOT FOUND
    watchRbacAuthorizationV1ClusterRoleBindingList | NOT FOUND
    watchRbacAuthorizationV1ClusterRoleList | NOT FOUND
    watchRbacAuthorizationV1NamespacedRole | NOT FOUND
    watchRbacAuthorizationV1NamespacedRoleBinding | NOT FOUND
    watchRbacAuthorizationV1NamespacedRoleBindingList | NOT FOUND
    watchRbacAuthorizationV1NamespacedRoleList | NOT FOUND
    watchRbacAuthorizationV1RoleBindingListForAllNamespaces | NOT FOUND
    watchRbacAuthorizationV1RoleListForAllNamespaces | NOT FOUND
    watchResourceV1DeviceClass | NOT FOUND
    watchResourceV1DeviceClassList | NOT FOUND
    watchResourceV1NamespacedResourceClaim | NOT FOUND
    watchResourceV1NamespacedResourceClaimList | NOT FOUND
    watchResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    watchResourceV1NamespacedResourceClaimTemplateList | NOT FOUND
    watchResourceV1ResourceClaimListForAllNamespaces | NOT FOUND
    watchResourceV1ResourceClaimTemplateListForAllNamespaces | NOT FOUND
    watchResourceV1ResourceSlice | NOT FOUND
    watchResourceV1ResourceSliceList | NOT FOUND
    watchSchedulingV1PriorityClass | NOT FOUND
    watchSchedulingV1PriorityClassList | NOT FOUND
    watchStorageV1CSIDriver | NOT FOUND
    watchStorageV1CSIDriverList | NOT FOUND
    watchStorageV1CSINode | NOT FOUND
    watchStorageV1CSINodeList | NOT FOUND
    watchStorageV1CSIStorageCapacityListForAllNamespaces | NOT FOUND
    watchStorageV1NamespacedCSIStorageCapacity | NOT FOUND
    watchStorageV1NamespacedCSIStorageCapacityList | NOT FOUND
    watchStorageV1StorageClass | NOT FOUND
    watchStorageV1StorageClassList | NOT FOUND
    watchStorageV1VolumeAttachment | NOT FOUND
    watchStorageV1VolumeAttachmentList | NOT FOUND
    watchStorageV1VolumeAttributesClass | NOT FOUND
    watchStorageV1VolumeAttributesClassList | NOT FOUND
  7. dims revised this gist Aug 19, 2025. 1 changed file with 952 additions and 0 deletions.
    952 changes: 952 additions & 0 deletions endpoints.log
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,952 @@
    Loading Swagger specification from: https://raw.githubusercontent.com/kubernetes/kubernetes/refs/heads/master/api/openapi-spec/swagger.json
    Using cached Swagger specification
    Extracting resource types from Swagger specification...
    Extracted 68 resource types from Swagger spec
    Building path to operation mapping...
    Loaded 1050 API operations from Swagger spec
    Parsing 2 audit log file(s):
    [1/2] ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log
    [2/2] ./1957781493858177024/artifacts/audit/audit.log

    Processing file 1/2: ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log
    Processed 10000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 20000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 30000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 40000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 50000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 60000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 70000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 80000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 90000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Processed 100000 lines from ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log...
    Completed ./1957781493858177024/artifacts/audit/audit-2025-08-19T13-40-49.182.log: 106451 entries processed
    Processing file 2/2: ./1957781493858177024/artifacts/audit/audit.log
    Processed 10000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 20000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 30000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 40000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 50000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 60000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 70000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Processed 80000 lines from ./1957781493858177024/artifacts/audit/audit.log...
    Completed ./1957781493858177024/artifacts/audit/audit.log: 89604 entries processed

    Parsing complete:
    Total log entries: 196055
    Swagger-based matches: 178855
    Fallback matches: 2214
    Unique endpoints found: 652
    Total API calls: 181069
    Skipped entries: 14986

    Results:
    Kubernetes API Endpoints Found in Audit Log (Swagger-Enhanced)
    ======================================================================
    Total unique endpoints: 652
    Total API calls: 181069
    Swagger-based matches: 178855
    Fallback matches: 2214
    Skipped entries: 14986
    Results sorted alphabetically

    Endpoint Name (OpenAPI Operation ID) | Count
    ----------------------------------------------------------------------
    connectCoreV1DeleteNamespacedPodProxy | 3
    connectCoreV1DeleteNamespacedServiceProxy | 3
    connectCoreV1GetNamespacedPodAttach | 3
    connectCoreV1GetNamespacedPodExec | 324
    connectCoreV1GetNamespacedPodPortforward | 18
    connectCoreV1GetNamespacedPodProxy | 618
    connectCoreV1GetNamespacedPodProxyWithPath | 24
    connectCoreV1GetNamespacedServiceProxy | 369
    connectCoreV1GetNamespacedServiceProxyWithPath | 9
    connectCoreV1PatchNamespacedPodProxy | 3
    connectCoreV1PatchNamespacedServiceProxy | 3
    connectCoreV1PostNamespacedPodAttach | 3
    connectCoreV1PostNamespacedPodProxy | 3
    connectCoreV1PostNamespacedServiceProxy | 3
    connectCoreV1PutNamespacedPodProxy | 3
    connectCoreV1PutNamespacedServiceProxy | 3
    createAdmissionregistrationV1MutatingWebhookConfiguration | 42
    createAdmissionregistrationV1ValidatingAdmissionPolicy | 12
    createAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 12
    createAdmissionregistrationV1ValidatingWebhookConfiguration | 48
    createApiextensionsV1CustomResourceDefinition | 86
    createApiregistrationV1APIService | 134
    createAppsV1NamespacedControllerRevision | 56
    createAppsV1NamespacedDaemonSet | 20
    createAppsV1NamespacedDeployment | 150
    createAppsV1NamespacedReplicaSet | 196
    createAppsV1NamespacedStatefulSet | 16
    createAuthenticationV1TokenReview | 4
    createAuthorizationV1NamespacedLocalSubjectAccessReview | 2
    createAuthorizationV1SelfSubjectAccessReview | 2
    createAuthorizationV1SubjectAccessReview | 144
    createBatchV1NamespacedCronJob | 12
    createBatchV1NamespacedJob | 38
    createCertificatesV1CertificateSigningRequest | 12
    createCoordinationV1NamespacedLease | 16
    createCoreV1Namespace | 934
    createCoreV1NamespacedConfigMap | 2242
    createCoreV1NamespacedEndpoints | 588
    createCoreV1NamespacedEvent | 9924
    createCoreV1NamespacedLimitRange | 6
    createCoreV1NamespacedPersistentVolumeClaim | 6
    createCoreV1NamespacedPod | 1928
    createCoreV1NamespacedPodBinding | 1754
    createCoreV1NamespacedPodEviction | 14
    createCoreV1NamespacedPodsProxy | 3
    createCoreV1NamespacedPodTemplate | 1610
    createCoreV1NamespacedReplicationController | 40
    createCoreV1NamespacedResourceQuota | 30
    createCoreV1NamespacedSecret | 122
    createCoreV1NamespacedService | 566
    createCoreV1NamespacedServiceAccount | 1032
    createCoreV1NamespacedServiceAccountToken | 1970
    createCoreV1NamespacedServicesProxy | 3
    createCoreV1Node | 10
    createCoreV1PersistentVolume | 6
    createCrdpublishopenapitestemptyexamplecomV1NamespacedE2e-test-crd-publish-openapi-8330-1665-crds | 4
    createCrdpublishopenapitestfooexamplecomV1NamespacedE2e-test-crd-publish-openapi-2854-1670-crds | 14
    createCrdpublishopenapitestunknownatrootexamplecomV1NamespacedE2e-test-crd-publish-openapi-9207-892-crds | 4
    createCrdpublishopenapitestunknowninnestedexamplecomV1NamespacedE2e-test-crd-publish-openapi-3566-3325-crds | 4
    createDiscoveryV1NamespacedEndpointSlice | 568
    createEventsV1NamespacedEvent | 26
    createFlowcontrolApiserverV1FlowSchema | 28
    createFlowcontrolApiserverV1PriorityLevelConfiguration | 22
    createGroup48wp2examplecomV1NamespacedTestcrds | 2
    createGroupdwcnjexamplecomV1NamespacedTestcrds | 2
    createMygroupexamplecomV1beta1Foobf2gqas | 4
    createMygroupexamplecomV1beta1Fooblhwqas | 2
    createMygroupexamplecomV1beta1Fooq5jtpas | 2
    createMygroupexamplecomV1beta1Foormzg6as | 2
    createMygroupexamplecomV1beta1Foot5gjfas | 2
    createMygroupexamplecomV1beta1Fooxfm79as | 2
    createMygroupexamplecomV1beta1Noxus | 6
    createNetworkingV1IngressClass | 6
    createNetworkingV1IPAddress | 548
    createNetworkingV1NamespacedIngress | 6
    createNetworkingV1ServiceCIDR | 2
    createNodeV1RuntimeClass | 14
    createPolicyV1NamespacedPodDisruptionBudget | 14
    createRbacAuthorizationV1ClusterRole | 148
    createRbacAuthorizationV1ClusterRoleBinding | 126
    createRbacAuthorizationV1NamespacedRole | 24
    createRbacAuthorizationV1NamespacedRoleBinding | 76
    createResourceV1DeviceClass | 14
    createResourceV1NamespacedResourceClaim | 2
    createResourceV1NamespacedResourceClaimTemplate | 2
    createResourceV1ResourceSlice | 2
    createSchedulingV1PriorityClass | 46
    createStableexamplecomV1NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    createStableexamplecomV1NamespacedE2e-test-crd-webhook-7868-6055-crds | 4
    createStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 8
    createStableexamplecomV2NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    createStableexamplecomV2NamespacedE2e-test-crd-webhook-7868-6055-crds | 2
    createStorageV1CSIDriver | 6
    createStorageV1CSINode | 10
    createStorageV1NamespacedCSIStorageCapacity | 8
    createStorageV1StorageClass | 6
    createStorageV1VolumeAttachment | 8
    createWardleexamplecomV1alpha1NamespacedFlunders | 6
    createWebhookexamplecomV1NamespacedE2e-test-webhook-1487-2867-crds | 2
    createWebhookexamplecomV1NamespacedE2e-test-webhook-4601-6171-crds | 4
    createWebhookexamplecomV1NamespacedE2e-test-webhook-6901-9215-crds | 2
    createWebhookexamplecomV1NamespacedE2e-test-webhook-7787-791-crds | 2
    deleteAdmissionregistrationV1CollectionMutatingWebhookConfiguration | 2
    deleteAdmissionregistrationV1CollectionValidatingAdmissionPolicy | 4
    deleteAdmissionregistrationV1CollectionValidatingAdmissionPolicyBinding | 4
    deleteAdmissionregistrationV1CollectionValidatingWebhookConfiguration | 2
    deleteAdmissionregistrationV1MutatingWebhookConfiguration | 22
    deleteAdmissionregistrationV1ValidatingAdmissionPolicy | 8
    deleteAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 8
    deleteAdmissionregistrationV1ValidatingWebhookConfiguration | 34
    deleteApiextensionsV1CollectionCustomResourceDefinition | 2
    deleteApiextensionsV1CustomResourceDefinition | 64
    deleteApiregistrationV1APIService | 94
    deleteApiregistrationV1CollectionAPIService | 2
    deleteAppsV1CollectionNamespacedControllerRevision | 922
    deleteAppsV1CollectionNamespacedDaemonSet | 922
    deleteAppsV1CollectionNamespacedDeployment | 922
    deleteAppsV1CollectionNamespacedReplicaSet | 922
    deleteAppsV1CollectionNamespacedStatefulSet | 922
    deleteAppsV1NamespacedControllerRevision | 70
    deleteAppsV1NamespacedDaemonSet | 14
    deleteAppsV1NamespacedDeployment | 162
    deleteAppsV1NamespacedReplicaSet | 158
    deleteAppsV1NamespacedStatefulSet | 14
    deleteAutoscalingV2CollectionNamespacedHorizontalPodAutoscaler | 920
    deleteAutoscalingV2NamespacedHorizontalPodAutoscaler | 6
    deleteBatchV1CollectionNamespacedCronJob | 922
    deleteBatchV1CollectionNamespacedJob | 922
    deleteBatchV1NamespacedCronJob | 10
    deleteBatchV1NamespacedJob | 12
    deleteCertificatesV1alpha1NamespacedPodCertificateRequest | 4
    deleteCertificatesV1CertificateSigningRequest | 2
    deleteCertificatesV1CollectionCertificateSigningRequest | 2
    deletecollectionCrdpublishopenapitestcommongroupexamplecomV4NamespacedE2e-test-crd-publish-openapi-7000-8380-crds | 4
    deletecollectionCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-2355-crds | 8
    deletecollectionCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-8996-crds | 8
    deletecollectionCrdpublishopenapitestfooexamplecomV1NamespacedE2e-test-crd-publish-openapi-856-6904-crds | 2
    deletecollectionCrdpublishopenapitestmultitosingleverexamplecomV5NamespacedE2e-test-crd-publish-openapi-1641-8360-crds | 4
    deletecollectionCrdpublishopenapitestmultiverexamplecomV3NamespacedE2e-test-crd-publish-openapi-1056-355-crds | 4
    deletecollectionCrdpublishopenapitestunknowninnestedexamplecomV1NamespacedE2e-test-crd-publish-openapi-3566-3325-crds | 2
    deletecollectionCrdpublishopenapitestwaldoexamplecomV1beta1NamespacedE2e-test-crd-publish-openapi-856-3228-crds | 2
    deletecollectionStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 16
    deletecollectionStableexamplecomV2NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    deletecollectionStableexamplecomV2NamespacedE2e-test-crd-webhook-7868-6055-crds | 2
    deletecollectionWebhookexamplecomV1NamespacedE2e-test-webhook-4601-6171-crds | 2
    deletecollectionWebhookexamplecomV1NamespacedE2e-test-webhook-6901-9215-crds | 4
    deletecollectionWebhookexamplecomV2NamespacedE2e-test-webhook-1487-2867-crds | 4
    deletecollectionWebhookexamplecomV2NamespacedE2e-test-webhook-7787-791-crds | 2
    deleteCoordinationV1CollectionNamespacedLease | 922
    deleteCoordinationV1NamespacedLease | 2
    deleteCoreV1CollectionNamespacedConfigMap | 922
    deleteCoreV1CollectionNamespacedEndpoints | 922
    deleteCoreV1CollectionNamespacedEvent | 922
    deleteCoreV1CollectionNamespacedLimitRange | 922
    deleteCoreV1CollectionNamespacedPersistentVolumeClaim | 922
    deleteCoreV1CollectionNamespacedPod | 1210
    deleteCoreV1CollectionNamespacedPodTemplate | 922
    deleteCoreV1CollectionNamespacedReplicationController | 924
    deleteCoreV1CollectionNamespacedResourceQuota | 922
    deleteCoreV1CollectionNamespacedSecret | 922
    deleteCoreV1CollectionNamespacedService | 922
    deleteCoreV1CollectionNamespacedServiceAccount | 922
    deleteCoreV1CollectionPersistentVolume | 2
    deleteCoreV1Namespace | 928
    deleteCoreV1NamespacedConfigMap | 230
    deleteCoreV1NamespacedEndpoints | 674
    deleteCoreV1NamespacedEvent | 2
    deleteCoreV1NamespacedLimitRange | 2
    deleteCoreV1NamespacedPersistentVolumeClaim | 6
    deleteCoreV1NamespacedPod | 1846
    deleteCoreV1NamespacedPodsProxy | 3
    deleteCoreV1NamespacedPodTemplate | 2
    deleteCoreV1NamespacedReplicationController | 20
    deleteCoreV1NamespacedResourceQuota | 2
    deleteCoreV1NamespacedSecret | 64
    deleteCoreV1NamespacedService | 106
    deleteCoreV1NamespacedServiceAccount | 6
    deleteCoreV1NamespacedServicesProxy | 3
    deleteCoreV1Node | 2
    deleteCoreV1PersistentVolume | 6
    deleteDiscoveryV1CollectionNamespacedEndpointSlice | 922
    deleteDiscoveryV1NamespacedEndpointSlice | 190
    deleteEventsV1CollectionNamespacedEvent | 922
    deleteEventsV1NamespacedEvent | 2
    deleteFlowcontrolApiserverV1CollectionFlowSchema | 4
    deleteFlowcontrolApiserverV1CollectionPriorityLevelConfiguration | 4
    deleteFlowcontrolApiserverV1FlowSchema | 2
    deleteFlowcontrolApiserverV1PriorityLevelConfiguration | 2
    deleteMygroupexamplecomV1beta1Fooblhwqas | 2
    deleteMygroupexamplecomV1beta1Fooq5jtpas | 2
    deleteMygroupexamplecomV1beta1Foormzg6as | 2
    deleteMygroupexamplecomV1beta1Foot5gjfas | 2
    deleteMygroupexamplecomV1beta1Fooxfm79as | 2
    deleteMygroupexamplecomV1beta1Noxus | 6
    deleteNetworkingV1CollectionIngressClass | 2
    deleteNetworkingV1CollectionIPAddress | 2
    deleteNetworkingV1CollectionNamespacedIngress | 922
    deleteNetworkingV1CollectionNamespacedNetworkPolicy | 920
    deleteNetworkingV1IngressClass | 2
    deleteNetworkingV1IPAddress | 544
    deleteNetworkingV1NamespacedIngress | 2
    deleteNodeV1CollectionRuntimeClass | 2
    deleteNodeV1RuntimeClass | 8
    deletePolicyV1CollectionNamespacedPodDisruptionBudget | 922
    deletePolicyV1NamespacedPodDisruptionBudget | 4
    deleteRbacAuthorizationV1ClusterRole | 6
    deleteRbacAuthorizationV1ClusterRoleBinding | 12
    deleteRbacAuthorizationV1CollectionNamespacedRole | 920
    deleteRbacAuthorizationV1CollectionNamespacedRoleBinding | 920
    deleteRbacAuthorizationV1NamespacedRoleBinding | 54
    deleteResourceV1CollectionNamespacedResourceClaim | 920
    deleteResourceV1CollectionNamespacedResourceClaimTemplate | 920
    deleteResourceV1CollectionResourceSlice | 10
    deleteResourceV1DeviceClass | 14
    deleteResourceV1NamespacedResourceClaim | 2
    deleteSchedulingV1CollectionPriorityClass | 2
    deleteSchedulingV1PriorityClass | 38
    deleteStorageV1CollectionCSIDriver | 2
    deleteStorageV1CollectionCSINode | 2
    deleteStorageV1CollectionNamespacedCSIStorageCapacity | 922
    deleteStorageV1CollectionStorageClass | 2
    deleteStorageV1CollectionVolumeAttachment | 2
    deleteStorageV1CSIDriver | 2
    deleteStorageV1CSINode | 2
    deleteStorageV1NamespacedCSIStorageCapacity | 2
    deleteStorageV1StorageClass | 2
    deleteStorageV1VolumeAttachment | 4
    getAdmissionregistrationAPIGroup | 8
    getAdmissionregistrationV1APIResources | 8
    getApiextensionsAPIGroup | 4
    getApiextensionsV1APIResources | 4
    getApiregistrationAPIGroup | 2
    getApiregistrationV1APIResources | 2
    getAPIVersions | 2224
    getAppsV1APIResources | 4
    getAuthenticationAPIGroup | 2
    getAuthenticationV1APIResources | 2
    getAuthorizationAPIGroup | 2
    getAuthorizationV1APIResources | 2
    getAutoscalingAPIGroup | 2
    getAutoscalingV1APIResources | 2
    getAutoscalingV2APIResources | 2
    getBatchAPIGroup | 2
    getBatchV1APIResources | 2
    getCertificatesAPIGroup | 4
    getCertificatesV1APIResources | 4
    getCodeVersion | 16
    getCoordinationAPIGroup | 2
    getCoordinationV1APIResources | 2
    getCoreAPIVersions | 2218
    getCoreV1APIResources | 2
    getCoreV1NamespacedPodsProxy | 204
    getCoreV1NamespacedServicesProxy | 6
    getDiscoveryAPIGroup | 4
    getDiscoveryV1APIResources | 4
    getEventsAPIGroup | 2
    getEventsV1APIResources | 4
    getFlowcontrolApiserverAPIGroup | 6
    getFlowcontrolApiserverV1APIResources | 4
    getMygroupexamplecomV1beta1Foobf2gqas | 4
    getNetworkingAPIGroup | 6
    getNetworkingV1APIResources | 6
    getNodeAPIGroup | 4
    getNodeV1APIResources | 4
    getPolicyAPIGroup | 2
    getPolicyV1APIResources | 2
    getRbacAuthorizationAPIGroup | 2
    getResourceAPIGroup | 2
    getSchedulingAPIGroup | 2
    getSchedulingV1APIResources | 2
    getServiceAccountIssuerOpenIDConfiguration | 2
    getServiceAccountIssuerOpenIDKeyset | 2
    getStorageAPIGroup | 4
    getStorageV1APIResources | 4
    listAdmissionregistrationV1MutatingWebhookConfiguration | 91
    listAdmissionregistrationV1ValidatingAdmissionPolicy | 93
    listAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 93
    listAdmissionregistrationV1ValidatingWebhookConfiguration | 94
    listApiextensionsV1CustomResourceDefinition | 88
    listApiregistrationV1APIService | 91
    listAppsV1ControllerRevisionForAllNamespaces | 43
    listAppsV1DaemonSetForAllNamespaces | 52
    listAppsV1DeploymentForAllNamespaces | 53
    listAppsV1NamespacedControllerRevision | 940
    listAppsV1NamespacedDaemonSet | 960
    listAppsV1NamespacedDeployment | 984
    listAppsV1NamespacedReplicaSet | 1143
    listAppsV1NamespacedStatefulSet | 942
    listAppsV1ReplicaSetForAllNamespaces | 100
    listAppsV1StatefulSetForAllNamespaces | 98
    listAutoscalingV2HorizontalPodAutoscalerForAllNamespaces | 41
    listAutoscalingV2NamespacedHorizontalPodAutoscaler | 920
    listBatchV1CronJobForAllNamespaces | 46
    listBatchV1JobForAllNamespaces | 48
    listBatchV1NamespacedCronJob | 927
    listBatchV1NamespacedJob | 999
    listCertificatesV1CertificateSigningRequest | 74
    listCoordinationV1LeaseForAllNamespaces | 43
    listCoordinationV1NamespacedLease | 967
    listCoreV1ConfigMapForAllNamespaces | 43
    listCoreV1EndpointsForAllNamespaces | 45
    listCoreV1EventForAllNamespaces | 8
    listCoreV1LimitRangeForAllNamespaces | 85
    listCoreV1Namespace | 377
    listCoreV1NamespacedConfigMap | 6094
    listCoreV1NamespacedEndpoints | 932
    listCoreV1NamespacedEvent | 944
    listCoreV1NamespacedLimitRange | 1587
    listCoreV1NamespacedPersistentVolumeClaim | 948
    listCoreV1NamespacedPod | 3188
    listCoreV1NamespacedPodTemplate | 1134
    listCoreV1NamespacedReplicationController | 937
    listCoreV1NamespacedResourceQuota | 1001
    listCoreV1NamespacedSecret | 1190
    listCoreV1NamespacedService | 947
    listCoreV1NamespacedServiceAccount | 5383
    listCoreV1Node | 2244
    listCoreV1PersistentVolume | 206
    listCoreV1PersistentVolumeClaimForAllNamespaces | 177
    listCoreV1PodForAllNamespaces | 838
    listCoreV1PodTemplateForAllNamespaces | 42
    listCoreV1ReplicationControllerForAllNamespaces | 94
    listCoreV1ResourceQuotaForAllNamespaces | 95
    listCoreV1SecretForAllNamespaces | 85
    listCoreV1ServiceAccountForAllNamespaces | 92
    listCoreV1ServiceForAllNamespaces | 580
    listCrdpublishopenapitestcommongroupexamplecomV4NamespacedE2e-test-crd-publish-openapi-7000-8380-crds | 4
    listCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-2355-crds | 8
    listCrdpublishopenapitestcommongroupexamplecomV6NamespacedE2e-test-crd-publish-openapi-8212-8996-crds | 8
    listCrdpublishopenapitestfooexamplecomV1NamespacedE2e-test-crd-publish-openapi-856-6904-crds | 2
    listCrdpublishopenapitestmultitosingleverexamplecomV5NamespacedE2e-test-crd-publish-openapi-1641-8360-crds | 4
    listCrdpublishopenapitestmultiverexamplecomV3NamespacedE2e-test-crd-publish-openapi-1056-355-crds | 4
    listCrdpublishopenapitestunknowninnestedexamplecomV1E2e-test-crd-publish-openapi-3566-3325-crds | 190
    listCrdpublishopenapitestunknowninnestedexamplecomV1NamespacedE2e-test-crd-publish-openapi-3566-3325-crds | 2
    listCrdpublishopenapitestwaldoexamplecomV1beta1NamespacedE2e-test-crd-publish-openapi-856-3228-crds | 2
    listDiscoveryV1EndpointSliceForAllNamespaces | 322
    listDiscoveryV1NamespacedEndpointSlice | 1072
    listEventsV1EventForAllNamespaces | 4
    listEventsV1NamespacedEvent | 930
    listFlowcontrolApiserverV1FlowSchema | 92
    listFlowcontrolApiserverV1PriorityLevelConfiguration | 101
    listGroupdwcnjexamplecomV1Testcrds | 22
    listMygroupexamplecomV1beta1Noxus | 174
    listMygroupexamplecomV1Foormzg6as | 40
    listNetworkingV1IngressClass | 93
    listNetworkingV1IngressForAllNamespaces | 46
    listNetworkingV1IPAddress | 97
    listNetworkingV1NamespacedIngress | 929
    listNetworkingV1NamespacedNetworkPolicy | 920
    listNetworkingV1NetworkPolicyForAllNamespaces | 170
    listNetworkingV1ServiceCIDR | 282
    listNodeV1RuntimeClass | 240
    listPolicyV1NamespacedPodDisruptionBudget | 938
    listPolicyV1PodDisruptionBudgetForAllNamespaces | 88
    listRbacAuthorizationV1ClusterRole | 88
    listRbacAuthorizationV1ClusterRoleBinding | 86
    listRbacAuthorizationV1NamespacedRole | 920
    listRbacAuthorizationV1NamespacedRoleBinding | 920
    listRbacAuthorizationV1RoleBindingForAllNamespaces | 81
    listRbacAuthorizationV1RoleForAllNamespaces | 87
    listResourceV1DeviceClass | 89
    listResourceV1NamespacedResourceClaim | 924
    listResourceV1NamespacedResourceClaimTemplate | 920
    listResourceV1ResourceClaimForAllNamespaces | 88
    listResourceV1ResourceClaimTemplateForAllNamespaces | 41
    listResourceV1ResourceSlice | 136
    listSchedulingV1PriorityClass | 89
    listStableexamplecomV1NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 4
    listStableexamplecomV1NamespacedE2e-test-crd-webhook-7868-6055-crds | 2
    listStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 26
    listStableexamplecomV2NamespacedE2e-test-crd-webhook-7857-9829-crds | 2
    listStableexamplecomV2NamespacedE2e-test-crd-webhook-7868-6055-crds | 4
    listStorageV1CSIDriver | 275
    listStorageV1CSINode | 97
    listStorageV1CSIStorageCapacityForAllNamespaces | 91
    listStorageV1NamespacedCSIStorageCapacity | 929
    listStorageV1StorageClass | 177
    listStorageV1VolumeAttachment | 140
    listStorageV1VolumeAttributesClass | 44
    listWardleexamplecomV1alpha1NamespacedFlunders | 12
    listWebhookexamplecomV1E2e-test-webhook-6901-9215-crds | 218
    listWebhookexamplecomV1NamespacedE2e-test-webhook-4601-6171-crds | 2
    listWebhookexamplecomV1NamespacedE2e-test-webhook-6901-9215-crds | 4
    listWebhookexamplecomV2NamespacedE2e-test-webhook-1487-2867-crds | 4
    listWebhookexamplecomV2NamespacedE2e-test-webhook-7787-791-crds | 2
    patchAdmissionregistrationV1MutatingWebhookConfiguration | 2
    patchAdmissionregistrationV1ValidatingAdmissionPolicy | 2
    patchAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 2
    patchAdmissionregistrationV1ValidatingAdmissionPolicyStatus | 14
    patchAdmissionregistrationV1ValidatingWebhookConfiguration | 2
    patchApiextensionsV1CustomResourceDefinition | 8
    patchApiextensionsV1CustomResourceDefinitionStatus | 2
    patchApiregistrationV1APIService | 4
    patchApiregistrationV1APIServiceStatus | 2
    patchAppsV1NamespacedControllerRevision | 2
    patchAppsV1NamespacedDaemonSet | 8
    patchAppsV1NamespacedDaemonSetStatus | 2
    patchAppsV1NamespacedDeployment | 8
    patchAppsV1NamespacedDeploymentScale | 2
    patchAppsV1NamespacedDeploymentStatus | 4
    patchAppsV1NamespacedReplicaSet | 10
    patchAppsV1NamespacedReplicaSetScale | 2
    patchAppsV1NamespacedReplicaSetStatus | 2
    patchAppsV1NamespacedStatefulSet | 4
    patchAppsV1NamespacedStatefulSetScale | 2
    patchAppsV1NamespacedStatefulSetStatus | 2
    patchAutoscalingV2NamespacedHorizontalPodAutoscaler | 2
    patchBatchV1NamespacedCronJob | 2
    patchBatchV1NamespacedCronJobStatus | 2
    patchBatchV1NamespacedJob | 2
    patchBatchV1NamespacedJobStatus | 2
    patchCertificatesV1CertificateSigningRequest | 2
    patchCertificatesV1CertificateSigningRequestApproval | 2
    patchCertificatesV1CertificateSigningRequestStatus | 2
    patchCoordinationV1NamespacedLease | 2
    patchCoreV1Namespace | 70
    patchCoreV1NamespacedConfigMap | 4
    patchCoreV1NamespacedEndpoints | 2
    patchCoreV1NamespacedEvent | 852
    patchCoreV1NamespacedLimitRange | 2
    patchCoreV1NamespacedPersistentVolumeClaim | 2
    patchCoreV1NamespacedPersistentVolumeClaimStatus | 2
    patchCoreV1NamespacedPod | 548
    patchCoreV1NamespacedPodEphemeralcontainers | 4
    patchCoreV1NamespacedPodsProxy | 3
    patchCoreV1NamespacedPodStatus | 5108
    patchCoreV1NamespacedPodTemplate | 2
    patchCoreV1NamespacedReplicationController | 16
    patchCoreV1NamespacedReplicationControllerScale | 6
    patchCoreV1NamespacedReplicationControllerStatus | 2
    patchCoreV1NamespacedResourceQuota | 4
    patchCoreV1NamespacedResourceQuotaStatus | 4
    patchCoreV1NamespacedSecret | 2
    patchCoreV1NamespacedService | 2
    patchCoreV1NamespacedServiceAccount | 2
    patchCoreV1NamespacedServicesProxy | 3
    patchCoreV1NamespacedServiceStatus | 2
    patchCoreV1NamespaceStatus | 2
    patchCoreV1Node | 44
    patchCoreV1NodeStatus | 1530
    patchCoreV1PersistentVolume | 2
    patchCoreV1PersistentVolumeStatus | 2
    patchDiscoveryV1NamespacedEndpointSlice | 2
    patchEventsV1NamespacedEvent | 2
    patchFlowcontrolApiserverV1FlowSchema | 2
    patchFlowcontrolApiserverV1FlowSchemaStatus | 34
    patchFlowcontrolApiserverV1PriorityLevelConfiguration | 2
    patchFlowcontrolApiserverV1PriorityLevelConfigurationStatus | 2
    patchMygroupexamplecomV1beta1Fooblhwqas | 2
    patchMygroupexamplecomV1beta1Fooq5jtpas | 2
    patchMygroupexamplecomV1beta1Foormzg6as | 2
    patchMygroupexamplecomV1beta1Foot5gjfas | 2
    patchMygroupexamplecomV1beta1Fooxfm79as | 2
    patchMygroupexamplecomV1beta1Noxus | 4
    patchNetworkingV1IngressClass | 2
    patchNetworkingV1IPAddress | 2
    patchNetworkingV1NamespacedIngress | 2
    patchNetworkingV1NamespacedIngressStatus | 2
    patchNetworkingV1ServiceCIDR | 4
    patchNetworkingV1ServiceCIDRStatus | 4
    patchNodeV1RuntimeClass | 2
    patchPolicyV1NamespacedPodDisruptionBudget | 4
    patchPolicyV1NamespacedPodDisruptionBudgetStatus | 2
    patchRbacAuthorizationV1ClusterRole | 14
    patchSchedulingV1PriorityClass | 4
    patchStorageV1CSIDriver | 2
    patchStorageV1CSINode | 2
    patchStorageV1NamespacedCSIStorageCapacity | 2
    patchStorageV1StorageClass | 2
    patchStorageV1VolumeAttachment | 4
    patchStorageV1VolumeAttachmentStatus | 2
    readAdmissionregistrationV1MutatingWebhookConfiguration | 8
    readAdmissionregistrationV1ValidatingAdmissionPolicy | 8
    readAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 6
    readAdmissionregistrationV1ValidatingAdmissionPolicyStatus | 2
    readAdmissionregistrationV1ValidatingWebhookConfiguration | 8
    readApiextensionsV1CustomResourceDefinition | 6
    readApiextensionsV1CustomResourceDefinitionStatus | 2
    readApiregistrationV1APIService | 6
    readApiregistrationV1APIServiceStatus | 10
    readAppsV1NamespacedControllerRevision | 82
    readAppsV1NamespacedDaemonSet | 48
    readAppsV1NamespacedDaemonSetStatus | 2
    readAppsV1NamespacedDeployment | 354
    readAppsV1NamespacedDeploymentScale | 2
    readAppsV1NamespacedDeploymentStatus | 6
    readAppsV1NamespacedReplicaSet | 308
    readAppsV1NamespacedReplicaSetScale | 2
    readAppsV1NamespacedReplicaSetStatus | 2
    readAppsV1NamespacedStatefulSet | 132
    readAppsV1NamespacedStatefulSetScale | 2
    readAppsV1NamespacedStatefulSetStatus | 2
    readAutoscalingV2NamespacedHorizontalPodAutoscaler | 4
    readBatchV1NamespacedCronJob | 434
    readBatchV1NamespacedCronJobStatus | 2
    readBatchV1NamespacedJob | 194
    readBatchV1NamespacedJobStatus | 2
    readCertificatesV1CertificateSigningRequest | 4
    readCertificatesV1CertificateSigningRequestApproval | 2
    readCertificatesV1CertificateSigningRequestStatus | 2
    readCoordinationV1NamespacedLease | 30
    readCoreV1Namespace | 2238
    readCoreV1NamespacedConfigMap | 80
    readCoreV1NamespacedEndpoints | 1256
    readCoreV1NamespacedEvent | 6
    readCoreV1NamespacedLimitRange | 4
    readCoreV1NamespacedPersistentVolumeClaim | 12
    readCoreV1NamespacedPersistentVolumeClaimStatus | 2
    readCoreV1NamespacedPod | 18038
    readCoreV1NamespacedPodEphemeralcontainers | 4
    readCoreV1NamespacedPodLog | 1131
    readCoreV1NamespacedPodStatus | 2
    readCoreV1NamespacedPodTemplate | 6
    readCoreV1NamespacedReplicationController | 646
    readCoreV1NamespacedReplicationControllerScale | 10
    readCoreV1NamespacedReplicationControllerStatus | 2
    readCoreV1NamespacedResourceQuota | 172
    readCoreV1NamespacedResourceQuotaStatus | 2
    readCoreV1NamespacedSecret | 8
    readCoreV1NamespacedService | 76
    readCoreV1NamespacedServiceAccount | 208
    readCoreV1NamespacedServiceStatus | 2
    readCoreV1NamespaceStatus | 4
    readCoreV1Node | 202
    readCoreV1PersistentVolume | 14
    readCoreV1PersistentVolumeStatus | 2
    readDiscoveryV1NamespacedEndpointSlice | 1786
    readEventsV1NamespacedEvent | 6
    readFlowcontrolApiserverV1FlowSchema | 10
    readFlowcontrolApiserverV1FlowSchemaStatus | 2
    readFlowcontrolApiserverV1PriorityLevelConfiguration | 8
    readFlowcontrolApiserverV1PriorityLevelConfigurationStatus | 2
    readNetworkingV1IngressClass | 4
    readNetworkingV1IPAddress | 4
    readNetworkingV1NamespacedIngress | 8
    readNetworkingV1NamespacedIngressStatus | 2
    readNetworkingV1ServiceCIDR | 4
    readNetworkingV1ServiceCIDRStatus | 2
    readNodeV1RuntimeClass | 10
    readPolicyV1NamespacedPodDisruptionBudget | 62
    readPolicyV1NamespacedPodDisruptionBudgetStatus | 8
    readRbacAuthorizationV1ClusterRole | 150
    readRbacAuthorizationV1ClusterRoleBinding | 102
    readRbacAuthorizationV1NamespacedRole | 16
    readRbacAuthorizationV1NamespacedRoleBinding | 16
    readResourceV1NamespacedResourceClaim | 4
    readSchedulingV1PriorityClass | 8
    readStorageV1CSIDriver | 10
    readStorageV1CSINode | 38
    readStorageV1NamespacedCSIStorageCapacity | 4
    readStorageV1StorageClass | 6
    readStorageV1VolumeAttachment | 8
    readStorageV1VolumeAttachmentStatus | 2
    replaceAdmissionregistrationV1MutatingWebhookConfiguration | 4
    replaceAdmissionregistrationV1ValidatingAdmissionPolicy | 2
    replaceAdmissionregistrationV1ValidatingAdmissionPolicyBinding | 2
    replaceAdmissionregistrationV1ValidatingAdmissionPolicyStatus | 2
    replaceAdmissionregistrationV1ValidatingWebhookConfiguration | 4
    replaceApiextensionsV1CustomResourceDefinition | 4
    replaceApiextensionsV1CustomResourceDefinitionStatus | 316
    replaceApiregistrationV1APIService | 2
    replaceApiregistrationV1APIServiceStatus | 4
    replaceAppsV1NamespacedControllerRevision | 10
    replaceAppsV1NamespacedDaemonSet | 4
    replaceAppsV1NamespacedDaemonSetStatus | 140
    replaceAppsV1NamespacedDeployment | 10
    replaceAppsV1NamespacedDeploymentScale | 2
    replaceAppsV1NamespacedDeploymentStatus | 800
    replaceAppsV1NamespacedReplicaSet | 46
    replaceAppsV1NamespacedReplicaSetScale | 2
    replaceAppsV1NamespacedReplicaSetStatus | 812
    replaceAppsV1NamespacedStatefulSet | 30
    replaceAppsV1NamespacedStatefulSetScale | 2
    replaceAppsV1NamespacedStatefulSetStatus | 344
    replaceAutoscalingV2NamespacedHorizontalPodAutoscaler | 2
    replaceBatchV1NamespacedCronJob | 2
    replaceBatchV1NamespacedCronJobStatus | 12
    replaceBatchV1NamespacedJob | 2
    replaceBatchV1NamespacedJobStatus | 154
    replaceCertificatesV1CertificateSigningRequest | 2
    replaceCertificatesV1CertificateSigningRequestApproval | 8
    replaceCertificatesV1CertificateSigningRequestStatus | 8
    replaceCoordinationV1NamespacedLease | 17076
    replaceCoreV1Namespace | 2
    replaceCoreV1NamespacedConfigMap | 106
    replaceCoreV1NamespacedEndpoints | 406
    replaceCoreV1NamespacedEvent | 2
    replaceCoreV1NamespacedLimitRange | 2
    replaceCoreV1NamespacedPersistentVolumeClaim | 18
    replaceCoreV1NamespacedPersistentVolumeClaimStatus | 10
    replaceCoreV1NamespacedPod | 32
    replaceCoreV1NamespacedPodEphemeralcontainers | 2
    replaceCoreV1NamespacedPodStatus | 4
    replaceCoreV1NamespacedPodTemplate | 2
    replaceCoreV1NamespacedReplicationController | 2
    replaceCoreV1NamespacedReplicationControllerScale | 2
    replaceCoreV1NamespacedReplicationControllerStatus | 774
    replaceCoreV1NamespacedResourceQuota | 2
    replaceCoreV1NamespacedResourceQuotaStatus | 100
    replaceCoreV1NamespacedSecret | 14
    replaceCoreV1NamespacedService | 24
    replaceCoreV1NamespacedServiceAccount | 2
    replaceCoreV1NamespacedServiceStatus | 2
    replaceCoreV1NamespaceFinalize | 1736
    replaceCoreV1NamespaceStatus | 942
    replaceCoreV1Node | 18
    replaceCoreV1NodeStatus | 22
    replaceCoreV1PersistentVolume | 16
    replaceCoreV1PersistentVolumeStatus | 22
    replaceDiscoveryV1NamespacedEndpointSlice | 512
    replaceEventsV1NamespacedEvent | 2
    replaceFlowcontrolApiserverV1FlowSchema | 2
    replaceFlowcontrolApiserverV1FlowSchemaStatus | 4
    replaceFlowcontrolApiserverV1PriorityLevelConfiguration | 2
    replaceFlowcontrolApiserverV1PriorityLevelConfigurationStatus | 2
    replaceNetworkingV1IngressClass | 2
    replaceNetworkingV1IPAddress | 2
    replaceNetworkingV1NamespacedIngress | 2
    replaceNetworkingV1NamespacedIngressStatus | 2
    replaceNetworkingV1ServiceCIDR | 2
    replaceNodeV1RuntimeClass | 2
    replacePolicyV1NamespacedPodDisruptionBudget | 4
    replacePolicyV1NamespacedPodDisruptionBudgetStatus | 78
    replaceResourceV1NamespacedResourceClaim | 4
    replaceResourceV1NamespacedResourceClaimStatus | 4
    replaceSchedulingV1PriorityClass | 4
    replaceStorageV1CSIDriver | 2
    replaceStorageV1CSINode | 2
    replaceStorageV1NamespacedCSIStorageCapacity | 2
    replaceStorageV1StorageClass | 2
    replaceStorageV1VolumeAttachment | 4
    replaceStorageV1VolumeAttachmentStatus | 2
    updateCoreV1NamespacedPodsProxy | 3
    updateCoreV1NamespacedServicesProxy | 3
    watchCrdpublishopenapitestunknowninnestedexamplecomV1E2e-test-crd-publish-openapi-3566-3325-crds | 291
    watchGroup48wp2examplecomV1NamespacedTestcrds | 3
    watchGroupdwcnjexamplecomV1NamespacedTestcrds | 3
    watchGroupdwcnjexamplecomV1Testcrds | 39
    watchMygroupexamplecomV1beta1Fooblhwqas | 3
    watchMygroupexamplecomV1beta1Fooq5jtpas | 3
    watchMygroupexamplecomV1beta1Foormzg6as | 3
    watchMygroupexamplecomV1beta1Foot5gjfas | 3
    watchMygroupexamplecomV1beta1Fooxfm79as | 3
    watchMygroupexamplecomV1beta1Noxus | 276
    watchMygroupexamplecomV1Fooblhwqas | 3
    watchMygroupexamplecomV1Fooq5jtpas | 3
    watchMygroupexamplecomV1Foormzg6as | 69
    watchMygroupexamplecomV1Foot5gjfas | 3
    watchMygroupexamplecomV1Fooxfm79as | 3
    watchStableexamplecomV1NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 3
    watchStableexamplecomV2NamespacedE2e-test-crd-selectable-fields-9774-6627-crds | 12
    watchWebhookexamplecomV1E2e-test-webhook-6901-9215-crds | 333

    ======================================================================
    STABLE ENDPOINTS NOT FOUND IN AUDIT LOG
    ======================================================================
    Total missing stable endpoints: 239
    (Filtered out 261 alpha/beta endpoints)
    These are stable API endpoints defined in the Swagger spec but not exercised in this audit log:

    connectCoreV1DeleteNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1DeleteNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1DeleteNodeProxy | NOT FOUND
    connectCoreV1DeleteNodeProxyWithPath | NOT FOUND
    connectCoreV1GetNodeProxy | NOT FOUND
    connectCoreV1GetNodeProxyWithPath | NOT FOUND
    connectCoreV1PatchNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1PatchNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1PatchNodeProxy | NOT FOUND
    connectCoreV1PatchNodeProxyWithPath | NOT FOUND
    connectCoreV1PostNamespacedPodExec | NOT FOUND
    connectCoreV1PostNamespacedPodPortforward | NOT FOUND
    connectCoreV1PostNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1PostNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1PostNodeProxy | NOT FOUND
    connectCoreV1PostNodeProxyWithPath | NOT FOUND
    connectCoreV1PutNamespacedPodProxyWithPath | NOT FOUND
    connectCoreV1PutNamespacedServiceProxyWithPath | NOT FOUND
    connectCoreV1PutNodeProxy | NOT FOUND
    connectCoreV1PutNodeProxyWithPath | NOT FOUND
    createAuthenticationV1SelfSubjectReview | NOT FOUND
    createAuthorizationV1SelfSubjectRulesReview | NOT FOUND
    createAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    createAutoscalingV2NamespacedHorizontalPodAutoscaler | NOT FOUND
    createCoreV1NamespacedBinding | NOT FOUND
    createNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    createStorageV1VolumeAttributesClass | NOT FOUND
    deleteAutoscalingV1CollectionNamespacedHorizontalPodAutoscaler | NOT FOUND
    deleteAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    deleteCoreV1CollectionNode | NOT FOUND
    deleteNetworkingV1CollectionServiceCIDR | NOT FOUND
    deleteNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    deleteNetworkingV1ServiceCIDR | NOT FOUND
    deleteRbacAuthorizationV1CollectionClusterRole | NOT FOUND
    deleteRbacAuthorizationV1CollectionClusterRoleBinding | NOT FOUND
    deleteRbacAuthorizationV1NamespacedRole | NOT FOUND
    deleteResourceV1CollectionDeviceClass | NOT FOUND
    deleteResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    deleteResourceV1ResourceSlice | NOT FOUND
    deleteStorageV1CollectionVolumeAttributesClass | NOT FOUND
    deleteStorageV1VolumeAttributesClass | NOT FOUND
    getAppsAPIGroup | NOT FOUND
    getInternalApiserverAPIGroup | NOT FOUND
    getRbacAuthorizationV1APIResources | NOT FOUND
    getResourceV1APIResources | NOT FOUND
    getStoragemigrationAPIGroup | NOT FOUND
    listAutoscalingV1HorizontalPodAutoscalerForAllNamespaces | NOT FOUND
    listAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    listCoreV1ComponentStatus | NOT FOUND
    logFileHandler | NOT FOUND
    logFileListHandler | NOT FOUND
    patchAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    patchAutoscalingV1NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    patchAutoscalingV2NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    patchCoreV1NamespacedPodResize | NOT FOUND
    patchNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    patchRbacAuthorizationV1ClusterRoleBinding | NOT FOUND
    patchRbacAuthorizationV1NamespacedRole | NOT FOUND
    patchRbacAuthorizationV1NamespacedRoleBinding | NOT FOUND
    patchResourceV1DeviceClass | NOT FOUND
    patchResourceV1NamespacedResourceClaim | NOT FOUND
    patchResourceV1NamespacedResourceClaimStatus | NOT FOUND
    patchResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    patchResourceV1ResourceSlice | NOT FOUND
    patchStorageV1VolumeAttributesClass | NOT FOUND
    readAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    readAutoscalingV1NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    readAutoscalingV2NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    readCoreV1ComponentStatus | NOT FOUND
    readCoreV1NamespacedPodResize | NOT FOUND
    readCoreV1NodeStatus | NOT FOUND
    readNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    readResourceV1DeviceClass | NOT FOUND
    readResourceV1NamespacedResourceClaimStatus | NOT FOUND
    readResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    readResourceV1ResourceSlice | NOT FOUND
    readStorageV1VolumeAttributesClass | NOT FOUND
    replaceAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    replaceAutoscalingV1NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    replaceAutoscalingV2NamespacedHorizontalPodAutoscalerStatus | NOT FOUND
    replaceCoreV1NamespacedPodResize | NOT FOUND
    replaceNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    replaceNetworkingV1ServiceCIDRStatus | NOT FOUND
    replaceRbacAuthorizationV1ClusterRole | NOT FOUND
    replaceRbacAuthorizationV1ClusterRoleBinding | NOT FOUND
    replaceRbacAuthorizationV1NamespacedRole | NOT FOUND
    replaceRbacAuthorizationV1NamespacedRoleBinding | NOT FOUND
    replaceResourceV1DeviceClass | NOT FOUND
    replaceResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    replaceResourceV1ResourceSlice | NOT FOUND
    replaceStorageV1VolumeAttributesClass | NOT FOUND
    watchAdmissionregistrationV1MutatingWebhookConfiguration | NOT FOUND
    watchAdmissionregistrationV1MutatingWebhookConfigurationList | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicy | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicyBinding | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicyBindingList | NOT FOUND
    watchAdmissionregistrationV1ValidatingAdmissionPolicyList | NOT FOUND
    watchAdmissionregistrationV1ValidatingWebhookConfiguration | NOT FOUND
    watchAdmissionregistrationV1ValidatingWebhookConfigurationList | NOT FOUND
    watchApiextensionsV1CustomResourceDefinition | NOT FOUND
    watchApiextensionsV1CustomResourceDefinitionList | NOT FOUND
    watchApiregistrationV1APIService | NOT FOUND
    watchApiregistrationV1APIServiceList | NOT FOUND
    watchAppsV1ControllerRevisionListForAllNamespaces | NOT FOUND
    watchAppsV1DaemonSetListForAllNamespaces | NOT FOUND
    watchAppsV1DeploymentListForAllNamespaces | NOT FOUND
    watchAppsV1NamespacedControllerRevision | NOT FOUND
    watchAppsV1NamespacedControllerRevisionList | NOT FOUND
    watchAppsV1NamespacedDaemonSet | NOT FOUND
    watchAppsV1NamespacedDaemonSetList | NOT FOUND
    watchAppsV1NamespacedDeployment | NOT FOUND
    watchAppsV1NamespacedDeploymentList | NOT FOUND
    watchAppsV1NamespacedReplicaSet | NOT FOUND
    watchAppsV1NamespacedReplicaSetList | NOT FOUND
    watchAppsV1NamespacedStatefulSet | NOT FOUND
    watchAppsV1NamespacedStatefulSetList | NOT FOUND
    watchAppsV1ReplicaSetListForAllNamespaces | NOT FOUND
    watchAppsV1StatefulSetListForAllNamespaces | NOT FOUND
    watchAutoscalingV1HorizontalPodAutoscalerListForAllNamespaces | NOT FOUND
    watchAutoscalingV1NamespacedHorizontalPodAutoscaler | NOT FOUND
    watchAutoscalingV1NamespacedHorizontalPodAutoscalerList | NOT FOUND
    watchAutoscalingV2HorizontalPodAutoscalerListForAllNamespaces | NOT FOUND
    watchAutoscalingV2NamespacedHorizontalPodAutoscaler | NOT FOUND
    watchAutoscalingV2NamespacedHorizontalPodAutoscalerList | NOT FOUND
    watchBatchV1CronJobListForAllNamespaces | NOT FOUND
    watchBatchV1JobListForAllNamespaces | NOT FOUND
    watchBatchV1NamespacedCronJob | NOT FOUND
    watchBatchV1NamespacedCronJobList | NOT FOUND
    watchBatchV1NamespacedJob | NOT FOUND
    watchBatchV1NamespacedJobList | NOT FOUND
    watchCertificatesV1CertificateSigningRequest | NOT FOUND
    watchCertificatesV1CertificateSigningRequestList | NOT FOUND
    watchCoordinationV1LeaseListForAllNamespaces | NOT FOUND
    watchCoordinationV1NamespacedLease | NOT FOUND
    watchCoordinationV1NamespacedLeaseList | NOT FOUND
    watchCoreV1ConfigMapListForAllNamespaces | NOT FOUND
    watchCoreV1EndpointsListForAllNamespaces | NOT FOUND
    watchCoreV1EventListForAllNamespaces | NOT FOUND
    watchCoreV1LimitRangeListForAllNamespaces | NOT FOUND
    watchCoreV1Namespace | NOT FOUND
    watchCoreV1NamespaceList | NOT FOUND
    watchCoreV1NamespacedConfigMap | NOT FOUND
    watchCoreV1NamespacedConfigMapList | NOT FOUND
    watchCoreV1NamespacedEndpoints | NOT FOUND
    watchCoreV1NamespacedEndpointsList | NOT FOUND
    watchCoreV1NamespacedEvent | NOT FOUND
    watchCoreV1NamespacedEventList | NOT FOUND
    watchCoreV1NamespacedLimitRange | NOT FOUND
    watchCoreV1NamespacedLimitRangeList | NOT FOUND
    watchCoreV1NamespacedPersistentVolumeClaim | NOT FOUND
    watchCoreV1NamespacedPersistentVolumeClaimList | NOT FOUND
    watchCoreV1NamespacedPod | NOT FOUND
    watchCoreV1NamespacedPodList | NOT FOUND
    watchCoreV1NamespacedPodTemplate | NOT FOUND
    watchCoreV1NamespacedPodTemplateList | NOT FOUND
    watchCoreV1NamespacedReplicationController | NOT FOUND
    watchCoreV1NamespacedReplicationControllerList | NOT FOUND
    watchCoreV1NamespacedResourceQuota | NOT FOUND
    watchCoreV1NamespacedResourceQuotaList | NOT FOUND
    watchCoreV1NamespacedSecret | NOT FOUND
    watchCoreV1NamespacedSecretList | NOT FOUND
    watchCoreV1NamespacedService | NOT FOUND
    watchCoreV1NamespacedServiceAccount | NOT FOUND
    watchCoreV1NamespacedServiceAccountList | NOT FOUND
    watchCoreV1NamespacedServiceList | NOT FOUND
    watchCoreV1Node | NOT FOUND
    watchCoreV1NodeList | NOT FOUND
    watchCoreV1PersistentVolume | NOT FOUND
    watchCoreV1PersistentVolumeClaimListForAllNamespaces | NOT FOUND
    watchCoreV1PersistentVolumeList | NOT FOUND
    watchCoreV1PodListForAllNamespaces | NOT FOUND
    watchCoreV1PodTemplateListForAllNamespaces | NOT FOUND
    watchCoreV1ReplicationControllerListForAllNamespaces | NOT FOUND
    watchCoreV1ResourceQuotaListForAllNamespaces | NOT FOUND
    watchCoreV1SecretListForAllNamespaces | NOT FOUND
    watchCoreV1ServiceAccountListForAllNamespaces | NOT FOUND
    watchCoreV1ServiceListForAllNamespaces | NOT FOUND
    watchDiscoveryV1EndpointSliceListForAllNamespaces | NOT FOUND
    watchDiscoveryV1NamespacedEndpointSlice | NOT FOUND
    watchDiscoveryV1NamespacedEndpointSliceList | NOT FOUND
    watchEventsV1EventListForAllNamespaces | NOT FOUND
    watchEventsV1NamespacedEvent | NOT FOUND
    watchEventsV1NamespacedEventList | NOT FOUND
    watchFlowcontrolApiserverV1FlowSchema | NOT FOUND
    watchFlowcontrolApiserverV1FlowSchemaList | NOT FOUND
    watchFlowcontrolApiserverV1PriorityLevelConfiguration | NOT FOUND
    watchFlowcontrolApiserverV1PriorityLevelConfigurationList | NOT FOUND
    watchNetworkingV1IPAddress | NOT FOUND
    watchNetworkingV1IPAddressList | NOT FOUND
    watchNetworkingV1IngressClass | NOT FOUND
    watchNetworkingV1IngressClassList | NOT FOUND
    watchNetworkingV1IngressListForAllNamespaces | NOT FOUND
    watchNetworkingV1NamespacedIngress | NOT FOUND
    watchNetworkingV1NamespacedIngressList | NOT FOUND
    watchNetworkingV1NamespacedNetworkPolicy | NOT FOUND
    watchNetworkingV1NamespacedNetworkPolicyList | NOT FOUND
    watchNetworkingV1NetworkPolicyListForAllNamespaces | NOT FOUND
    watchNetworkingV1ServiceCIDR | NOT FOUND
    watchNetworkingV1ServiceCIDRList | NOT FOUND
    watchNodeV1RuntimeClass | NOT FOUND
    watchNodeV1RuntimeClassList | NOT FOUND
    watchPolicyV1NamespacedPodDisruptionBudget | NOT FOUND
    watchPolicyV1NamespacedPodDisruptionBudgetList | NOT FOUND
    watchPolicyV1PodDisruptionBudgetListForAllNamespaces | NOT FOUND
    watchRbacAuthorizationV1ClusterRole | NOT FOUND
    watchRbacAuthorizationV1ClusterRoleBinding | NOT FOUND
    watchRbacAuthorizationV1ClusterRoleBindingList | NOT FOUND
    watchRbacAuthorizationV1ClusterRoleList | NOT FOUND
    watchRbacAuthorizationV1NamespacedRole | NOT FOUND
    watchRbacAuthorizationV1NamespacedRoleBinding | NOT FOUND
    watchRbacAuthorizationV1NamespacedRoleBindingList | NOT FOUND
    watchRbacAuthorizationV1NamespacedRoleList | NOT FOUND
    watchRbacAuthorizationV1RoleBindingListForAllNamespaces | NOT FOUND
    watchRbacAuthorizationV1RoleListForAllNamespaces | NOT FOUND
    watchResourceV1DeviceClass | NOT FOUND
    watchResourceV1DeviceClassList | NOT FOUND
    watchResourceV1NamespacedResourceClaim | NOT FOUND
    watchResourceV1NamespacedResourceClaimList | NOT FOUND
    watchResourceV1NamespacedResourceClaimTemplate | NOT FOUND
    watchResourceV1NamespacedResourceClaimTemplateList | NOT FOUND
    watchResourceV1ResourceClaimListForAllNamespaces | NOT FOUND
    watchResourceV1ResourceClaimTemplateListForAllNamespaces | NOT FOUND
    watchResourceV1ResourceSlice | NOT FOUND
    watchResourceV1ResourceSliceList | NOT FOUND
    watchSchedulingV1PriorityClass | NOT FOUND
    watchSchedulingV1PriorityClassList | NOT FOUND
    watchStorageV1CSIDriver | NOT FOUND
    watchStorageV1CSIDriverList | NOT FOUND
    watchStorageV1CSINode | NOT FOUND
    watchStorageV1CSINodeList | NOT FOUND
    watchStorageV1CSIStorageCapacityListForAllNamespaces | NOT FOUND
    watchStorageV1NamespacedCSIStorageCapacity | NOT FOUND
    watchStorageV1NamespacedCSIStorageCapacityList | NOT FOUND
    watchStorageV1StorageClass | NOT FOUND
    watchStorageV1StorageClassList | NOT FOUND
    watchStorageV1VolumeAttachment | NOT FOUND
    watchStorageV1VolumeAttachmentList | NOT FOUND
    watchStorageV1VolumeAttributesClass | NOT FOUND
    watchStorageV1VolumeAttributesClassList | NOT FOUND
  8. dims created this gist Aug 19, 2025.
    3 changes: 3 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    ```
    python3 audit_log_parser_swagger.py ./1957781493858177024/artifacts/audit/audit*.log
    ```
    624 changes: 624 additions & 0 deletions audit_log_parser_swagger.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,624 @@
    #!/usr/bin/env python3
    """
    Kubernetes Audit Log Parser with Swagger/OpenAPI Integration
    This script parses a Kubernetes audit log file and generates a list of
    Kubernetes API endpoints using the official Swagger/OpenAPI specification
    for accurate endpoint naming.
    Usage: python3 audit_log_parser_swagger.py <audit_log_file> [--output <output_file>] [--swagger-url <url>]
    """

    import json
    import re
    import sys
    import urllib.request
    import urllib.parse
    from collections import Counter
    from pathlib import Path
    import argparse
    import time


    class SwaggerEndpointMapper:
    """Maps Kubernetes API paths to proper OpenAPI operation IDs using Swagger spec.
    Requires a valid Swagger specification to operate - fails hard if not available.
    """

    def __init__(self, swagger_url=None):
    self.swagger_url = swagger_url or "https://raw.githubusercontent.com/kubernetes/kubernetes/refs/heads/master/api/openapi-spec/swagger.json"
    self.swagger_spec = None
    self.path_to_operation = {}
    self.known_resource_types = set()
    self.load_swagger_spec()

    def load_swagger_spec(self):
    """Load and parse the Kubernetes Swagger/OpenAPI specification."""
    print(f"Loading Swagger specification from: {self.swagger_url}")

    try:
    # Try to load from cache first
    cache_file = Path("kubernetes_swagger_cache.json")
    if cache_file.exists():
    cache_age = time.time() - cache_file.stat().st_mtime
    if cache_age < 3600: # Cache for 1 hour
    print("Using cached Swagger specification")
    with open(cache_file, 'r') as f:
    self.swagger_spec = json.load(f)
    self._extract_resource_types()
    self._build_path_mapping()
    return

    # Download fresh specification
    with urllib.request.urlopen(self.swagger_url, timeout=30) as response:
    self.swagger_spec = json.load(response)

    # Cache the specification
    with open(cache_file, 'w') as f:
    json.dump(self.swagger_spec, f, indent=2)

    print("Swagger specification loaded successfully")
    self._extract_resource_types()
    self._build_path_mapping()

    except urllib.error.URLError as e:
    print(f"Error downloading Swagger spec: {e}")
    print("Cannot proceed without Swagger specification")
    sys.exit(1)
    except json.JSONDecodeError as e:
    print(f"Error parsing Swagger JSON: {e}")
    print("Cannot proceed without valid Swagger specification")
    sys.exit(1)
    except Exception as e:
    print(f"Unexpected error loading Swagger spec: {e}")
    print("Cannot proceed without Swagger specification")
    sys.exit(1)

    def _build_path_mapping(self):
    """Build mapping from API paths and HTTP methods to OpenAPI operation IDs."""
    if not self.swagger_spec or 'paths' not in self.swagger_spec:
    return

    print("Building path to operation mapping...")

    for path, path_info in self.swagger_spec['paths'].items():
    for method, operation in path_info.items():
    if method.lower() in ['get', 'post', 'put', 'patch', 'delete'] and 'operationId' in operation:
    operation_id = operation['operationId']

    # Normalize the path for matching
    normalized_path = self._normalize_swagger_path(path)
    key = f"{method.lower()}:{normalized_path}"
    self.path_to_operation[key] = operation_id

    print(f"Loaded {len(self.path_to_operation)} API operations from Swagger spec")

    def _extract_resource_types(self):
    """Extract resource types from Swagger paths to avoid hardcoding."""
    if not self.swagger_spec or 'paths' not in self.swagger_spec:
    return

    print("Extracting resource types from Swagger specification...")

    # Extract resource types from paths
    for path, path_info in self.swagger_spec['paths'].items():
    # Skip non-resource paths
    if not path.startswith('/api') or '/watch/' in path:
    continue

    # Parse path segments
    segments = [s for s in path.split('/') if s]

    for i, segment in enumerate(segments):
    # Look for resource type patterns in paths
    # Resource types are typically:
    # 1. In paths like /api/v1/{resource} or /apis/group/version/{resource}
    # 2. In paths like /api/v1/namespaces/{namespace}/{resource}
    # 3. Plural nouns that aren't parameters

    if (segment and
    not segment.startswith('{') and
    not '.' in segment and
    not segment.startswith('v') and
    segment not in ['api', 'apis', 'namespaces', 'status', 'scale', 'binding',
    'proxy', 'log', 'exec', 'attach', 'portforward', 'eviction',
    'ephemeralcontainers', 'finalize', 'watch']):

    # Check if this looks like a resource type (plural noun at end of path or before {name})
    next_segment = segments[i+1] if i+1 < len(segments) else None

    # It's likely a resource type if:
    # 1. It's the last segment in the path (collection operations)
    # 2. The next segment is {name} or a parameter
    # 3. It's followed by a subresource
    if (not next_segment or
    next_segment.startswith('{') or
    next_segment in ['status', 'scale', 'binding', 'proxy', 'log', 'exec',
    'attach', 'portforward', 'eviction', 'ephemeralcontainers', 'finalize']):

    # Additional validation: should be a plural noun (heuristic)
    if len(segment) > 2 and segment.endswith('s') and segment != 'namespaces':
    self.known_resource_types.add(segment)

    # Add some critical ones that might be missed by heuristics
    critical_resources = {
    'nodes', 'namespaces', 'componentstatuses' # These don't always follow plural patterns
    }
    self.known_resource_types.update(critical_resources)

    print(f"Extracted {len(self.known_resource_types)} resource types from Swagger spec")

    def _normalize_swagger_path(self, path):
    """Normalize Swagger path template for matching against audit log URIs."""
    # Replace common Swagger path parameters with our placeholders
    normalized = path

    # Replace parameter templates
    normalized = re.sub(r'\{namespace\}', '{namespace}', normalized)
    normalized = re.sub(r'\{name\}', '{name}', normalized)
    normalized = re.sub(r'\{node\}', '{node}', normalized)
    normalized = re.sub(r'\{path\}', '{path}', normalized)

    return normalized

    def _normalize_audit_path(self, uri):
    """Normalize audit log URI for matching against Swagger paths."""
    # Remove query parameters
    uri = uri.split('?')[0]

    # Replace actual values with parameter placeholders
    normalized = re.sub(r'/namespaces/[^/]+', '/namespaces/{namespace}', uri)
    normalized = re.sub(r'/nodes/[^/]+(?=/|$)', '/nodes/{node}', normalized)

    # Replace resource names with {name} placeholder
    # Split the path and process each segment
    parts = normalized.split('/')
    result_parts = []

    for i, part in enumerate(parts):
    if i == 0 and part == '':
    result_parts.append(part)
    continue

    # Skip known path segments that shouldn't be replaced
    if part in ['api', 'apis', 'namespaces', 'status', 'scale', 'binding', 'proxy',
    'log', 'exec', 'attach', 'portforward', 'eviction', 'ephemeralcontainers',
    'watch', 'finalize', '{namespace}', '{node}', '{name}']:
    result_parts.append(part)
    continue

    # Skip API group and version segments (contain dots or start with v)
    if '.' in part or re.match(r'^v\d+', part):
    result_parts.append(part)
    continue

    # Determine if this part should be replaced with {name}
    # It should be replaced if it's after a resource type and looks like an instance name
    is_resource_name = False

    if i > 0:
    prev_part = parts[i-1]

    # This is a resource name if the previous part is a known resource type
    if prev_part in self.known_resource_types:
    # And this part looks like a resource instance name (not a subresource)
    if (part not in ['status', 'scale', 'binding', 'proxy', 'log', 'exec',
    'attach', 'portforward', 'eviction', 'ephemeralcontainers', 'finalize'] and
    not part.startswith('{')):
    is_resource_name = True

    if is_resource_name:
    result_parts.append('{name}')
    else:
    result_parts.append(part)

    return '/'.join(result_parts)

    def _k8s_verb_to_http_method(self, k8s_verb, uri):
    """Convert Kubernetes audit verb to HTTP method for Swagger lookup."""
    k8s_verb = k8s_verb.lower()

    # Map Kubernetes verbs to HTTP methods
    verb_mapping = {
    'get': 'get',
    'list': 'get',
    'watch': 'get',
    'create': 'post',
    'update': 'put',
    'patch': 'patch',
    'delete': 'delete',
    'deletecollection': 'delete',
    'connect': 'get', # For exec, attach, proxy, etc.
    }

    return verb_mapping.get(k8s_verb, k8s_verb)

    def get_operation_id(self, method, uri):
    """Get the OpenAPI operation ID for a given HTTP method and URI."""
    if not self.swagger_spec:
    return None

    # Convert Kubernetes verb to HTTP method
    http_method = self._k8s_verb_to_http_method(method, uri).lower()
    normalized_uri = self._normalize_audit_path(uri)
    key = f"{http_method}:{normalized_uri}"

    # Direct match
    if key in self.path_to_operation:
    return self.path_to_operation[key]

    # Try some common variations
    variations = [
    # Try without trailing slash
    key.rstrip('/'),
    # Try with trailing slash if not present
    key if key.endswith('/') else key + '/',
    ]

    for variation in variations:
    if variation in self.path_to_operation:
    return self.path_to_operation[variation]

    # For specific resource instance operations, try with {name} placeholder
    if '/{name}' not in normalized_uri and http_method == 'get':
    # Try adding {name} for individual resource gets
    name_variation = f"{http_method}:{normalized_uri}/{{name}}"
    if name_variation in self.path_to_operation:
    return self.path_to_operation[name_variation]

    # Fuzzy matching for complex cases
    return self._fuzzy_match_operation(http_method, normalized_uri)

    def _fuzzy_match_operation(self, method, uri):
    """Try to find a matching operation using fuzzy matching."""
    method_prefix = f"{method}:"

    # Find all operations for this method
    matching_ops = [key for key in self.path_to_operation.keys() if key.startswith(method_prefix)]

    # Score matches based on path similarity
    best_match = None
    best_score = 0

    for op_key in matching_ops:
    op_path = op_key[len(method_prefix):]
    score = self._path_similarity(uri, op_path)
    if score > best_score and score > 0.7: # Require 70% similarity
    best_score = score
    best_match = op_key

    return self.path_to_operation.get(best_match) if best_match else None

    def _path_similarity(self, path1, path2):
    """Calculate similarity between two API paths."""
    parts1 = [p for p in path1.split('/') if p]
    parts2 = [p for p in path2.split('/') if p]

    if len(parts1) != len(parts2):
    return 0

    matches = 0
    for p1, p2 in zip(parts1, parts2):
    if p1 == p2 or p1 == '{name}' or p2 == '{name}' or p1 == '{namespace}' or p2 == '{namespace}':
    matches += 1

    return matches / len(parts1) if parts1 else 0


    def convert_to_k8s_endpoint_fallback(verb, uri):
    """
    Fallback method: Convert HTTP verb and URI to Kubernetes endpoint format.
    Used when Swagger specification is not available.
    """
    # This is the same logic as the original script
    uri = uri.split('?')[0]
    uri = re.sub(r'/namespaces/[^/]+', '/namespaces/{namespace}', uri)
    uri = re.sub(r'/nodes/[^/]+', '/nodes/{node}', uri)

    verb = verb.lower()

    # Handle core API v1
    if uri.startswith('/api/v1/'):
    resource_part = uri[8:] # Remove /api/v1/

    if resource_part.startswith('namespaces/{namespace}/'):
    remaining = resource_part[23:]
    resource = remaining.split('/')[0]

    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource) and not '.' in resource:
    parts = remaining.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale', 'log', 'exec', 'attach', 'portforward', 'proxy', 'binding', 'eviction', 'ephemeralcontainers']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}CoreV1Namespaced{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}CoreV1Namespaced{resource_name}'

    else:
    resource = resource_part.split('/')[0]
    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource) and not '.' in resource:
    parts = resource_part.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}CoreV1{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}CoreV1{resource_name}'

    # Handle APIs group
    elif uri.startswith('/apis/'):
    match = re.match(r'/apis/([^/]+)/([^/]+)/(.*)', uri)
    if match:
    group, version, rest = match.groups()

    group_clean = group.replace('.k8s.io', '').replace('.', '').replace('-', '')
    group_clean = re.sub(r'[^a-zA-Z0-9]', '', group_clean)
    version_clean = version[0].upper() + version[1:] if len(version) > 1 else version.upper()

    if rest.startswith('namespaces/{namespace}/'):
    remaining = rest[23:]
    resource = remaining.split('/')[0]

    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource):
    parts = remaining.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale', 'binding']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}Namespaced{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}Namespaced{resource_name}'

    else:
    resource = rest.split('/')[0]
    if resource and not re.match(r'.*[.-].*[0-9a-f]{8,}', resource):
    parts = rest.split('/')
    if len(parts) > 2 and parts[1] and not re.match(r'[0-9a-f-]{20,}', parts[1]):
    subresource = parts[2]
    if subresource in ['status', 'scale']:
    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    subresource_name = subresource[0].upper() + subresource[1:] if len(subresource) > 1 else subresource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}{resource_name}{subresource_name}'

    resource_name = resource[0].upper() + resource[1:] if len(resource) > 1 else resource.upper()
    return f'{verb}{group_clean.capitalize()}{version_clean}{resource_name}'

    return None


    def parse_audit_logs(file_paths, swagger_mapper=None):
    """
    Parse multiple audit log files and extract Kubernetes endpoints with counts.
    Args:
    file_paths (list): List of paths to audit log files
    swagger_mapper (SwaggerEndpointMapper): Mapper for converting to operation IDs
    Returns:
    tuple: (Counter of endpoint counts, stats dict)
    """
    endpoint_counts = Counter()
    total_entries = 0
    skipped_entries = 0
    swagger_matches = 0
    fallback_matches = 0
    total_files = len(file_paths)

    print(f"Parsing {total_files} audit log file(s):")
    for i, file_path in enumerate(file_paths, 1):
    print(f" [{i}/{total_files}] {file_path}")
    print()

    for file_index, file_path in enumerate(file_paths, 1):
    print(f"Processing file {file_index}/{total_files}: {file_path}")

    try:
    with open(file_path, 'r') as file:
    file_entries = 0
    for line_num, line in enumerate(file, 1):
    if line_num % 10000 == 0:
    print(f" Processed {line_num} lines from {file_path}...")

    line = line.strip()
    if not line:
    continue

    try:
    entry = json.loads(line)
    total_entries += 1
    file_entries += 1

    verb = entry.get('verb', '')
    request_uri = entry.get('requestURI', '')

    if verb and request_uri:
    # Use Swagger-based mapping (required)
    operation_id = swagger_mapper.get_operation_id(verb, request_uri)
    if operation_id:
    endpoint_counts[operation_id] += 1
    swagger_matches += 1
    else:
    # Try fallback parsing for edge cases
    fallback_endpoint = convert_to_k8s_endpoint_fallback(verb, request_uri)
    if fallback_endpoint:
    endpoint_counts[fallback_endpoint] += 1
    fallback_matches += 1
    else:
    skipped_entries += 1
    else:
    skipped_entries += 1

    except json.JSONDecodeError:
    skipped_entries += 1
    continue
    except Exception as e:
    skipped_entries += 1
    continue

    print(f" Completed {file_path}: {file_entries} entries processed")

    except FileNotFoundError:
    print(f"Error: File {file_path} not found")
    continue
    except Exception as e:
    print(f"Error reading file {file_path}: {e}")
    continue

    stats = {
    'total_entries': total_entries,
    'swagger_matches': swagger_matches,
    'fallback_matches': fallback_matches,
    'skipped_entries': skipped_entries,
    'unique_endpoints': len(endpoint_counts),
    'total_api_calls': sum(endpoint_counts.values())
    }

    print(f"\nParsing complete:")
    print(f" Total log entries: {total_entries}")
    print(f" Swagger-based matches: {swagger_matches}")
    print(f" Fallback matches: {fallback_matches}")
    print(f" Unique endpoints found: {len(endpoint_counts)}")
    print(f" Total API calls: {sum(endpoint_counts.values())}")
    print(f" Skipped entries: {skipped_entries}")

    return endpoint_counts, stats


    def write_results(endpoint_counts, stats, swagger_mapper=None, output_file=None, sort_by='count'):
    """
    Write results to file or stdout.
    Args:
    endpoint_counts (Counter): Endpoint counts
    stats (dict): Parsing statistics
    swagger_mapper (SwaggerEndpointMapper): Mapper for finding missing endpoints
    output_file (str, optional): Output file path
    sort_by (str): Sort method - 'count' (descending) or 'name' (alphabetical)
    """
    if sort_by == 'count':
    sorted_endpoints = endpoint_counts.most_common()
    sort_desc = "sorted by count (descending)"
    elif sort_by == 'name':
    sorted_endpoints = sorted(endpoint_counts.items(), key=lambda x: x[0].lower())
    sort_desc = "sorted alphabetically"
    else:
    sorted_endpoints = endpoint_counts.most_common()
    sort_desc = "sorted by count (descending)"

    output = []
    output.append("Kubernetes API Endpoints Found in Audit Log (Swagger-Enhanced)")
    output.append("=" * 70)
    output.append(f"Total unique endpoints: {stats['unique_endpoints']}")
    output.append(f"Total API calls: {stats['total_api_calls']}")
    output.append(f"Swagger-based matches: {stats['swagger_matches']}")
    output.append(f"Fallback matches: {stats['fallback_matches']}")
    output.append(f"Skipped entries: {stats['skipped_entries']}")
    output.append(f"Results {sort_desc}")
    output.append("")
    output.append("Endpoint Name (OpenAPI Operation ID) | Count")
    output.append("-" * 70)

    for endpoint, count in sorted_endpoints:
    output.append(f"{endpoint} | {count}")

    # Find and display missing endpoints from Swagger spec
    if swagger_mapper and swagger_mapper.path_to_operation:
    all_swagger_operations = set(swagger_mapper.path_to_operation.values())
    found_operations = set(endpoint_counts.keys())

    # Only count operations that are actually from Swagger (not fallback)
    swagger_found = found_operations & all_swagger_operations
    missing_operations = all_swagger_operations - swagger_found

    # Filter out alpha and beta versions from missing operations
    stable_missing_operations = {
    op for op in missing_operations
    if not any(version in op for version in ['V1alpha', 'V1beta', 'V2alpha', 'V2beta', 'V3alpha', 'V3beta', 'alpha', 'beta'])
    }

    if stable_missing_operations:
    filtered_count = len(missing_operations) - len(stable_missing_operations)

    output.append("")
    output.append("=" * 70)
    output.append("STABLE ENDPOINTS NOT FOUND IN AUDIT LOG")
    output.append("=" * 70)
    output.append(f"Total missing stable endpoints: {len(stable_missing_operations)}")
    if filtered_count > 0:
    output.append(f"(Filtered out {filtered_count} alpha/beta endpoints)")
    output.append(f"These are stable API endpoints defined in the Swagger spec but not exercised in this audit log:")
    output.append("")

    # Sort missing operations alphabetically
    for operation in sorted(stable_missing_operations):
    output.append(f"{operation} | NOT FOUND")

    result_text = "\n".join(output)

    if output_file:
    try:
    with open(output_file, 'w') as f:
    f.write(result_text)
    print(f"\nResults written to: {output_file}")
    except Exception as e:
    print(f"Error writing to file: {e}")
    print("\nResults:")
    print(result_text)
    else:
    print("\nResults:")
    print(result_text)


    def main():
    """Main function to parse command line arguments and run the parser."""
    parser = argparse.ArgumentParser(
    description='Parse Kubernetes audit log using official Swagger/OpenAPI specification',
    formatter_class=argparse.RawDescriptionHelpFormatter,
    epilog="""
    Examples:
    python3 audit_log_parser_swagger.py audit.log
    python3 audit_log_parser_swagger.py audit1.log audit2.log
    python3 audit_log_parser_swagger.py audit.log --output results.txt
    python3 audit_log_parser_swagger.py audit*.log --sort count --output results.txt
    python3 audit_log_parser_swagger.py audit.log --swagger-url https://custom-swagger.json
    """
    )

    parser.add_argument('audit_logs', nargs='+', help='Path(s) to Kubernetes audit log file(s)')
    parser.add_argument('-o', '--output', help='Output file (default: print to stdout)')
    parser.add_argument('--swagger-url', help='Custom Swagger/OpenAPI specification URL')
    parser.add_argument('--sort', choices=['count', 'name'], default='name',
    help='Sort results by count (descending) or name (alphabetical). Default: name')

    args = parser.parse_args()

    # Initialize Swagger mapper
    swagger_mapper = SwaggerEndpointMapper(args.swagger_url)

    # Verify Swagger spec is loaded (will have already exited if not)
    if not swagger_mapper.swagger_spec:
    print("Error: Failed to load Swagger specification")
    sys.exit(1)

    # Parse the audit log(s)
    endpoint_counts, stats = parse_audit_logs(args.audit_logs, swagger_mapper)

    if not endpoint_counts:
    print("No endpoints found or error parsing file")
    sys.exit(1)

    # Write results
    write_results(endpoint_counts, stats, swagger_mapper, args.output, args.sort)


    if __name__ == '__main__':
    main()