doktor

package
v0.3.8 Latest Latest
Warning

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

Go to latest
Published: May 4, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

pkg/doktor

The doktor package turns a project directory into a production-grade Kubernetes deployment — without the developer writing a single pod spec.

It reads what the developer already has (Dockerfile, .env, .git) and produces everything Kubernetes needs: a Katalog, an application ConfigMap, and a bundle of Secrets and ConfigMaps derived from the environment file.

What the developer already has

my-app/
  Dockerfile        ← how to build
  .env              ← config and secrets
  .git/             ← what version to deploy

That is enough. pkg/doktor produces the rest.

What the package produces

Output File How
Orkestra Katalog .orkestra/katalog.yaml Init()buildKatalog()
Application ConfigMap .orkestra/app.yaml Init()buildCR()
Kubernetes Secret .orkestra/bundle/app-secrets.yaml GenerateBundle()
Kubernetes ConfigMap .orkestra/bundle/app-config.yaml GenerateBundle()

Package structure

File Responsibility
detect.go Read the project directory — language, port, git commit, frontend
envfile.go Parse .env, split into secrets and config vars
generate.go Write .orkestra/katalog.yaml and .orkestra/app.yaml
bundle.go Write .orkestra/bundle/app-secrets.yaml and app-config.yaml
docker.go docker build and docker push wrappers
ingress.go Detect ingress controller and Orkestra presence on the cluster

The .env contract

Variables in .env become Kubernetes resources — never baked into the image.

DATABASE_URL=postgres://user:pass@host/db   # → Secret
JWT_SECRET=abc123xyz                         # → Secret

PORT=8080       # ork:cfg → ConfigMap (not a secret)
LOG_LEVEL=info  # ork:cfg → ConfigMap

Variables tagged # ork:cfg on the same line become a ConfigMap. All others become a Secret.

Developer documentation

I want to… Go to
Understand project detection docs/01-detection.md
Understand .env parsing docs/02-envfile.md
Understand Katalog generation docs/03-generation.md
Understand bundle generation docs/04-bundle.md
Understand Docker and cluster operations docs/05-deploy.md

Documentation

Index

Constants

View Source
const (
	BundleFile      = "bundle.yaml"
	AppSecretFile   = "app-secrets.yaml"
	AppConfigFile   = "app-config.yaml"
	ApplicationFile = "app.yaml"

	Orkestra          = "orkestra"
	OrkestraRuntime   = "orkestra-runtime"
	OrkestraNamespace = "orkestra-system"
	OrkestraChartRepo = "https://orkspace.github.io/orkestra"
	OrkestraChartName = "orkestra/orkestra"
)
View Source
const (
	NotificationSecretName = "orkestra-notification"
	NotificationSecretFile = "orkestra-notification-secret.yaml"
)
View Source
const (
	// KindClusterName is the default kind cluster created by `ork deploy --dev`.
	KindClusterName = "orkestra-playground"
)
View Source
const (
	RuntimeKatalogPath = "__runtime_katalog_do_not_edit.yml"
)

Variables

This section is empty.

Functions

func Build

func Build(dir, image string, w io.Writer) error

Build runs docker build -t <image> <dir> and streams output to w.

func BuildNotificationSecret

func BuildNotificationSecret(envMap map[string]string) string

BuildNotificationSecret generates the orkestra-notification Kubernetes Secret YAML. When applied to orkestra-system and referenced by runtime.extraEnvFrom, it injects SMTP/Slack credentials into the Orkestra runtime so pkg/konfig can pick them up as normal env vars.

func ClusterReachable

func ClusterReachable() bool

ClusterReachable reports whether kubectl can reach the cluster configured in the current kubeconfig (KUBECONFIG env, ~/.kube/config, or --kubeconfig flag resolved by root.go). Times out after 5 seconds.

func CurrentContext

func CurrentContext() string

CurrentContext returns the active kubectl context name.

func DetectLicense

func DetectLicense(dir string) string

func EnsureDependencies

func EnsureDependencies() error

func EnsureKindCluster

func EnsureKindCluster(name string) error

EnsureKindCluster creates a kind cluster named `name` if it does not already exist, then switches kubectl to its context. It installs kind via `go install` when kind is not found in PATH or GOBIN.

func FetchRuntimeLogs

func FetchRuntimeLogs() (tail string, err error)

FetchRuntimeLogs saves the last 100 log lines from the Orkestra runtime to /tmp/orkestra/runtime.log. If the control-center deployment exists but has no ready replicas, its logs are also saved to /tmp/orkestra/controlcenter.log. Returns the last 10 lines of the runtime log for inline display.

func GenerateBundle

