tenant

package
v7.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package tenant provides services for multi-tenant Kubernetes onboarding, including RBAC manifest generation, GitOps sync resources, and tenant lifecycle management.

Index

Constants

View Source
const (
	// DefaultClusterRole is the default ClusterRole bound to tenant ServiceAccounts.
	DefaultClusterRole = "edit"
	// DefaultOutputDir is the default output directory.
	DefaultOutputDir = "."
	// DefaultSyncSource is the default sync source for Flux tenants.
	DefaultSyncSource = SyncSourceOCI
	// DefaultRepoVisibility is the default repository visibility.
	DefaultRepoVisibility = "Private"
)
View Source
const (

	// DefaultArgoCDRBACCMFilename is the default filename when creating a new argocd-rbac-cm file.
	DefaultArgoCDRBACCMFilename = "argocd-rbac-cm.yaml"
)

Variables

View Source
var (
	// ErrInvalidType is returned when an invalid tenant type is provided.
	ErrInvalidType = errors.New("invalid tenant type")
	// ErrTenantNameRequired is returned when the tenant name is empty.
	ErrTenantNameRequired = errors.New("tenant name is required")
	// ErrTenantTypeRequired is returned when the tenant type is not specified and cannot be auto-detected.
	ErrTenantTypeRequired = errors.New(
		"tenant type is required (use --type flag or configure gitOpsEngine in ksail.yaml)",
	)
	// ErrKustomizationNotFound is returned when no kustomization.yaml is found.
	ErrKustomizationNotFound = errors.New("kustomization.yaml not found")
	// ErrKustomizationIsDirectory is returned when the kustomization path points to a directory.
	ErrKustomizationIsDirectory = errors.New("kustomization path is a directory, not a file")
	// ErrInvalidTenantName is returned when the tenant name is not a valid DNS-1123 label.
	ErrInvalidTenantName = errors.New("invalid tenant name")
	// ErrInvalidNamespace is returned when a namespace is not a valid DNS-1123 label.
	ErrInvalidNamespace = errors.New("invalid namespace")
	// ErrDuplicateNamespace is returned when duplicate namespaces are provided.
	ErrDuplicateNamespace = errors.New("duplicate namespaces are not allowed")
	// ErrNamespaceRequired is returned when no namespace is provided.
	ErrNamespaceRequired = errors.New("at least one namespace is required")
	// ErrGitProviderRequired is returned when --git-provider is required but not set.
	ErrGitProviderRequired = errors.New("--git-provider is required")
	// ErrTenantRepoRequired is returned when --tenant-repo is required but not set.
	ErrTenantRepoRequired = errors.New("--tenant-repo is required")
	// ErrRegistryRequired is returned when --registry is required but not set.
	ErrRegistryRequired = errors.New("--registry is required for Flux OCI sync source")
	// ErrUnsupportedSyncSource is returned when an unsupported sync source is specified.
	ErrUnsupportedSyncSource = errors.New("unsupported sync source")
	// ErrTenantAlreadyExists is returned when a tenant directory already exists.
	ErrTenantAlreadyExists = errors.New("tenant directory already exists")
	// ErrTenantDirNotExist is returned when a tenant directory does not exist.
	ErrTenantDirNotExist = errors.New("tenant directory does not exist")
	// ErrOutsideKustomizationRoot is returned when a tenant path is outside the kustomization root.
	ErrOutsideKustomizationRoot = errors.New("tenant directory is outside the kustomization root")
	// ErrInvalidDelivery is returned when an invalid --delivery value is provided.
	ErrInvalidDelivery = errors.New("invalid --delivery value")
	// ErrInvalidSyncSource is returned when an invalid --sync-source value is provided.
	ErrInvalidSyncSource = errors.New("invalid --sync-source value")
	// ErrConfigNotFound is returned when no --type is specified and no ksail.yaml is found.
	ErrConfigNotFound = errors.New(
		"no --type specified and no ksail.yaml found: " +
			"please specify --type (flux, argocd, or kubectl)",
	)
	// ErrDeleteRepoGitProviderRequired is returned when --git-provider is required with --delete-repo.
	ErrDeleteRepoGitProviderRequired = errors.New(
		"--git-provider is required when --delete-repo is set",
	)
	// ErrDeleteRepoTenantRepoRequired is returned when --tenant-repo is required with --delete-repo.
	ErrDeleteRepoTenantRepoRequired = errors.New(
		"--tenant-repo is required when --delete-repo is set",
	)
	// ErrPlatformRepoRequired is returned when the platform repo cannot be resolved.
	ErrPlatformRepoRequired = errors.New(
		"--platform-repo is required (or run from a git repo with a remote)",
	)
	// ErrOutsideRepoRoot is returned when a collected file path escapes the repo root.
	ErrOutsideRepoRoot = errors.New("file is outside the repository root")
	// ErrRBACConfigMapNotFound is returned when no argocd-rbac-cm ConfigMap file is found.
	ErrRBACConfigMapNotFound = errors.New("no argocd-rbac-cm ConfigMap found")
)

