Last active
August 29, 2025 12:16
-
-
Save dims/1fc254d0e4d043ef18bbc84596785de2 to your computer and use it in GitHub Desktop.
Revisions
-
dims revised this gist
Aug 29, 2025 . 1 changed file with 439 additions and 46 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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) - 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 **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 **Command line usage**: ```bash # Basic comparison against latest CI baseline python3 kubernetes_api_analysis.py # Use specific baseline file (skip auto-download) python3 kubernetes_api_analysis.py --baseline-file ci-audit-endpoints.txt # Custom output directory python3 kubernetes_api_analysis.py --output-dir analysis-results/ # Detailed verbose output python3 kubernetes_api_analysis.py --verbose ``` **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 ## Enforcement Process ### For Pull Request Authors When the presubmit job identifies issues, contributors must follow the appropriate scenario guide above. The system enforces: 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 ## 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 **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 ### General Questions **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 ### 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. 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. -
dims renamed this gist
Aug 29, 2025 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
dims revised this gist
Aug 29, 2025 . 1 changed file with 228 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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. -
dims revised this gist
Aug 26, 2025 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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:** -
dims revised this gist
Aug 26, 2025 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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:** -
dims revised this gist
Aug 26, 2025 . 3 changed files with 186 additions and 1578 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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: ``` 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) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,624 +0,0 @@ This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,952 +0,0 @@ -
dims revised this gist
Aug 19, 2025 . 1 changed file with 952 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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 -
dims created this gist
Aug 19, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,3 @@ ``` python3 audit_log_parser_swagger.py ./1957781493858177024/artifacts/audit/audit*.log ``` This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal 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()