func GenerateBundle(name, namespace string, secrets, config []EnvVar, outputDir string) error

GenerateBundle writes the app Secret and ConfigMap YAML files into outputDir. The caller is responsible for creating outputDir before calling.

func GetEnvValue

func GetEnvValue(vars []EnvVar, key string) (string, bool)

GetEnvValue returns the value of an ENV var or false if not exists

func GlobalKomposerPath

func GlobalKomposerPath() (string, error)

GlobalKomposerPath returns ~/.orkestra/deploy/komposer.yaml.

func GoInstalled

func GoInstalled() bool

GoInstalled reports whether the Go toolchain is present in PATH. Required when kind needs to be installed via `go install`.

func HasSMTP

func HasSMTP(vars []EnvVar) bool

HasSMTP returns true if any variable starts with "SMTP_".

func HasSlack

func HasSlack(vars []EnvVar) bool

HasSlack returns true if any variable starts with "SLACK_".

func HelmAvailable

func HelmAvailable() bool

HelmAvailable reports whether helm is present in PATH.

func ImageTag

func ImageTag(registry, appName, tag string) string

ImageTag returns the full image reference for a build. tag defaults to the git commit short SHA when empty.

func Init

func Init(info *ProjectInfo, opts GenerateOptions) error

Init generates .orkestra/katalog.yaml and .orkestra/app.yaml, creates the .orkestra/ directory, and updates .gitignore to exclude the bundle directory.

func InstallOrUpgradeOrkestra

func InstallOrUpgradeOrkestra(version, values string, upgrade bool) error

func KatalogChanged

func KatalogChanged(dir string) bool

KatalogChanged returns true when .orkestra/katalog.yaml has uncommitted changes or was modified by the most recent commit. Either condition means the operator should be restarted after the bundle is applied so it picks up the new configuration.

func KubectlAvailable

func KubectlAvailable() bool

KubectlAvailable reports whether kubectl is present in PATH.

func NotificationEnvVars

func NotificationEnvVars(vars []EnvVar) map[string]string

NotificationEnvVars maps developer .env keys to Orkestra konfig env var names. Only keys with non-empty values are included.

func OrkestraInstalled

func OrkestraInstalled() bool

OrkestraInstalled reports whether the Orkestra runtime deployment exists and is available in the given namespace.

func OrkestraInstalledRunning

func OrkestraInstalledRunning() bool

OrkestraInstalled reports whether the Orkestra runtime deployment exists and is available and running in the given namespace.

func Push

func Push(image string, w io.Writer) error

Push runs docker push <image> and streams output to w.

func ReadCRName

func ReadCRName(appYAML string) (string, error)

ReadCRName reads the ConfigMap name from .orkestra/app.yaml. Returns the name (e.g. "my-app-orkestra") so callers don't need to re-derive it.

func RestartOrkestra

func RestartOrkestra() error

RestartOrkestra issues a rollout restart of the runtime deployment and waits up to 3 minutes for it to become available again.

func StateDir

func StateDir() (string, error)

StateDir returns ~/.orkestra/deploy/

Types

type DeployState

type DeployState struct {
	ClusterContext string                   `json:"clusterContext"`
	Projects       map[string]*ProjectState `json:"projects"`
}

DeployState is the contents of ~/.orkestra/deploy/state.json.

func LoadState

func LoadState() (*DeployState, error)

LoadState reads the state file. Returns an empty state if not found.

func (*DeployState) PreviousImage

func (s *DeployState) PreviousImage(appName string) string

PreviousImage returns the image deployed before the last deploy, or "" if none.

func (*DeployState) RecordDeploy

func (s *DeployState) RecordDeploy(appName, namespace, katalogPath, newImage string)

RecordDeploy captures the current image as previous before recording the new one. Call this BEFORE patching the cluster so previousImage is always the live image.

func (*DeployState) Save

func (s *DeployState) Save() error

Save writes the state file atomically.

type EnvVar

type EnvVar struct {
	Key   string
	Value string
	IsCfg bool // true when line carries "# ork:cfg"
}

EnvVar is a single variable parsed from a .env file.

func ParseEnvFile

func ParseEnvFile(path string) ([]EnvVar, error)

ParseEnvFile reads a .env file and returns all non-blank, non-comment lines. Variables tagged with "# ork:cfg" on the same line have IsCfg = true; all others are treated as secrets.

func SplitEnvVars

func SplitEnvVars(vars []EnvVar) (secrets, config []EnvVar)

SplitEnvVars partitions parsed variables into secrets and config vars.

type GenerateOptions