Functions

func CollectDeliveryFiles

func CollectDeliveryFiles(
	tenantName, outputDir, kustomizationPath, repoRoot string,
) (map[string][]byte, error)

CollectDeliveryFiles reads generated tenant files and optionally kustomization.yaml from disk, returning a map of repo-relative paths to file contents.

func Delete

func Delete(ctx context.Context, opts DeleteOptions) error

Delete removes a tenant's manifests and optionally unregisters and deletes the repo.

func DeliverPR

func DeliverPR(ctx context.Context, opts DeliverPROptions) (string, error)

DeliverPR orchestrates delivering tenant changes as a pull request:

  1. Resolves the platform repo (explicit or auto-detected from git remote)
  2. Determines the target branch (explicit or repo default)
  3. Collects generated/modified files from disk
  4. Creates a feature branch, pushes files, and opens a PR

Returns the PR URL on success.

func DetectPlatformRepo

func DetectPlatformRepo(ctx context.Context, dir string) (string, error)

DetectPlatformRepo extracts the owner/repo from the git remote of the directory containing the generated manifests.

func FindArgoCDRBACCM

func FindArgoCDRBACCM(dir string) (string, error)

FindArgoCDRBACCM scans YAML files in the given directory for a ConfigMap named "argocd-rbac-cm" (apiVersion: v1, kind: ConfigMap). Returns the file path if found, or empty string if not found. Supports multi-document YAML files separated by "---".

func FindKustomization

func FindKustomization(startDir string) (string, error)

FindKustomization walks up from startDir looking for kustomization.yaml. Returns the path to the first kustomization.yaml found, or error if none found.

func Generate

func Generate(opts Options) error

Generate creates a complete tenant directory with all required manifests. It orchestrates RBAC + type-specific resource generation, writes files to disk, and generates the tenant's kustomization.yaml.

Directory layout: <opts.OutputDir>/<opts.Name>/

namespace.yaml, serviceaccount.yaml, rolebinding.yaml,
kustomization.yaml, [sync.yaml], [project.yaml, app.yaml]

func GenerateArgoCDManifests

func GenerateArgoCDManifests(opts Options) (map[string]string, error)

GenerateArgoCDManifests generates ArgoCD-specific tenant manifests. Returns a map of filename -> YAML content. Files: project.yaml, app.yaml

Note: ArgoCD RBAC ConfigMap (argocd-rbac-cm) is NOT generated per-tenant to avoid kustomize conflicts when multiple tenants share the same namespace. Use MergeArgoCDRBACPolicy to add tenant policies to a shared argocd-rbac-cm.

func GenerateFluxSyncManifests

func GenerateFluxSyncManifests(opts Options) (map[string]string, error)

GenerateFluxSyncManifests generates Flux-specific sync manifests. Returns a map of filename -> YAML content. Files: sync.yaml (multi-doc: source CR + Kustomization CR).

