소스 정보
- 저장소
- leroyguillaume/claude
- 최근 소스 활동
- 2026년 6월 30일 08:10
- 감지된 SKILL.md 언어
- 영어
- 스타
- 4
- 포크
- 2
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/leroyguillaume/claude --skill kubernetes-operator-conventions명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | kubernetes-operator-conventions |
| description | Kubernetes operator / controller conventions (error handling, |
These rules govern any reconcile path: the handler itself and everything it
calls (clients, token providers, DB access). The mechanics below are written
for kopf (this repo's framework); the same principles map onto
controller-runtime (return ctrl.Result{Requeue: true}, err) and Operator SDK.
This is the non-negotiable core rule.
kopf.TemporaryError (which logs, posts an
event, and re-schedules) and never kopf.PermanentError — a permanent
error stops the retries, which violates this rule. A bare raise of an
arbitrary exception also requeues, but prefer TemporaryError so you control
the message and delay.reason / response message, not just an HTTP status code,
and never the raw stack trace as the only signal.kubectl describe. Do not assume the framework does this for free on a
raised error. In kopf specifically, settings.posting.enabled = True
only enables explicit kopf.event(...) calls — a raised
TemporaryError posts no event unless settings.posting.loggers is
also on (it defaults to False). Post the event explicitly (e.g. a
ProvisioningFailed Warning from a reconcile wrapper). See the
kopf-conventions skill for the full posting model and the gotcha.5xx, 429, network/timeout): retry quickly (e.g. 30s).4xx such as 422 invalid manifest, 403
RBAC; or a failed spec validation): retry slowly (e.g. 300s) to avoid a
hot loop, since they need an external change — but still retry.errors.py) exposing a requeue()
chokepoint plus raise_for_* helpers that extract the cause, log it, and
requeue. Route every reconcile-path failure through it instead of scattering
bare raise_for_status() / re-raises. Extract the shared helper as soon as a
second call site appears in a third module (rule of three across the
operator's I/O surfaces).Anti-patterns to fix on sight: raise kopf.PermanentError; re-raising a raw
ApiException / httpx.HTTPStatusError out of a handler; logging only
status without the reason; swallowing an error and returning so the
resource silently stops reconciling.
409) on create and not-found (404) on
delete as success, not failure — log and continue.404/already-gone is success).When generating CRD YAML (e.g. a crd CLI subcommand driven by the Pydantic /
typed spec models), emit one file per kind into an output directory, not a
single --kind selector or one concatenated file. The generator owns the
filename↔manifest mapping in a single place (e.g. an all_crds() registry next
to the builders) so the CLI stays a thin caller and the pre-commit hook is one
entry, not one-per-kind.
Name each file after the kind in kebab-case, acronym-aware — never glue the words together:
Tenant → tenant.yamlTenantMCPServer → tenant-mcp-server.yaml (not tenantmcpserver.yaml)Kebab conversion needs two passes: split lower/digit→upper boundaries
((?<=[a-z0-9])(?=[A-Z])), then acronym→word boundaries
((?<=[A-Z])(?=[A-Z][a-z]), the P→Server split in MCPServer), then
lowercase. A naive .lower() of the PascalCase kind glues acronyms and is wrong.
Default the command with no output dir to a multi-document YAML stream on
stdout (all kinds, ----separated). A single pre-commit hook regenerates the
whole crds/ directory and the files: regex covers the spec modules plus
crds/.*\.yaml, so the committed CRDs can never drift from the models.
type: "null"A Kubernetes structural schema rejects both type: "null" and an anyOf
node that lacks its own type. Pydantic emits an optional T | None field as
anyOf: [{type: T}, {type: "null"}], which the apiserver refuses on kubectl apply of the CRD. When converting a spec model's JSON Schema to the CRD's
OpenAPI v3 subset, collapse <type> | null unions into the single branch with
nullable: true (carrying over sibling keywords like description). The same
converter must strip additionalProperties: false wherever it sits next to
properties (Pydantic's extra="forbid" leaks it, and structural schemas
forbid the pair). Add a test that walks the generated CRD asserting no node has
type: "null" nor additionalProperties: false beside properties.
Every write to the API (server-side apply, JSON/merge/strategic-merge patch,
create, update) must set an explicit, stable field_manager equal to the
operator's name (e.g. tenant-operator). Never let the client default it:
the apiserver will then attribute the fields to a generic or empty manager,
which is invisible to downstream tooling.
This is non-negotiable because anything that reads .metadata.managedFields
relies on the manager name being recognisable:
managedFieldsManagers (and Flux's
equivalent) tells the GitOps engine "this manager owns these fields, don't
flag them as drift". The lookup is by exact manager name. If the
operator's writes don't carry a recognisable manager, the GitOps engine
cannot defer ownership and the resource stays permanently OutOfSync.kubectl get ... -o yaml
shows nameless entries) and force_conflicts decisions become guesswork.kubectl get ... --show-managed-fields becomes the
canonical answer to "who last wrote this field?". A blank or generic
manager defeats the audit.Apply this uniformly: the SSA call, every patch helper (json-patch+json,
merge-patch+json, strategic-merge-patch+json), and any direct
create/update. Centralise the constant (FIELD_MANAGER = "<operator>")
in one module so every I/O call site uses the same string. A patch helper
that silently omits field_manager is a bug to fix on sight — even if the
write succeeds, it breaks the contract with GitOps and audit tooling
downstream.
The manager appears in managedFields only after a successful write to
the resource — creation by another controller is not enough. When debugging
"my manager doesn't show up", force at least one reconcile that actually
writes, then re-check.
LOG_LEVEL), never a
bespoke flag. Emit debug logs around every external call (inputs + outcome)
and at each decision branch, so a failure is diagnosable from logs alone.kubectl describe, not the operator's pod
logs.text, not jsontext, never json. A human
running kubectl logs reads key=value far more easily than one JSON object
per line. JSON is opt-in for clusters with a log pipeline that parses it.LOG_FORMAT (default text) and keep the binary's default
and the chart's default in sync — don't ship a chart whose logging.format
default disagrees with what the operator does on its own.README.md (a
Troubleshooting section): where to look (events + logs), and the
requeue-always behaviour with the per-class delays.