type GenerateOptions struct {
	NoHA       bool   // skip HPA and PDB; single replica
	NoSecure   bool   // skip deletionProtection and protection labels
	Clean      bool   // add cleanupOnShutdown: true to deletionProtection
	Name       string // override app name
	AddIngress bool   // force-include Ingress even when no frontend was detected
	NotifyMe   bool   // add notification block
}

GenerateOptions controls which sections are included in the generated Katalog.

type GitAuthor

type GitAuthor struct {
	Name  string
	Email string
	Raw   string // "Name <email>"
}

func LastCommitAuthor

func LastCommitAuthor() (*GitAuthor, error)

LastCommitAuthor returns "Name <email>" from the most recent Git commit.

type GlobalKomposer

type GlobalKomposer struct {
	APIVersion string          `yaml:"apiVersion"`
	Kind       string          `yaml:"kind"`
	Metadata   KomposerMeta    `yaml:"metadata"`
	Sources    KomposerSources `yaml:"sources"`
}

GlobalKomposer is the structure of ~/.orkestra/deploy/komposer.yaml. It aggregates Katalog paths from all deployed projects on this machine.

func LoadGlobalKomposer

func LoadGlobalKomposer() (*GlobalKomposer, error)

LoadGlobalKomposer reads the global Komposer, returning a fresh one if absent.

func (*GlobalKomposer) DeployedProjects

func (k *GlobalKomposer) DeployedProjects() []string

DeployedProjects returns app names inferred from the Komposer source paths. Paths are expected to contain a .orkestra/ directory segment.

func (*GlobalKomposer) RegisterKatalog

func (k *GlobalKomposer) RegisterKatalog(katalogPath string) bool

RegisterKatalog adds katalogPath to the Komposer sources if not already present. Returns true when the path was newly added.

func (*GlobalKomposer) Save

func (k *GlobalKomposer) Save() error

Save writes the global Komposer file.

type IngressController

type IngressController string

IngressController is the ingress controller detected on the cluster.

const (
	IngressNginx   IngressController = "nginx"
	IngressTraefik IngressController = "traefik"
	IngressNone    IngressController = ""
)

func DetectIngressController

func DetectIngressController() IngressController

DetectIngressController tries to identify which ingress controller is installed on the current cluster. Returns IngressNone when kubectl is not available or when no known controller is found.

type KomposerMeta

type KomposerMeta struct {
	Name        string `yaml:"name"`
	Description string `yaml:"description,omitempty"`
	Version     string `yaml:"version,omitempty"`
	Author      string `yaml:"author,omitempty"`
	License     string `yaml:"license,omitempty"`
}

type KomposerSources

type KomposerSources struct {
	Files []string `yaml:"files,omitempty"`
}

type Language

type Language string

Language represents the primary language detected in the project.

const (
	LangGo      Language = "Go"
	LangNode    Language = "Node.js"
	LangJava    Language = "Java"
	LangPython  Language = "Python"
	LangRuby    Language = "Ruby"
	LangRust    Language = "Rust"
	LangUnknown Language = "Unknown"
)

type ProjectInfo

type ProjectInfo struct {
	Dir           string
	HasDockerfile bool
	GitCommit     string // short SHA, empty when not a git repo
	Language      Language
	LangMarker    string   // the file that triggered language detection
	Port          string   // from PORT in .env, or language default
	EnvVars       []EnvVar // all parsed .env variables
	Secrets       []EnvVar // IsCfg == false
	Config        []EnvVar // IsCfg == true
	HasFrontend   bool
	AppName       string // derived from directory name
	HasSMTP       bool   // if env has smtp vars
	HasSlack      bool   // if env has slack vars
	License       string // project license read from regular license files
}

ProjectInfo holds everything ork doktor discovers about a project directory.

func Detect

func Detect(dir string) (*ProjectInfo, error)

Detect examines dir and returns a ProjectInfo. Missing .env is not an error.

type ProjectState

type ProjectState struct {
	Name          string    `json:"name"`
	Namespace     string    `json:"namespace"`
	CurrentImage  string    `json:"currentImage"`
	PreviousImage string    `json:"previousImage,omitempty"`
	KatalogPath   string    `json:"katalogPath"`
	DeployedAt    time.Time `json:"deployedAt"`
}

ProjectState tracks one deployed project.

type RuntimeStatus

type RuntimeStatus struct {
	Running bool
	Reason  string // set when Running is false
}

RuntimeStatus is the result of CheckRuntimeHealth.

func CheckRuntimeHealth

func CheckRuntimeHealth() RuntimeStatus

CheckRuntimeHealth reports whether the Orkestra runtime deployment is up and has at least one ready replica. Pods in CrashLoopBackOff are treated as not running and their pod name is included in Reason.

Jump to

Keyboard shortcuts

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