-
Notifications
You must be signed in to change notification settings - Fork 34
service_key: support editable-only API endpoints #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: devel
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -483,6 +483,23 @@ def _build_url(self, endpoint: str, query_params: Optional[Dict] = None) -> str: | |||||
|
|
||||||
| return url | ||||||
|
|
||||||
| def endpoint_supports_method(self, path: str, method: str) -> bool: | ||||||
| """Return whether an endpoint advertises an HTTP method via OPTIONS.""" | ||||||
| method = method.upper() | ||||||
| cache_key = f"endpoint-method:{path}:{method}" | ||||||
| if cache_key in self.cache: | ||||||
| return self.cache[cache_key] | ||||||
|
|
||||||
| response = self.session.options(self._build_url(path), timeout=self.request_timeout, verify=self.requests_verify) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🤖 get_repo_knowledge executed:
Length of output: 460 🏁 Script executed: #!/bin/bash
set -eu
file="plugins/plugin_utils/manager/platform_manager.py"
printf '%s\n' '--- targeted definitions and callers ---'
rg -n -C 18 'def (_make_request|endpoint_supports_method)|endpoint_supports_method\(|_make_request\(' "$file"
printf '%s\n' '--- imports and relevant helpers ---'
sed -n '1,120p' "$file"
printf '%s\n' '--- focused implementation context ---'
sed -n '430,525p' "$file"Repository: ansible/ansible.platform Length of output: 16371 🏁 Script executed: #!/bin/bash
set -eu
file="plugins/plugin_utils/manager/platform_manager.py"
printf '%s\n' '--- _make_request implementation ---'
sed -n '130,225p' "$file"
printf '%s\n' '--- endpoint_supports_method implementations and callers ---'
rg -n -C 12 'def endpoint_supports_method|endpoint_supports_method\(' plugins
printf '%s\n' '--- direct client request path and JSON fallback ---'
rg -n -C 16 'response\.json\(\)\.get\("actions"|options\(|_make_request\("OPTIONS"|operation="options"' plugins
printf '%s\n' '--- scoped convention ---'
cat /tmp/coderabbit-repo-knowledge/ansible-ansible-platform-435f8a6c/conventions/repo-wide.mdRepository: ansible/ansible.platform Length of output: 23255 🏁 Script executed: #!/bin/bash
set -eu
file="plugins/plugin_utils/manager/platform_manager.py"
printf '%s\n' '--- authentication recovery implementation ---'
rg -n -C 20 'def _handle_auth_error|_handle_auth_error\(' "$file"
printf '%s\n' '--- retry contract and supported request methods ---'
rg -n -C 12 'def retry_http_request|class Retry|retry_http_request' plugins/plugin_utils/platform plugins/plugin_utils/managerRepository: ansible/ansible.platform Length of output: 16178 🏁 Script executed: #!/bin/bash
set -eu
sed -n '255,340p' plugins/plugin_utils/manager/platform_manager.pyRepository: ansible/ansible.platform Length of output: 3493 Route the OPTIONS request through If the manager token expires after startup, the direct request returns 401 and Proposed fix- response = self.session.options(self._build_url(path), timeout=self.request_timeout, verify=self.requests_verify)
+ response = self._make_request("OPTIONS", self._build_url(path), operation="options", resource=path)📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| response.raise_for_status() | ||||||
| allowed = response.headers.get("Allow", "") | ||||||
| if allowed: | ||||||
| supported = method in {item.strip().upper() for item in allowed.split(",")} | ||||||
| else: | ||||||
| supported = method in response.json().get("actions", {}) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- target context ---'
sed -n '450,515p' plugins/plugin_utils/manager/platform_manager.py
printf '%s\n' '--- related definitions and callers ---'
rg -n -C 3 'def (endpoint_supports_method|_make_request)|endpoint_supports_method\(' plugins/plugin_utils tests 2>/dev/null | head -240Repository: ansible/ansible.platform Length of output: 6919 🤖 get_repo_knowledge executed:
Length of output: 414 🏁 Script executed: #!/bin/bash
set -eu
printf '%s\n' '--- manager request helper ---'
sed -n '110,205p' plugins/plugin_utils/manager/platform_manager.py
printf '%s\n' '--- direct-client capability implementation ---'
sed -n '1000,1055p' plugins/plugin_utils/platform/direct_client.py
printf '%s\n' '--- capability call sites ---'
rg -n -C 4 'endpoint_supports_method\(' plugins | head -180Repository: ansible/ansible.platform Length of output: 9564 Handle an empty OPTIONS body as unsupported. When 🤖 Prompt for AI Agents |
||||||
| self.cache[cache_key] = supported | ||||||
| return supported | ||||||
|
|
||||||
| def execute(self, operation: str, module_name: str, ansible_data_dict: dict) -> dict: | ||||||
| """ | ||||||
| Execute a generic operation on any resource. | ||||||
|
|
@@ -660,7 +677,7 @@ def _update_resource(self, ansible_data: Any, mixin_class: type, context: dict) | |||||
| lookup_field = mixin_class.get_lookup_field() | ||||||
| api_normalized_fields = {"slug"} | ||||||
| internal_fields = {"organization_id"} | ||||||
| skip_fields = read_only_fields | {"state", lookup_field} | api_normalized_fields | internal_fields | ||||||
| skip_fields = read_only_fields | {"state", "new_name", lookup_field} | api_normalized_fields | internal_fields | ||||||
| requested = asdict(ansible_data) | ||||||
| for k, v in requested.items(): | ||||||
| if k in skip_fields or v is None: | ||||||
|
|
@@ -703,7 +720,7 @@ def _update_resource(self, ansible_data: Any, mixin_class: type, context: dict) | |||||
| internal_fields = {"organization_id"} | ||||||
| norm = self._normalize_for_compare | ||||||
| lookup_field = mixin_class.get_lookup_field() | ||||||
| skip_fields = read_only_fields | {"state", lookup_field} | api_normalized_fields | internal_fields | ||||||
| skip_fields = read_only_fields | {"state", "new_name", lookup_field} | api_normalized_fields | internal_fields | ||||||
| requested = asdict(ansible_data) | ||||||
| changed = False | ||||||
| for k, v in requested.items(): | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Require an HTTP 405 error before suppressing creation failure.
The substring check accepts any error text that contains
405. For example, an error for service-cluster ID405can become a successful no-op result.Use a structured status code. If RPC serialization requires a text fallback, match an explicit HTTP status pattern instead of arbitrary digits.
🤖 Prompt for AI Agents