Skip to content

Latest commit

Β 

History

History
741 lines (583 loc) Β· 26 KB

File metadata and controls

741 lines (583 loc) Β· 26 KB

KubeKey Agent Guide

This is the single entry point for any AI agent (or new contributor) working on the KubeKey v4 codebase. It covers what the project is, how the code actually flows, and the conventions you must follow when changing it.

Read it top to bottom once; afterwards use Β§3 (Code Logic Map) and Β§8 (File-to-Concern Map) as lookup tables.

Further reading:

1. What is KubeKey?

KubeKey v4 is a Go-based task execution framework modeled on Ansible. Its primary use case is installing and managing Kubernetes clusters, but the core engine is generic: it loads playbook projects (YAML), executes tasks across hosts via connectors (SSH/local/Kubernetes/Prometheus), and provides built-in modules (command, copy, template, image, etc.).

Two binaries are produced:

  • kk – CLI tool that runs playbooks locally or inside a Kubernetes pod.
  • kk-controller-manager – Kubernetes operator that watches Playbook CRs and spawns executor pods.

A third build target, capkk, provides the Cluster API infrastructure provider (built with the clusterapi tag).

2. Repository Layout

kubekey/
β”œβ”€β”€ cmd/kk                    # CLI binary entry
β”œβ”€β”€ cmd/controller-manager    # Operator binary entry
β”œβ”€β”€ api/                      # Separate Go module for CRD Go types
β”‚   β”œβ”€β”€ core/v1               # Playbook / Inventory / Config CRDs
β”‚   β”œβ”€β”€ core/v1alpha1         # Task CRD
β”‚   └── project/v1            # Playbook YAML types (play/role/block/...)
β”œβ”€β”€ pkg/                      # Core packages
β”‚   β”œβ”€β”€ executor/             # Playbook/role/block/task execution engine
β”‚   β”œβ”€β”€ project/              # Project loading (builtin/local/git)
β”‚   β”œβ”€β”€ modules/              # Built-in modules
β”‚   β”œβ”€β”€ variable/             # Variable merging and lookup
β”‚   β”œβ”€β”€ connector/            # SSH/local/k8s/prometheus connectors
β”‚   β”œβ”€β”€ converter/            # Block↔Task conversion, template rendering
β”‚   β”œβ”€β”€ manager/              # commandManager/controllerManager/webManager
β”‚   β”œβ”€β”€ controllers/          # Kubernetes reconcilers and webhooks
β”‚   β”œβ”€β”€ proxy/                # Hybrid REST API proxy
β”‚   β”œβ”€β”€ web/                  # HTTP services
β”‚   β”œβ”€β”€ const/                # Constants, scheme, workdir helpers
β”‚   └── utils/                # Small utilities
β”œβ”€β”€ builtin/core/             # Embedded playbooks/roles (requires "builtin" tag)
β”œβ”€β”€ plugins/                  # Optional community playbooks/roles
β”œβ”€β”€ config/                   # Generated CRDs, Helm charts, Kustomize
β”œβ”€β”€ docs/                     # Documentation
β”‚   └── en/framework/         # User-facing framework docs
β”œβ”€β”€ Makefile                  # Build targets, generate, test, lint
β”œβ”€β”€ go.mod                    # Main module
β”œβ”€β”€ go.work                   # Workspace including ./api
└── version/                  # Build-time version injection

3. Code Logic Map

Exact code paths for the most important flows, so you can jump straight to the right function when debugging or adding a feature.

3.1 CLI Startup Flow

kk binary entry:

cmd/kk/kubekey.go:main()
    └── app.NewRootCommand().Execute()

Root command construction:

cmd/kk/app/root.go:NewRootCommand()
    β”œβ”€β”€ options.AddProfilingFlags()      # pprof/gops
    β”œβ”€β”€ options.AddKlogFlags()
    β”œβ”€β”€ options.AddGOPSFlags()
    β”œβ”€β”€ newRunCommand()
    β”œβ”€β”€ newPlaybookCommand()
    β”œβ”€β”€ newVersionCommand()
    β”œβ”€β”€ newWebCommand()
    └── internalCommand...               # built-in commands registered by init()

Built-in commands registration (gated by //go:build builtin):

cmd/kk/app/builtin.go:init()
    └── imports cmd/kk/app/builtin/* packages

cmd/kk/app/builtin/create.go:init()
    └── internalCommand = append(internalCommand, newCreateCommand())

cmd/kk/app/builtin/add.go:init()
cmd/kk/app/builtin/delete.go:init()
cmd/kk/app/builtin/init.go:init()
cmd/kk/app/builtin/precheck.go:init()
cmd/kk/app/builtin/artifact.go:init()
cmd/kk/app/builtin/certs.go:init()

Each built-in command constructs a CommonOptions and calls CommonOptions.Run().

Built-in command flow (example: create cluster):

cmd/kk/app/builtin/create.go:newCreateCommand()
    └── cmd.RunE = func(...)
        β”œβ”€β”€ options.NewCommonOptions()
        β”‚   └── sets up Playbook/Inventory/Config references
        β”œβ”€β”€ options.Complete()
        β”‚   β”œβ”€β”€ resolve inventory/config files
        β”‚   β”œβ”€β”€ apply --set overrides
        β”‚   └── determine workdir
        └── options.Run()
            └── manager.NewCommandManager(playbook, inventory, config)
                └── commandManager.Run()
                    └── executor.NewPlaybookExecutor(...).Exec(ctx)

Arbitrary playbook flow (kk run):

cmd/kk/app/run.go:newRunCommand()
    └── options.KubeKeyRunOptions.Complete()
        β”œβ”€β”€ project.New() for git/local project
        └── build Playbook CR pointing at that project
    └── options.Run() -> CommandManager -> PlaybookExecutor

In-cluster executor (kk playbook):

cmd/kk/app/playbook.go:newPlaybookCommand()
    └── PlaybookOptions.Complete()
        β”œβ”€β”€ read Playbook CR from API server
        └── read Inventory/Config CRs
    └── Run() -> CommandManager -> PlaybookExecutor

3.2 Manager Layer

All three binaries converge on the Manager interface in pkg/manager/manager.go.

Command manager:

pkg/manager/command_manager.go:NewCommandManager()
    └── Run(ctx)
        β”œβ”€β”€ create controller-runtime client for local file storage
        β”œβ”€β”€ if local run and not dry-run: create/update Playbook CR locally
        └── PlaybookExecutor.Exec(ctx)

Controller manager:

cmd/controller-manager/controller_manager.go:main()
    └── app.NewControllerManagerCommand().Execute()
        └── pkg/manager/controller_manager.go:NewControllerManager().Run(ctx)
            β”œβ”€β”€ create controller-runtime manager
            β”œβ”€β”€ register enabled controllers via options.Register()
            └── mgr.Start(ctx)

Controllers register in pkg/controllers/core/register.go:init() and pkg/controllers/infrastructure/register.go:init().

Web manager:

pkg/manager/web_manager.go:NewWebManager().Run(ctx)
    β”œβ”€β”€ create local REST config via pkg/proxy
    β”œβ”€β”€ build go-restful container
    β”œβ”€β”€ pkg/web.NewCoreService()
    β”œβ”€β”€ pkg/web.NewSchemaService()
    β”œβ”€β”€ pkg/web.NewUIService()
    └── http.ListenAndServe()

3.3 Project Loading

Project factory:

pkg/project/project.go:New(ctx, playbook, update)
    β”œβ”€β”€ if playbook address looks like git: newGitProject()
    β”‚   └── go-git clone/pull into workdir
    β”œβ”€β”€ else if BuiltinsProjectAnnotation is set: builtinProjectFunc()
    β”‚   └── builtin/core.BuiltinPlaybook embed.FS
    └── else: newLocalProject()
        └── os.DirFS(path)

Playbook marshaling:

pkg/project/project.go:MarshalPlaybook()
    β”œβ”€β”€ ReadFile(playbook.yaml)
    β”œβ”€β”€ yaml.Unmarshal -> kkprojectv1.Playbook
    β”œβ”€β”€ resolve import_playbook recursively
    β”œβ”€β”€ load vars_files
    β”œβ”€β”€ load roles:
    β”‚   β”œβ”€β”€ read defaults/main.yaml
    β”‚   β”œβ”€β”€ read meta/main.yaml dependencies
    β”‚   └── recursively marshal dependency roles
    β”œβ”€β”€ expand include_tasks
    └── validate playbook/role/block

YAML project types live in api/project/v1/:

  • playbook.go:Playbook – top-level list of Plays.
  • play.go:Play – hosts, gather_facts, vars_files, roles, pre_tasks/tasks/post_tasks.
  • role.go:Role / RoleInfo – dependencies, name, blocks.
  • block.go:Block – nested block/rescue/always or leaf task.
  • base.go:Base – name, connection, vars, environment, run_once, ignore_errors, become.
  • taggable.go:Taggable – tags logic (always/never/all/tagged).
  • conditional.go:When – conditional evaluation.

3.4 Execution Engine

Executor creation:

pkg/executor/playbook_executor.go:NewPlaybookExecutor(client, playbook, variable, logOutput)
    └── returns *playbookExecutor{ option{...}, project }

Playbook execution:

pkg/executor/playbook_executor.go:Exec(ctx)
    β”œβ”€β”€ project.MarshalPlaybook() -> kkprojectv1.Playbook
    β”œβ”€β”€ set Playbook phase Running
    β”œβ”€β”€ for each Play:
    β”‚   β”œβ”€β”€ select hosts from inventory by pattern
    β”‚   β”œβ”€β”€ group hosts by serial batches
    β”‚   β”‚   └── pkg/converter/converter.go:GroupHostBySerial()
    β”‚   β”œβ”€β”€ for each batch:
    β”‚   β”‚   β”œβ”€β”€ gather_facts (if play.gather_facts != false)
    β”‚   β”‚   β”‚   └── setup module on each host
    β”‚   β”‚   β”œβ”€β”€ run pre_tasks
    β”‚   β”‚   β”œβ”€β”€ for each role:
    β”‚   β”‚   β”‚   └── roleExecutor.Exec(ctx)
    β”‚   β”‚   β”œβ”€β”€ run tasks
    β”‚   β”‚   └── run post_tasks
    β”‚   └── update Playbook status
    β”œβ”€β”€ set Playbook phase Succeeded/Failed
    └── store final result

Role execution:

pkg/executor/role_executor.go:Exec(ctx)
    β”œβ”€β”€ merge role defaults into variable system
    β”œβ”€β”€ recursively execute dependency roles
    β”‚   └── dependency role inherits parent role's when/tags/ignore_errors
    └── for each block in role:
        └── blockExecutor.Exec(ctx)
            └── blocks inherit role's when conditions

when defined on a role is merged with parent conditions and passed down to all blocks and tasks within that role.

Block execution:

pkg/executor/block_executor.go:Exec(ctx)
    β”œβ”€β”€ evaluate tags: skip block if tags don't match
    β”œβ”€β”€ merge block's when condition with parent when conditions
    β”œβ”€β”€ if block has nested block/rescue/always:
    β”‚   β”œβ”€β”€ run block tasks
    β”‚   β”œβ”€β”€ on failure: run rescue tasks
    β”‚   └── always: run always tasks
    └── else (leaf task):
        └── taskExecutor.Exec(ctx)
            └── all inherited when conditions are evaluated per host

when conditions are cumulative: a block or task must satisfy its own when expressions and all inherited when expressions from parent blocks and roles.

Task execution:

pkg/executor/task_executor.go:Exec(ctx)
    β”œβ”€β”€ if loop: expand loop items
    β”œβ”€β”€ create/update kkcorev1alpha1.Task CR
    β”œβ”€β”€ for each host in parallel (wait.Group):
    β”‚   β”œβ”€β”€ evaluate per-host when condition
    β”‚   β”œβ”€β”€ create progress bar
    β”‚   β”œβ”€β”€ FindModule(moduleName)
    β”‚   β”œβ”€β”€ moduleExecFunc(ctx, ExecOptions)
    β”‚   β”œβ”€β”€ evaluate failed_when
    β”‚   β”œβ”€β”€ handle ignore_errors
    β”‚   └── store register/result variables
    └── update Task CR status

Module discovery:

pkg/executor/block_executor.go:MarshalBlock()
    β”œβ”€β”€ iterate over UnknownField(s) in kkprojectv1.Block
    └── first unknown key that matches a registered module -> ModuleName

3.5 Variables

Variable structure:

pkg/variable/variable.go:value
    β”œβ”€β”€ Config    kkcorev1.Config
    β”œβ”€β”€ Inventory kkcorev1.Inventory
    β”œβ”€β”€ Hosts     map[string]host
    β”‚   β”œβ”€β”€ RemoteVars  map[string]any   # gather_facts
    β”‚   └── RuntimeVars map[string]any   # set_fact, register
    └── Result    map[string]any

Lookup precedence:

pkg/variable/variable_get.go:GetFunc
    └── resolves in order:
        1. Config vars
        2. Host-specific inventory vars
        3. Group vars (for groups containing host)
        4. Inventory vars
        5. Runtime vars
        6. Remote vars

Merge paths:

pkg/variable/variable_merge.go
    β”œβ”€β”€ MergeRemoteVariable()       # gather_facts -> Hosts[host].RemoteVars
    β”œβ”€β”€ MergeRuntimeVariable()      # set_fact/register -> Hosts[host].RuntimeVars
    β”œβ”€β”€ MergeHostsRuntimeVariable() # cross-host variable injection
    └── MergeResultVariable()       # task result -> Playbook.Status.Result

Persistence:

pkg/variable/source/file_source.go
    └── reads/writes per-host vars to
        <workdir>/runtime/<namespace>/<playbook>/variable/<hostname>.yaml

3.6 Connectors

Factory:

pkg/connector/connector.go:NewConnector(host, vars, logger)
    β”œβ”€β”€ connector.type == "local"      -> localConnector
    β”œβ”€β”€ connector.type == "ssh"        -> sshConnector
    β”œβ”€β”€ connector.type == "kubernetes" -> kubernetesConnector
    β”œβ”€β”€ connector.type == "prometheus" -> prometheusConnector
    └── default:
        β”œβ”€β”€ localhost -> localConnector
        └── otherwise -> sshConnector

SSH connector (pkg/connector/ssh_connector.go): Init() parses auth (password/key); ExecuteCommand() via golang.org/x/crypto/ssh; PutFile() / FetchFile() via sftp.

Local connector (pkg/connector/local_connector.go): ExecuteCommand() via os/exec; PutFile() / FetchFile() operate on the local filesystem.

Fact gathering (pkg/connector/gather_facts.go): local/ssh connectors implement HostInfo(), collecting OS, arch, hostname, IP, memory and CPU facts.

Modules must stay decoupled from the local OS: always go through the Connector interface, never hardcode Linux paths or bash-only syntax.

3.7 Modules

Registry:

pkg/modules/internal/options.go
    β”œβ”€β”€ RegisterModule(fn, names...)
    β”œβ”€β”€ FindModule(name)
    └── ModuleExecFunc signature

Module list (registered in pkg/modules/module.go):

Module Package Key file
add_hostvars pkg/modules/add_hostvars add_hostvars.go
assert pkg/modules/assert assert.go
command/shell pkg/modules/command command.go
copy pkg/modules/copy copy.go
debug pkg/modules/debug debug.go
fetch pkg/modules/fetch fetch.go
gen_cert pkg/modules/gen_cert gen_cert.go
http_get_file pkg/modules/http_get_file http_get_file.go
image pkg/modules/image image.go, image_deprecated.go, repository.go
include_vars pkg/modules/include_vars include_vars.go
prometheus pkg/modules/prometheus prometheus.go
result pkg/modules/result result.go
set_fact pkg/modules/set_fact set_fact.go
setup pkg/modules/setup setup.go
template pkg/modules/template template.go

Representative implementations:

pkg/modules/command/command.go:ModuleCommand(ctx, opts)
    β”œβ”€β”€ render args through template
    β”œβ”€β”€ build command string
    β”œβ”€β”€ opts.Connector.ExecuteCommand(cmd)
    └── return stdout/stderr

pkg/modules/copy/copy.go:ModuleCopy(ctx, opts)
    β”œβ”€β”€ resolve src/content
    β”œβ”€β”€ optionally template content
    β”œβ”€β”€ opts.Connector.PutFile(data, dst, mode)
    └── return result

pkg/modules/template/template.go:ModuleTemplate(ctx, opts)
    β”œβ”€β”€ read src template
    β”œβ”€β”€ render with variables
    β”œβ”€β”€ opts.Connector.PutFile(rendered, dst, mode)
    └── return result

3.8 Templates, when and Tags

Rendering:

pkg/converter/tmpl/template.go:ParseFunc()
    β”œβ”€β”€ if string contains "{{" and "}}":
    β”‚   └── text/template.Execute()
    └── else return original string

Custom functions (pkg/converter/tmpl/functions.go), on top of Sprig:

toYaml / fromYaml / toToml
ipInCIDR / ipFamily / isIP
pow / subtractList
fileExists / unquote / getStringSlice
toLowerByteUnit
mapToNamedStringArgs

when conditions (api/project/v1/conditional.go) are always wrapped as templates and rendered to a boolean-like result. They can be defined at role, block and task level:

  • Role-level when is inherited by all blocks and tasks in that role.
  • Block-level when is merged with parent block/role conditions and inherited by nested blocks and leaf tasks.
  • Task-level when is evaluated per host right before module execution.
  • All inherited conditions must evaluate to true for a task to run.

Tags (api/project/v1/taggable.go):

Tags []string
AlwaysTag = "always"
NeverTag  = "never"
AllTag    = "all"
TaggedTag = "tagged"
IsEnabled(onlyTags, skipTags) bool

Tags are inherited the same way as when: role β†’ block β†’ nested block/task. Use JoinTag() to merge parent tags into child tags. Runtime filtering uses playbook.Spec.Tags (only run matching) and playbook.Spec.SkipTags (skip matching), typically set via CLI --tags and --skip-tags.

Tag Meaning
always Always runs unless explicitly skipped by always in skipTags.
never Never runs unless explicitly included.
all Matches every block except those tagged never.
tagged Matches any block that has at least one tag.

Matching rules for onlyTags:

  • A block with always runs.
  • all or tagged runs everything except never.
  • Otherwise the block runs if any of its tags intersect with onlyTags.
  • Blocks without matching tags are skipped.

Matching rules for skipTags:

  • all skips everything except blocks tagged always (unless always is also in skipTags).
  • Any tag intersection with skipTags skips the block.
  • tagged skips all tagged blocks.

Like when, declare tags at the highest applicable scope; do not repeat the same tag at every nested level (see Β§4.4).

3.9 Kubernetes Controllers

Playbook controller:

pkg/controllers/core/playbook_controller.go:Reconcile()
    β”œβ”€β”€ fetch Playbook CR
    β”œβ”€β”€ if no executor Pod exists:
    β”‚   └── create Pod running "kk playbook --name <name> --namespace <ns>"
    β”œβ”€β”€ watch owned Pods
    └── sync Playbook status from Pod phase/logs

CAPKK controllers live in pkg/controllers/infrastructure/: inventory_controller.go, kkcluster_controller.go, kkmachine_controller.go.

Registration:

pkg/controllers/core/register.go:init()
    β”œβ”€β”€ options.Register(&PlaybookReconciler{})
    └── options.Register(&PlaybookWebhook{})

pkg/controllers/infrastructure/register.go:init()
    └── registers Inventory/KKCluster/KKMachine reconcilers

3.10 REST Proxy / Web

Hybrid REST config:

pkg/proxy/transport.go:RestConfig()
    β”œβ”€β”€ if no k8s cluster: use file-based storage for Task/Inventory/Playbook
    └── if cluster exists: forward non-local resources to API server,
        keep Task local

This lets kk run without a Kubernetes cluster while still using controller-runtime clients.

Web services (pkg/web/service.go):

NewCoreService()       # /api/v1/playbooks, /inventories, /logs
NewSchemaService()     # schema listing and config
NewUIService()         # static SPA UI
NewSwaggerUIService()  # swagger UI
NewAPIService()        # OpenAPI JSON

3.11 Built-in Kubernetes Install Flow

High-level flow of builtin/core/playbooks/create_cluster.yaml:

 1. native/root role on all hosts
 2. hook/pre_install.yaml
 3. load defaults + precheck on all hosts
 4. on localhost:
        generate certs, download binaries/images
 5. on etcd/k8s_cluster/image_registry/nfs:
        run native role
 6. on etcd hosts (when external):
        etcd prepare/install
 7. on image_registry hosts:
        docker + registry
 8. on localhost (when registry configured):
        push images
 9. on k8s_cluster hosts:
        CRI install
        kubernetes pre/init/join
        certs renewal
        custom labels/taints
10. on a random control plane host:
        CNI + storage class
11. hook/post_install.yaml

Default variables are loaded from builtin/core/defaults/ and merged before playbook execution.

4. Universal Conventions

Follow these conventions when producing or modifying code.

4.1 Logging

Choose the appropriate log level.

Level Usage
klog.Info Main business events.
klog.Warning Recoverable abnormal situations.
klog.Error Errors requiring attention.
klog.V(4) Framework execution flow. Examples: project, proxy, variable, connector, web, manager, controllers, executor.
klog.V(5) Extension modules. Examples: module, converter.
klog.V(6) Debug information. May include detailed intermediate values and execution flow.

4.2 Errors

Wrap errors only where they originate.

  • Lower layers should use errors.Wrap (or equivalent) to add context.
  • Upper layers should return the error directly unless adding meaningful business context.
  • Do not repeatedly wrap the same error.

KubeKey uses github.com/cockroachdb/errors with errors.Wrapf / errors.Join.

4.3 Naming

Keep names concise. Prefer meaningful short names. Avoid unnecessary abbreviations and verbose names.

Avoid:

tmpData
managerObject
projectConfiguration

Prefer:

cfg
proj
mgr
conn

4.4 Architecture

Prefer modifying existing code instead of introducing new abstractions.

  • Do not introduce new structs or interfaces unless there is a clear benefit.
  • Keep APIs stable.
  • Minimize public surface.
  • Favor composition over inheritance-like patterns.
  • Do not repeat inherited conditions (e.g. when, tags) at every level; declare them at the highest applicable scope (see Β§3.8).

4.5 Go Conventions

  • Package aliases: kkcorev1, kkcorev1alpha1, kkprojectv1.
  • pkg/const is imported as _const to avoid keyword collision.
  • Options structs have Flags() and Complete() methods.
  • Modules return (stdout, stderr, err) triples.
  • Controllers and built-in commands register via init() gated by build tags.
  • Templates use Go text/template + Sprig + custom functions in pkg/converter/tmpl/.

5. Build & Test

Important Makefile targets:

Target Purpose
make kk Build kk binary with BUILDTAGS=builtin
make build-kk-dev Dev build with branch-based version
make controller-manager Build operator image
make generate Deepcopy, CRDs, RBAC, modules, goimports
make generate-manifests-kubekey Generate CRDs to config/kubekey/crds/
make verify Verify generated artifacts and modules are up to date
make test Run unit/integration tests with envtest
make lint Run golangci-lint

Build tags:

  • builtin – includes embedded playbooks/roles and built-in CLI commands.
  • clusterapi – CAPKK controller-manager image build.

6. Debugging Tips

  • Find where a built-in command is defined: search cmd/kk/app/builtin/*.go for the command name.
  • Find where a module is implemented: search pkg/modules/<name>/<name>.go and confirm registration in pkg/modules/module.go.
  • Trace variable values: start at pkg/variable/variable_get.go and add logging in GetFunc.
  • Trace task execution: add logging in pkg/executor/task_executor.go before FindModule.
  • Test a module locally: look at existing *_test.go files; many use the fake connector from pkg/modules/internal/test.go.
  • Regenerate CRDs: make generate-manifests-kubekey.
  • Build with built-ins: make kk (sets BUILDTAGS=builtin).

7. Git Commit & PR Conventions

Commit Message Format

Follow Conventional Commits:

<type>: <short description>

Common types:

  • feat: – new feature
  • fix: – bug fix
  • refactor: – code refactoring
  • docs: – documentation only
  • test: – tests
  • chore: – build, dependencies, tooling

Examples:

feat: support multiple ssh private keys
fix: preserve proxy configuration during reconnect

Pull Request Description

A PR description should include:

  • What changed and why.
  • How it was implemented (briefly).
  • Testing performed.
  • Risks / breaking changes.

8. Appendix: File-to-Concern Map

Concern File
CLI root cmd/kk/app/root.go
CLI options base cmd/kk/app/options/option.go
Built-in commands cmd/kk/app/builtin/*.go
Controller options cmd/controller-manager/app/options/controller_manager.go
Playbook execution pkg/executor/playbook_executor.go
Role execution pkg/executor/role_executor.go
Block execution pkg/executor/block_executor.go
Task execution pkg/executor/task_executor.go
Project loading pkg/project/project.go
Git project pkg/project/git.go
Local project pkg/project/local.go
Builtin project pkg/project/builtin.go
Variable core pkg/variable/variable.go
Variable get pkg/variable/variable_get.go
Variable merge pkg/variable/variable_merge.go
Variable source pkg/variable/source/file_source.go
Connector factory pkg/connector/connector.go
SSH connector pkg/connector/ssh_connector.go
Local connector pkg/connector/local_connector.go
Kubernetes connector pkg/connector/kubernetes_connector.go
Prometheus connector pkg/connector/prometheus_connector.go
Module registry pkg/modules/module.go
Module internals pkg/modules/internal/options.go
Template functions pkg/converter/tmpl/functions.go
Template rendering pkg/converter/tmpl/template.go
Block↔Task converter pkg/converter/converter.go
Playbook CRD api/core/v1/playbook_types.go
Inventory CRD api/core/v1/inventory_types.go
Config CRD api/core/v1/config_types.go
Task CRD api/core/v1alpha1/task_types.go
Project YAML types api/project/v1/playbook.go, play.go, block.go, role.go, base.go, taggable.go, conditional.go
Playbook controller pkg/controllers/core/playbook_controller.go
Web services pkg/web/service.go
REST proxy pkg/proxy/transport.go
Constants/workdir pkg/const/common.go, pkg/const/workdir.go, pkg/const/scheme.go