Documentation
¶
Overview ¶
Package types provides common type definitions used across the GitOps Reverser.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ResourceIdentifier ¶
type ResourceIdentifier struct {
Group string // e.g., "apps", "" for core resources
Version string // e.g., "v1"
Resource string // Plural form, e.g., "deployments", "pods"
Namespace string // Empty string for cluster-scoped resources
Name string // Resource name
}
ResourceIdentifier encapsulates all information needed to uniquely identify a Kubernetes resource. Its Key() is the fully-qualified REST-style identity ({group}/{version}/{resource}/{namespace}/{name}); its ToGitPath() is the versionless, namespace-first Git storage path (see that method).
func NewResourceIdentifier ¶
func NewResourceIdentifier(group, version, resource, namespace, name string) ResourceIdentifier
NewResourceIdentifier creates a ResourceIdentifier from explicit parts. Useful for watch-based ingestion where we know group/version/resource.
func (ResourceIdentifier) IsClusterScoped ¶
func (r ResourceIdentifier) IsClusterScoped() bool
IsClusterScoped returns true if the resource is cluster-scoped.
func (ResourceIdentifier) Key ¶
func (r ResourceIdentifier) Key() string
Key returns a stable, fully-qualified identifier suitable for map keys and deduplication.
The exact string is a public contract. Tools built around GitOps Reverser key their own rows on this identity and join them against ours, so a consumer that cannot import this package (it lives under internal/) reimplements the format from this comment. Changing any byte of it is a breaking change rather than a refactor, and TestResourceIdentifier_Key_GoldenFormat is the gate that turns such a change into a decision instead of a silent split.
namespaced: "{group}/{version}/{resource}/{namespace}/{name}"
cluster-scoped: "{group}/{version}/{resource}/{name}"
Two rules a reimplementation has to get right, and they pull in opposite directions:
- A cluster-scoped resource DROPS the namespace segment; it does not emit an empty one. Always joining five parts yields "…/clusterroles//admin", which never joins.
- A core-group resource has an EMPTY group segment, which it does emit, so the key leads with "/".
The four shapes, which are the four cases of the golden test:
apps/v1/deployments/prod/api namespaced, grouped rbac.authorization.k8s.io/v1/clusterroles/admin cluster-scoped, grouped /v1/secrets/prod/db namespaced, core group /v1/nodes/node-1 cluster-scoped, core group
Key versus ToGitPath: which one is "the same resource" ¶
Key includes Version and ResourceIdentifier.ToGitPath deliberately excludes it, so the two disagree about whether a preferred-version bump is the same object. The decision, recorded at both methods: Key is the API-side identity — correct for in-process map keys, deduplication and logs, where every participant observes one version at a time — and the versionless, namespace-first path is the DURABLE identity of the object, which is why a storage-version bump moves no file in Git.
A join that must survive a storage-version bump is therefore keyed on the versionless identity, not on Key. Consumers holding rows across releases should drop the version segment (the second) rather than treat "apps/v1/deployments/prod/api" and "apps/v2/deployments/prod/api" as two resources.
Example ¶
ExampleResourceIdentifier_Key shows the four shapes of the key format, including the two empty-segment rules that pull in opposite directions.
namespaced := ResourceIdentifier{
Group: "apps", Version: "v1", Resource: "deployments", Namespace: "prod", Name: "api",
}
clusterScoped := ResourceIdentifier{
Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles", Name: "admin",
}
coreNamespaced := ResourceIdentifier{
Version: "v1", Resource: "secrets", Namespace: "prod", Name: "db",
}
coreClusterScoped := ResourceIdentifier{
Version: "v1", Resource: "nodes", Name: "node-1",
}
fmt.Println(namespaced.Key())
fmt.Println(clusterScoped.Key()) // no empty namespace segment
fmt.Println(coreNamespaced.Key()) // empty group: a leading "/"
fmt.Println(coreClusterScoped.Key()) // both rules at once
Output: apps/v1/deployments/prod/api rbac.authorization.k8s.io/v1/clusterroles/admin /v1/secrets/prod/db /v1/nodes/node-1
func (ResourceIdentifier) String ¶
func (r ResourceIdentifier) String() string
String returns a human-readable representation.
func (ResourceIdentifier) ToGitPath ¶
func (r ResourceIdentifier) ToGitPath() string
ToGitPath generates the canonical Git file path for a new resource: {namespace-or-cluster}/{group}/{resource}/{name}.yaml. The scope segment leads (a real namespace, or the literal "_cluster" for a cluster-scoped resource) so a repository reads namespace-first, the way a human browses it; the API group is omitted for core resources, and the API version is deliberately left out — the operator writes one version per object, so a version segment adds noise and would churn the path on a preferred-version bump. This is only the cold-start fallback: once any layout exists in the target, sibling inference follows it, and an existing document is always edited in place at its current location (match-first), so changing this shape never moves a file that is already in Git. See docs/spec/gittarget-new-file-placement-rules.md.
That omitted version is the other half of the decision recorded at ResourceIdentifier.Key: this versionless identity is the durable one — the object stays the same object across a preferred-version bump — while Key is the API-side identity and splits on that bump. Neither is wrong; they answer different questions, and a caller joining data that outlives a release wants this one.
Example ¶
ExampleResourceIdentifier_ToGitPath contrasts the two identity functions on one object: the key carries the API version, the path deliberately does not.
deployment := ResourceIdentifier{
Group: "apps", Version: "v1", Resource: "deployments", Namespace: "prod", Name: "api",
}
node := ResourceIdentifier{Version: "v1", Resource: "nodes", Name: "node-1"}
fmt.Println(deployment.Key())
fmt.Println(deployment.ToGitPath())
fmt.Println(node.Key())
fmt.Println(node.ToGitPath()) // cluster-scoped resources live under "_cluster"
Output: apps/v1/deployments/prod/api prod/apps/deployments/api.yaml /v1/nodes/node-1 _cluster/nodes/node-1.yaml
type ResourceReference ¶
ResourceReference references a Kubernetes resource by name and namespace. Provides a clean, reusable type for referencing GitDestinations and other resources.
UID, when set, identifies the specific object generation. It is deliberately excluded from String/Key/Equal so in-memory bookkeeping stays keyed by namespace/name; it scopes durable Redis keys (e.g. watch cursors) so a recreated GitTarget never inherits a deleted predecessor's state.
func NewResourceReference ¶
func NewResourceReference(name, namespace string) ResourceReference
NewResourceReference creates a new resource reference.
func (ResourceReference) Equal ¶
func (r ResourceReference) Equal(other ResourceReference) bool
Equal checks if two references are equal.
func (ResourceReference) IsZero ¶
func (r ResourceReference) IsZero() bool
IsZero returns true if this is an empty reference.
func (ResourceReference) Key ¶
func (r ResourceReference) Key() string
Key returns a string key suitable for map lookups: "namespace/name".
Not to be confused with ResourceIdentifier.Key, which is the fully-qualified "{group}/{version}/{resource}/{namespace}/{name}" identity of a watched object. This one names a GitTarget-like object by reference and carries no group, version or resource.
func (ResourceReference) String ¶
func (r ResourceReference) String() string
String returns "namespace/name" format.
func (ResourceReference) WithUID ¶
func (r ResourceReference) WithUID(uid string) ResourceReference
WithUID returns a copy of the reference carrying the given object UID.
type SensitiveResourcePolicy ¶
type SensitiveResourcePolicy struct {
// contains filtered or unexported fields
}
SensitiveResourcePolicy classifies resource types that must use the encrypted Git write path. Core Kubernetes Secrets are always sensitive.
func ParseSensitiveResourcePolicy ¶
func ParseSensitiveResourcePolicy(additional string) (SensitiveResourcePolicy, error)
ParseSensitiveResourcePolicy builds a policy from comma-separated additional entries in resource or group/resource form.
func (SensitiveResourcePolicy) Entries ¶
func (p SensitiveResourcePolicy) Entries() []string
Entries returns the built-in and additional sensitive resource types in flag form.
func (SensitiveResourcePolicy) IsSensitive ¶
func (p SensitiveResourcePolicy) IsSensitive(group, resource string) bool
IsSensitive reports whether group/resource must use the encrypted Git write path.