Documentation
¶
Overview ¶
Package reconcile makes Frontier platform resources match a desired-state file through the admin API. Each resource kind implements Reconciler and registers under its kind, so new kinds plug in without changing the command or file format. PlatformUser is the first kind.
Index ¶
- Constants
- func Export(ctx context.Context, registry map[string]Reconciler, kind string) ([]byte, error)
- type Op
- type PermissionAPI
- type PermissionReconciler
- type PermissionSpec
- type PlatformUserAPI
- type PlatformUserReconciler
- type PlatformUserSpec
- type PreferenceAPI
- type PreferenceReconciler
- type PreferenceSpec
- type Reconciler
- type Report
- type RoleAPI
- type RoleReconciler
- type RoleSpec
Constants ¶
const KindPermission = "Permission"
KindPermission is the desired-state document kind for custom permissions.
const KindPlatformUser = "PlatformUser"
KindPlatformUser is the desired-state document kind for platform users.
const KindPreference = "Preference"
KindPreference is the desired-state document kind for platform preferences.
const KindRole = "Role"
KindRole is the desired-state document kind for platform-level roles.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Op ¶
Op is a single planned change to one (principal, relation). Ref is the desired entry's ref for an add (email or id) and the current principal's id for a remove.
type PermissionAPI ¶ added in v0.110.0
type PermissionAPI interface {
ListPermissions(context.Context, *connect.Request[frontierv1beta1.ListPermissionsRequest]) (*connect.Response[frontierv1beta1.ListPermissionsResponse], error)
CreatePermission(context.Context, *connect.Request[frontierv1beta1.CreatePermissionRequest]) (*connect.Response[frontierv1beta1.CreatePermissionResponse], error)
DeletePermission(context.Context, *connect.Request[frontierv1beta1.DeletePermissionRequest]) (*connect.Response[frontierv1beta1.DeletePermissionResponse], error)
}
PermissionAPI is the API subset the permission reconciler needs. Reads live on FrontierService, writes on AdminService; the caller provides one value that serves both.
type PermissionReconciler ¶ added in v0.110.0
type PermissionReconciler struct {
// contains filtered or unexported fields
}
PermissionReconciler makes custom permissions match the desired spec. Base-schema permissions (app namespaces) are server-managed and ignored.
func NewPermissionReconciler ¶ added in v0.110.0
func NewPermissionReconciler(client PermissionAPI, header string) *PermissionReconciler
func (*PermissionReconciler) Export ¶ added in v0.110.0
func (r *PermissionReconciler) Export(ctx context.Context) (any, error)
Export returns the current custom permissions as a desired-state spec, sorted so repeated exports produce identical files.
func (*PermissionReconciler) Kind ¶ added in v0.110.0
func (r *PermissionReconciler) Kind() string
type PermissionSpec ¶ added in v0.110.0
type PermissionSpec struct {
Namespace string `yaml:"namespace"`
Name string `yaml:"name"`
Delete bool `yaml:"delete,omitempty"`
}
PermissionSpec is one desired permission. A permission is identity only (namespace + name): it is added or deleted, never updated. Deleting needs the explicit flag; a permission that just disappears from the file fails the plan instead.
func (PermissionSpec) String ¶ added in v0.110.0
func (s PermissionSpec) String() string
type PlatformUserAPI ¶
type PlatformUserAPI interface {
ListPlatformUsers(context.Context, *connect.Request[frontierv1beta1.ListPlatformUsersRequest]) (*connect.Response[frontierv1beta1.ListPlatformUsersResponse], error)
AddPlatformUser(context.Context, *connect.Request[frontierv1beta1.AddPlatformUserRequest]) (*connect.Response[frontierv1beta1.AddPlatformUserResponse], error)
RemovePlatformUser(context.Context, *connect.Request[frontierv1beta1.RemovePlatformUserRequest]) (*connect.Response[frontierv1beta1.RemovePlatformUserResponse], error)
}
PlatformUserAPI is the subset of the admin API the platform-user reconciler needs. frontierv1beta1connect.AdminServiceClient satisfies it.
type PlatformUserReconciler ¶
type PlatformUserReconciler struct {
// contains filtered or unexported fields
}
PlatformUserReconciler makes platform admins and members match the desired spec.
func NewPlatformUserReconciler ¶
func NewPlatformUserReconciler(client PlatformUserAPI, header string) *PlatformUserReconciler
func (*PlatformUserReconciler) Export ¶ added in v0.110.0
func (r *PlatformUserReconciler) Export(ctx context.Context) (any, error)
Export returns the current platform users as a desired-state spec: one entry per (principal, relation), users referenced by email when they have one. Entries are sorted so repeated exports produce identical files.
func (*PlatformUserReconciler) Kind ¶
func (r *PlatformUserReconciler) Kind() string
type PlatformUserSpec ¶
type PlatformUserSpec struct {
Type string `yaml:"type"` // "user" | "serviceuser"
Ref string `yaml:"ref"` // email or uuid for a user; id for a service user
Relation string `yaml:"relation"` // "admin" | "member"
}
PlatformUserSpec is one desired platform-user entry from the YAML spec. Relation is "admin" or "member" — a SpiceDB relation, not an RBAC "role" (a separate concept in Frontier), hence the field name.
type PreferenceAPI ¶ added in v0.110.0
type PreferenceAPI interface {
ListPreferences(context.Context, *connect.Request[frontierv1beta1.ListPreferencesRequest]) (*connect.Response[frontierv1beta1.ListPreferencesResponse], error)
DescribePreferences(context.Context, *connect.Request[frontierv1beta1.DescribePreferencesRequest]) (*connect.Response[frontierv1beta1.DescribePreferencesResponse], error)
CreatePreferences(context.Context, *connect.Request[frontierv1beta1.CreatePreferencesRequest]) (*connect.Response[frontierv1beta1.CreatePreferencesResponse], error)
}
PreferenceAPI is the API subset the preference reconciler needs. The reads live on different services (platform preferences on AdminService, the trait list on FrontierService); the caller provides one value that serves both.
type PreferenceReconciler ¶ added in v0.110.0
type PreferenceReconciler struct {
// contains filtered or unexported fields
}
PreferenceReconciler makes platform preferences match the desired spec. A preference is a name and a value; a missing entry resets to the trait default, because settings always have a default to fall back to.
func NewPreferenceReconciler ¶ added in v0.110.0
func NewPreferenceReconciler(client PreferenceAPI, header string) *PreferenceReconciler
func (*PreferenceReconciler) Export ¶ added in v0.110.0
func (r *PreferenceReconciler) Export(ctx context.Context) (any, error)
Export returns the platform preferences whose value differs from the trait default, sorted by name. Preferences at their default stay out of the file, so reconciling an export plans no changes.
func (*PreferenceReconciler) Kind ¶ added in v0.110.0
func (r *PreferenceReconciler) Kind() string
type PreferenceSpec ¶ added in v0.110.0
PreferenceSpec is one desired platform preference. Name is a trait name the server knows; value is the string value to set. Preferences are strings end to end, so a boolean-like trait is "true" or "false".
type Reconciler ¶
type Reconciler interface {
Kind() string
Reconcile(ctx context.Context, spec []byte, dryRun bool) (Report, error)
Export(ctx context.Context) (spec any, err error)
}
Reconciler makes a single resource kind match its desired-state spec. Export is the reverse direction and is part of the contract: it reads the current server state and returns it as a spec value, ready to be marshalled into a desired-state document. Reconciling an exported document must plan no changes.
type Report ¶
type Report struct {
Kind string
DryRun bool
Planned []string // the plan, human-readable
Applied int // number actually applied (0 when dryRun)
}
Report summarises what a reconcile did, or would do when dryRun.
func Run ¶
func Run(ctx context.Context, registry map[string]Reconciler, data []byte, dryRun bool) ([]Report, error)
Run applies a (possibly multi-document) desired-state file. The whole file is parsed and checked first, so a malformed later document stops the run before anything applies. Documents then dispatch in file order — dependency order is the file author's job — and the first error stops the run and returns the reports gathered so far.
type RoleAPI ¶ added in v0.110.0
type RoleAPI interface {
ListRoles(context.Context, *connect.Request[frontierv1beta1.ListRolesRequest]) (*connect.Response[frontierv1beta1.ListRolesResponse], error)
CreateRole(context.Context, *connect.Request[frontierv1beta1.CreateRoleRequest]) (*connect.Response[frontierv1beta1.CreateRoleResponse], error)
UpdateRole(context.Context, *connect.Request[frontierv1beta1.UpdateRoleRequest]) (*connect.Response[frontierv1beta1.UpdateRoleResponse], error)
DeleteRole(context.Context, *connect.Request[frontierv1beta1.DeleteRoleRequest]) (*connect.Response[frontierv1beta1.DeleteRoleResponse], error)
}
RoleAPI is the API subset the role reconciler needs. Reads live on FrontierService, writes on AdminService; the caller provides one value that serves both.
type RoleReconciler ¶ added in v0.110.0
type RoleReconciler struct {
// contains filtered or unexported fields
}
RoleReconciler makes platform-level roles match the desired spec. The role name is the identity; title, permissions, and scopes are the managed fields.
func NewRoleReconciler ¶ added in v0.110.0
func NewRoleReconciler(client RoleAPI, header string) *RoleReconciler
func (*RoleReconciler) Export ¶ added in v0.110.0
func (r *RoleReconciler) Export(ctx context.Context) (any, error)
Export returns the current platform roles as a desired-state spec. Custom roles are exported in full. Predefined roles are exported only when they differ from their shipped definition (title, permissions, or scopes), and only with the differing fields, so converged ones stay out of the file. The comparisons mirror diffPredefinedRole exactly — including skipping fields that are empty on the server, which a file cannot represent — so reconciling an export's output always plans no changes.
func (*RoleReconciler) Kind ¶ added in v0.110.0
func (r *RoleReconciler) Kind() string
type RoleSpec ¶ added in v0.110.0
type RoleSpec struct {
Name string `yaml:"name"`
Title string `yaml:"title,omitempty"`
Description string `yaml:"description,omitempty"`
Permissions []string `yaml:"permissions,omitempty"`
Scopes []string `yaml:"scopes,omitempty"`
Delete bool `yaml:"delete,omitempty"`
}
RoleSpec is one desired platform-level role. Name is the identity and never changes. For custom roles, a field that is present is managed and a field that is omitted keeps its server value; permissions must be listed. Predefined roles converge to their shipped definition instead: an entry overrides the fields it lists, an omitted field takes the definition's value, and a predefined role absent from the file resets to the definition. Predefined roles cannot be deleted — bootstrap recreates a missing one on the next boot.