Documentation
¶
Overview ¶
Package dataapi resolves which of the two API groups a cluster serves DataExport and DataImport under, and which of them the calling user is actually authorized to use.
Two different modules produce the same pair of CRDs:
- storage-foundation serves them under FoundationGroup. It supersedes the older module and is what a cluster with storage-foundation enabled exposes.
- storage-volume-data-manager serves them under LegacyGroup. Editions that ship that module alone expose this group and nothing else.
A single d8 binary has to work against both, so the group is a runtime decision rather than a compile-time constant. The decision cannot be made from the module list: `d8 data` is run by ordinary users, who are not authorized to read ModuleConfig, and whose RBAC may cover only one of the two groups even when the cluster serves both.
Index ¶
Constants ¶
const ( // FoundationGroup is the API group under which storage-foundation serves DataExport and // DataImport. Preferred whenever the cluster serves it and the user is authorized for it. FoundationGroup = "storage-foundation.deckhouse.io" // LegacyGroup is the API group under which storage-volume-data-manager serves DataExport // and DataImport. Used when the cluster does not serve FoundationGroup, or serves it but // denies the user access to it. LegacyGroup = "storage.deckhouse.io" // Version is the version both groups serve these CRDs under. Version = "v1alpha1" )
const ( ResourceDataExports = "dataexports" ResourceDataImports = "dataimports" )
Resource plurals this package can resolve a group for. Resolution is per resource rather than per group because a cluster is free to serve one CRD of the pair and not the other.
Variables ¶
var ( // FoundationGroupVersion is the storage-foundation GroupVersion of DataExport/DataImport. FoundationGroupVersion = schema.GroupVersion{Group: FoundationGroup, Version: Version} // LegacyGroupVersion is the storage-volume-data-manager GroupVersion of the same pair. LegacyGroupVersion = schema.GroupVersion{Group: LegacyGroup, Version: Version} )
var ErrForbidden = errors.New("not authorized to use this resource")
ErrForbidden reports that the cluster does serve the resource, but the calling user is not authorized for any group that serves it. This is deliberately distinct from ErrNoBackend: the fix is an RBAC grant, not enabling a module.
var ErrNoBackend = errors.New("no module in this cluster serves this resource")
ErrNoBackend reports that no candidate group serves the resource at all: neither producing module is installed, or neither has finished installing its CRDs.
Functions ¶
This section is empty.
Types ¶
type AccessReviewer ¶
type AccessReviewer interface {
Create(ctx context.Context, ssar *authv1.SelfSubjectAccessReview, opts metav1.CreateOptions) (*authv1.SelfSubjectAccessReview, error)
}
AccessReviewer answers "may the current user do this", via SelfSubjectAccessReview. client-go's typed SelfSubjectAccessReviewInterface satisfies it.
SelfSubjectAccessReview is used rather than a trial request because it is the only check every authenticated user may perform (ClusterRole system:basic-user is bound to system:authenticated) and because it does not create, read or mutate anything in the target namespace.
type Backend ¶
type Backend struct {
GroupVersion schema.GroupVersion
Module string
}
Backend is a resolved answer: the GroupVersion to address the CRD through, plus the module that serves it for messages.
func Resolve ¶
func Resolve(ctx context.Context, cfg *rest.Config, resource, namespace string, log *slog.Logger) (Backend, error)
Resolve picks the group to address resource through, for a user acting in namespace.
It answers two independent questions per candidate and combines them, because each alone is ambiguous:
- discovery: does the API server serve this group at all? RBAC does not affect the answer — a role naming a group that no CRD backs still parses, so permission alone cannot tell an installed module from an uninstalled one.
- SelfSubjectAccessReview: may this user read the resource in this namespace? Discovery does not affect the answer, so a served group alone cannot tell an authorized user from one whose grants were left behind by a previous edition.
The first candidate that is both served and not denied wins. When nothing qualifies, the returned error distinguishes "no module serves it" (ErrNoBackend) from "it is served but you may not use it" (ErrForbidden), naming what was found either way.
type ResourceLister ¶
type ResourceLister interface {
ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error)
}
ResourceLister reports which resources one group/version serves. *discovery.DiscoveryClient satisfies it.