func GenerateRBACManifests

func GenerateRBACManifests(opts Options) (map[string]string, error)

GenerateRBACManifests generates RBAC manifests for a tenant. Returns a map of filename -> YAML content. Files: namespace.yaml, serviceaccount.yaml, rolebinding.yaml

A single ServiceAccount is created in the primary namespace (Namespaces[0]). A RoleBinding is created in each namespace, referencing the primary-namespace SA.

func ManagedByLabels

func ManagedByLabels() map[string]string

ManagedByLabels returns the standard KSail managed-by labels.

func MergeArgoCDRBACPolicy

func MergeArgoCDRBACPolicy(existingContent string, tenantName string) (string, error)

MergeArgoCDRBACPolicy intelligently merges tenant policies into existing argocd-rbac-cm content. If existingContent is empty, creates a new ConfigMap. Uses map[string]any for round-trip fidelity to preserve unknown fields.

func MergeArgoCDRBACPolicyFile

func MergeArgoCDRBACPolicyFile(rbacCMPath, tenantName string) error

MergeArgoCDRBACPolicyFile reads an existing argocd-rbac-cm file (or creates a new one) and merges the tenant's RBAC policy into it.

func ParseRemoteURL

func ParseRemoteURL(remoteURL string) (string, error)

ParseRemoteURL extracts owner/repo from a git remote URL. Supports SCP-style SSH (git@host:owner/repo.git), ssh:// URLs, and HTTPS formats.

func RegisterResource

func RegisterResource(kustomizationPath, resourceName string) error

RegisterResource adds a resource name to a kustomization.yaml's resources list. Idempotent — does nothing if the resource is already listed.

func RegisterTenant

func RegisterTenant(tenantName, outputDir, kustomizationPath string) error

RegisterTenant adds a tenant's directory path to a kustomization.yaml resources list. If kustomizationPath is empty, auto-discovers by walking up from outputDir.

func RemoveArgoCDRBACPolicy

func RemoveArgoCDRBACPolicy(existingContent string, tenantName string) (string, error)

RemoveArgoCDRBACPolicy removes a tenant's policy lines from argocd-rbac-cm content. Uses map[string]any for round-trip fidelity to preserve unknown fields.

func RemoveArgoCDRBACPolicyFile

func RemoveArgoCDRBACPolicyFile(rbacCMPath, tenantName string) error

RemoveArgoCDRBACPolicyFile reads an existing argocd-rbac-cm file and removes the tenant's RBAC policy from it. No-op if the file does not exist.

func ResolveKustomizationPath

func ResolveKustomizationPath(outputDir, explicit string) (string, error)

ResolveKustomizationPath resolves the kustomization.yaml path from an explicit path or by auto-discovering it by walking up from outputDir.

func ScaffoldFiles

func ScaffoldFiles(opts Options) map[string][]byte

ScaffoldFiles returns the files to push to a new tenant repository. The returned map is filename -> content (as bytes).

func UnregisterTenant

func UnregisterTenant(tenantName, outputDir, kustomizationPath string) error

UnregisterTenant removes a tenant's directory path from a kustomization.yaml resources list.

Types

type DeleteOptions

type DeleteOptions struct {
	// Name is the tenant name (required).
	Name string
	// OutputDir is the directory containing tenant subdirectories.
	OutputDir string
	// Unregister removes the tenant from kustomization.yaml resources.
	Unregister bool
	// KustomizationPath is the explicit path to kustomization.yaml.
	KustomizationPath string
	// DeleteRepo deletes the tenant's Git repository.
	DeleteRepo bool
	// GitProvider is the Git provider name (github, gitlab, gitea).
	GitProvider string
	// TenantRepo is the tenant repo as owner/repo-name.
	TenantRepo string
	// GitToken is the Git provider API token.
	GitToken string
}

DeleteOptions holds configuration for tenant deletion.

type DeliverPROptions

type DeliverPROptions struct {
	// GitProvider is the git provider name (e.g. "github").
	GitProvider string
	// GitToken is the explicit API token (optional; resolved via ResolveToken if empty).
	GitToken string
	// PlatformRepo is the platform repo as owner/repo-name (optional; auto-detected if empty).
	PlatformRepo string
	// TargetBranch is the PR target branch (optional; uses repo default branch if empty).
	TargetBranch string
	// TenantName is the tenant name.
	TenantName string
	// OutputDir is the directory where tenant manifests were generated.
	OutputDir string
	// Register indicates whether kustomization.yaml was modified and should be included.
	Register bool
	// KustomizationPath is the explicit path to kustomization.yaml (optional; auto-discovers if empty).
	KustomizationPath string
}

DeliverPROptions holds options for PR delivery.

type Options

type Options struct {
	// Name is the tenant name (required).
	Name string
	// Namespaces to create (default: [Name]).
	Namespaces []string
	// ClusterRole to bind to the tenant ServiceAccount (default: "edit").
	ClusterRole string
	// OutputDir is the output directory for platform manifests (default: ".").
	OutputDir string
	// Force overwrites existing tenant directory.
	Force bool
	// TenantType is the tenant type: flux, argocd, or kubectl.
	TenantType Type
	// SyncSource is the Flux source type: oci or git (Flux only).
	SyncSource SyncSource
	// Registry is the OCI registry URL for Flux OCI source.
	Registry string
	// GitProvider is the Git provider name (github, gitlab, gitea).
	GitProvider string
	// TenantRepo is the tenant repo as owner/repo-name.
	TenantRepo string
	// GitToken is the Git provider API token.
	GitToken string
	// RepoVisibility is the repo visibility: Private, Internal, or Public.
	RepoVisibility string
	// Register indicates whether to register the tenant in kustomization.yaml.
	Register bool
	// KustomizationPath is the explicit path to kustomization.yaml.
	KustomizationPath string
	// PlatformRepo is the platform repo as owner/repo-name for PR delivery.
	PlatformRepo string
	// TargetBranch is the PR target branch (empty = repo's default branch).
	TargetBranch string
}

Options holds all configuration for tenant generation.

func (*Options) ResolveDefaults

func (o *Options) ResolveDefaults()

ResolveDefaults fills in default values for unset fields.

func (*Options) Validate

func (o *Options) Validate() error

Validate checks that required fields are set and values are safe.

type SyncSource

type SyncSource string

SyncSource defines the source type for Flux tenants.

const (
	// SyncSourceOCI uses an OCIRepository source for Flux sync.
	SyncSourceOCI SyncSource = "oci"
	// SyncSourceGit uses a GitRepository source for Flux sync.
	SyncSourceGit SyncSource = "git"
)

type Type

type Type string

Type defines the type of tenant (determines which resources are generated).

const (
	// TypeFlux generates RBAC + Flux sync manifests (OCIRepository/GitRepository + Kustomization).
	TypeFlux Type = "flux"
	// TypeArgoCD generates RBAC + ArgoCD manifests (AppProject + Application).
	TypeArgoCD Type = "argocd"
	// TypeKubectl generates RBAC manifests only (no GitOps sync resources).
	TypeKubectl Type = "kubectl"
)

func ValidTypes

func ValidTypes() []Type

ValidTypes returns all valid tenant type values.

func (*Type) Set

func (t *Type) Set(value string) error

Set implements pflag.Value for Type (case-insensitive).

func (*Type) String

func (t *Type) String() string

String returns the string representation of the Type.

func (*Type) Type

func (t *Type) Type() string

Type returns the type name for pflag.

Directories

Path Synopsis
Package gitprovider provides a provider-agnostic interface for Git repository operations, including creating repos, pushing files, and deleting repos.
Package gitprovider provides a provider-agnostic interface for Git repository operations, including creating repos, pushing files, and deleting repos.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL