Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
556c9bc4b3
|
|||
|
ad921fd14b
|
|||
|
ae1cec2998
|
|||
|
2f6dba296f
|
|||
|
ae049cf2d3
|
|||
|
e00db9e58d
|
|||
|
51f2611e9d
|
|||
|
84686672ea
|
|||
|
e5db02b4f8
|
|||
|
4dfcc61143
|
|||
|
affcf1bca8
|
|||
|
22d3f569df
|
|||
|
8f3539ed34
|
|||
|
a9b0993ffb
|
|||
|
6a341e426c
|
|||
|
85a83e7580
|
|||
|
d62dc0f349
|
|||
|
1574342e92
|
|||
|
2c679229db
|
|||
|
a4d0f2a547
|
|||
|
4b8e544ab8
|
|||
|
9a08882e28
|
|||
|
afb91c66bd
|
|||
|
ead883f714
|
|||
|
ac45011794
|
|||
|
2b244348ca
|
|||
|
de66fef2d6
|
|||
|
6c16c89379
|
|||
|
e515ffbe0c
|
|||
|
978109d3fc
|
|||
|
17a50d776b
|
|||
|
550dcd1f0c
|
|||
|
cbbeaf6d67
|
|||
|
6dffb91626
|
|||
|
c63bf7b814
|
|||
|
7a9af8015e
|
|||
|
d437e6ff36
|
|||
|
93f1b726ce
|
|||
|
c58c5d3eff
|
|||
|
60e8c7f9a8
|
|||
|
272ddf17c2
|
|||
|
b0bf71aa61
|
|||
|
0cb26df68b
|
|||
|
a7c2eb1d9b
|
|||
|
496a192198
|
|||
|
d9e2c485f4
|
|||
|
ed9c97ca32
|
|||
|
31a46ecbbd
|
|||
|
d3426e5d82
|
|||
|
ed38caecec
|
|||
|
f0cc531ada
|
|||
|
b1a1098fbc
|
|||
|
04c52c8158
|
|||
|
1f14c9ac9a
|
|||
|
6c11473999
|
|||
|
ced1916def
|
|||
|
57d4bdfb79
|
|||
|
dd724e0a3c
|
|||
|
ab1dbea329
|
|||
|
9c90f0a477
|
|||
|
aff3df6fcf
|
|||
|
a71fa531f9
|
|||
|
aeb51614cb
|
|||
|
39b3daf57c
|
|||
|
fe65d2debc
|
|||
|
20f32531b7
|
|||
|
856edbd22e
|
|||
|
bf252c51f0
|
|||
|
821ef2f570
|
|||
|
a3211552a5
|
|||
|
0317c6adea
|
|||
|
2f861a9192
|
|||
|
27ce28e2ea
|
|||
|
d71f86a38b
|
|||
|
b02da21aac
|
|||
|
30b26ca5f0
|
|||
|
d4519e862f
|
|||
|
4fc16646eb
|
|||
|
a26a088c69
|
|||
|
71d9821c4c
|
5
.cargo/config.toml
Normal file
5
.cargo/config.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
[build]
|
||||
rustc-wrapper = "/opt/homebrew/bin/sccache"
|
||||
|
||||
[registries.sunbeam]
|
||||
index = "sparse+https://src.sunbeam.pt/api/packages/studio/cargo/"
|
||||
@@ -34,6 +34,17 @@ retries = 2
|
||||
[profile.ci.junit]
|
||||
path = "target/nextest/ci/junit.xml"
|
||||
|
||||
[profile.cover]
|
||||
# Coverage profile — used with cargo llvm-cov nextest
|
||||
fail-fast = false
|
||||
test-threads = "num-cpus"
|
||||
failure-output = "immediate-final"
|
||||
success-output = "never"
|
||||
slow-timeout = { period = "60s", terminate-after = 2 }
|
||||
|
||||
[profile.cover.junit]
|
||||
path = "target/nextest/cover/junit.xml"
|
||||
|
||||
# Postgres tests must run serially (shared database state)
|
||||
[[profile.default.overrides]]
|
||||
filter = "package(wfe-postgres)"
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,4 +3,4 @@ Cargo.lock
|
||||
*.swp
|
||||
*.swo
|
||||
.DS_Store
|
||||
.env
|
||||
.env*
|
||||
|
||||
169
CHANGELOG.md
Normal file
169
CHANGELOG.md
Normal file
@@ -0,0 +1,169 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.8.0] - 2026-04-06
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-kubernetes**: New crate -- Kubernetes executor for running workflow steps as K8s Jobs
|
||||
- Namespace-per-workflow isolation with automatic cleanup
|
||||
- Job manifest builder with env, resources, pull policy, node selector support
|
||||
- Pod log streaming to LogSink with real-time output capture
|
||||
- `##wfe[output key=value]` parsing from Job stdout
|
||||
- Timeout handling with Job cleanup on expiry
|
||||
- `KubernetesServiceProvider`: provisions infrastructure services as K8s Pods + Services with DNS resolution and readiness polling
|
||||
- 100% test coverage on service provider, 91% overall crate coverage
|
||||
- **wfe-core**: `ServiceDefinition`, `ServicePort`, `ReadinessProbe`, `ServiceEndpoint` types for declaring infrastructure services
|
||||
- **wfe-core**: `ServiceProvider` trait for pluggable service provisioning
|
||||
- **wfe-core**: `services` field on `WorkflowDefinition` for declaring required services
|
||||
- **wfe**: Capability-based workflow routing -- hosts check `can_execute()` before accepting workflows
|
||||
- Verifies all step types are registered in the StepRegistry
|
||||
- Verifies ServiceProvider is configured and can provision required services
|
||||
- Re-queues workflows that can't be handled by this host
|
||||
- **wfe**: Service lifecycle in dequeue loop -- provision before execution, teardown after completion/failure
|
||||
- **wfe**: `use_service_provider()` on `WorkflowHostBuilder`
|
||||
- **wfe-containerd**: `ContainerdServiceProvider` for running services via containerd gRPC API on host network
|
||||
- **wfe-yaml**: `services:` block in workflow YAML definitions with readiness probes (exec, tcp, http)
|
||||
- **wfe-yaml**: `kubernetes`/`k8s` step type with lazy client creation
|
||||
|
||||
## [1.7.0] - 2026-04-05
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-deno**: New crate -- Deno/JS/TS bindings for the WFE workflow engine
|
||||
- Full API surface via 23 deno_core ops: host lifecycle, workflow management, fluent builder, step registration, event publishing
|
||||
- Channel-based execution bridge: JS step functions called from tokio executor via mpsc/oneshot channels
|
||||
- High-level JS API classes: `WorkflowHost`, `WorkflowBuilder`, `ExecutionResult`
|
||||
- 52 tests (26 unit + 26 integration), 93% line coverage
|
||||
- **wfe-core**: `WorkflowBuilder.steps` and `last_step` fields now public
|
||||
|
||||
## [1.6.3] - 2026-04-05
|
||||
|
||||
### Fixed
|
||||
|
||||
- **wfe-core**: Propagate `step_name` into execution pointers when advancing to next steps, compensation steps, and parallel branch children
|
||||
- **wfe**: Set `step_name` on initial execution pointer when starting a workflow instance
|
||||
|
||||
## [1.6.2] - 2026-04-05
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-core**: `WorkflowBuilder::add_step_typed()` for adding named, configured steps in parallel branch closures
|
||||
- **wfe-core**: `WorkflowBuilder::wire_outcome()` now public for custom graph wiring
|
||||
|
||||
## [1.6.1] - 2026-04-05
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-core**: `StepBuilder::config()` for attaching arbitrary JSON configuration to individual steps, readable at runtime via `context.step.step_config`
|
||||
|
||||
## [1.6.0] - 2026-04-01
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-server**: Headless workflow server (single binary)
|
||||
- gRPC API with 13 RPCs: workflow CRUD, lifecycle streaming, log streaming, log search
|
||||
- HTTP webhooks: GitHub and Gitea with HMAC-SHA256 verification, configurable triggers
|
||||
- OIDC/JWT authentication with JWKS discovery and asymmetric algorithm allowlist
|
||||
- Static bearer token auth with constant-time comparison
|
||||
- Lifecycle event broadcasting via `WatchLifecycle` server-streaming RPC
|
||||
- Real-time log streaming via `StreamLogs` with follow mode and history replay
|
||||
- Full-text log search via OpenSearch with `SearchLogs` RPC
|
||||
- Layered config: CLI flags > env vars > TOML file
|
||||
- **wfe-server-protos**: gRPC service definitions (tonic 0.14, server + client stubs)
|
||||
- **wfe-core**: `LogSink` trait for real-time step output streaming
|
||||
- **wfe-core**: Lifecycle publisher wired into executor (StepStarted, StepCompleted, Error, Completed, Terminated)
|
||||
- **wfe**: `use_log_sink()` on `WorkflowHostBuilder`
|
||||
- **wfe-yaml**: Shell step streaming mode with `tokio::select!` interleaved stdout/stderr
|
||||
|
||||
### Security
|
||||
|
||||
- JWT algorithm confusion prevention: derive algorithm from JWK, reject symmetric algorithms
|
||||
- Constant-time static token comparison via `subtle` crate
|
||||
- OIDC issuer HTTPS validation to prevent SSRF
|
||||
- Fail-closed on OIDC discovery failure (server won't start with broken auth)
|
||||
- Authenticated generic webhook endpoint
|
||||
- 2MB webhook payload size limit
|
||||
- Config parse errors fail loudly (no silent fallback to open defaults)
|
||||
- Blocked sensitive env var injection (PATH, LD_PRELOAD, etc.) from workflow data
|
||||
- Security regression tests for all critical and high findings
|
||||
|
||||
### Fixed
|
||||
|
||||
- Shell step streaming path now respects `timeout_ms` with `child.kill()` on timeout
|
||||
- LogSink properly threaded from WorkflowHostBuilder through executor to StepExecutionContext
|
||||
- LogStore.with_search() wired in server main.rs for OpenSearch indexing
|
||||
- OpenSearch `index_chunk` returns Err on HTTP failure instead of swallowing it
|
||||
- Webhook publish failures return 500 instead of 200
|
||||
|
||||
## [1.5.0] - 2026-03-29
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-rustlang**: New crate with Rust toolchain step executors
|
||||
- Cargo steps: `cargo-build`, `cargo-test`, `cargo-check`, `cargo-clippy`, `cargo-fmt`, `cargo-doc`, `cargo-publish`
|
||||
- External tool steps with auto-install: `cargo-audit`, `cargo-deny`, `cargo-nextest`, `cargo-llvm-cov`
|
||||
- Rustup steps: `rust-install`, `rustup-toolchain`, `rustup-component`, `rustup-target`
|
||||
- `cargo-doc-mdx`: generates MDX documentation from rustdoc JSON output using the `rustdoc-types` crate
|
||||
- **wfe-yaml**: `rustlang` feature flag enabling all cargo/rustup step types
|
||||
- **wfe-yaml**: Schema fields for Rust steps (`package`, `features`, `toolchain`, `profile`, `output_dir`, etc.)
|
||||
- **wfe-containerd**: Remote daemon support via `WFE_IO_DIR` environment variable
|
||||
- **wfe-containerd**: Image chain ID resolution from content store for proper rootfs snapshots
|
||||
- **wfe-containerd**: Docker-default Linux capabilities for root containers
|
||||
- Lima `wfe-test` VM config (Alpine + containerd + BuildKit, TCP socat proxy)
|
||||
- Containerd integration tests running Rust toolchain in containers
|
||||
|
||||
### Fixed
|
||||
|
||||
- **wfe-containerd**: Empty rootfs — snapshot parent now resolved from image chain ID instead of empty string
|
||||
- **wfe-containerd**: FIFO deadlock with remote daemons — replaced with regular file I/O
|
||||
- **wfe-containerd**: `sh: not found` — use absolute `/bin/sh` path in OCI process spec
|
||||
- **wfe-containerd**: `setgroups: Operation not permitted` — grant capabilities when running as UID 0
|
||||
|
||||
### Changed
|
||||
|
||||
- Lima `wfe-test` VM uses Alpine apk packages instead of GitHub release binaries
|
||||
- Container tests use TCP proxy (`http://127.0.0.1:2500`) instead of Unix socket forwarding
|
||||
- CI pipeline (`workflows.yaml`) updated with `wfe-rustlang` in test, package, and publish steps
|
||||
|
||||
879 tests. 88.8% coverage on wfe-rustlang.
|
||||
|
||||
## [1.4.0] - 2026-03-26
|
||||
|
||||
### Added
|
||||
|
||||
- Type-safe `when:` conditions on workflow steps with compile-time validation
|
||||
- Full boolean combinator set: `all` (AND), `any` (OR), `none` (NOR), `one_of` (XOR), `not` (NOT)
|
||||
- Task file includes with cycle detection
|
||||
- Self-hosting CI pipeline (`workflows.yaml`) demonstrating all features
|
||||
- `readFile()` op for deno runtime
|
||||
- Auto-typed `##wfe[output]` annotations (bool, number conversion)
|
||||
- Multi-workflow YAML files, SubWorkflow step type, typed input/output schemas
|
||||
- HostContext for programmatic child workflow invocation
|
||||
- BuildKit image builder and containerd container runner as standalone crates
|
||||
- gRPC clients generated from official upstream proto files (tonic 0.14)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Pipeline coverage step produces valid JSON, deno reads it with `readFile()`
|
||||
- Host context field added to container executor test contexts
|
||||
- `.outputs.` paths resolved flat for child workflows
|
||||
- Pointer status conversion for Skipped in postgres provider
|
||||
|
||||
629 tests. 87.7% coverage.
|
||||
|
||||
## [1.0.0] - 2026-03-23
|
||||
|
||||
### Added
|
||||
|
||||
- **wfe-core**: Workflow engine with step primitives, executor, fluent builder API
|
||||
- **wfe**: WorkflowHost, registry, sync runner, and purger
|
||||
- **wfe-sqlite**: SQLite persistence provider
|
||||
- **wfe-postgres**: PostgreSQL persistence provider
|
||||
- **wfe-opensearch**: OpenSearch search index provider
|
||||
- **wfe-valkey**: Valkey provider for locks, queues, and lifecycle events
|
||||
- **wfe-yaml**: YAML workflow definitions with shell and deno executors
|
||||
- **wfe-yaml**: Deno JS/TS runtime with sandboxed permissions, HTTP ops, npm support via esm.sh
|
||||
- OpenTelemetry tracing support behind `otel` feature flag
|
||||
- In-memory test support providers
|
||||
29
Cargo.toml
29
Cargo.toml
@@ -1,11 +1,13 @@
|
||||
[workspace]
|
||||
members = ["wfe-core", "wfe-sqlite", "wfe-postgres", "wfe-opensearch", "wfe-valkey", "wfe", "wfe-yaml"]
|
||||
members = ["wfe-core", "wfe-sqlite", "wfe-postgres", "wfe-opensearch", "wfe-valkey", "wfe", "wfe-yaml", "wfe-buildkit", "wfe-containerd", "wfe-containerd-protos", "wfe-buildkit-protos", "wfe-rustlang", "wfe-server-protos", "wfe-server", "wfe-kubernetes", "wfe-deno"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
version = "0.1.0"
|
||||
version = "1.8.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
repository = "https://src.sunbeam.pt/studio/wfe"
|
||||
homepage = "https://src.sunbeam.pt/studio/wfe"
|
||||
|
||||
[workspace.dependencies]
|
||||
# Core
|
||||
@@ -36,22 +38,33 @@ redis = { version = "0.27", features = ["tokio-comp", "connection-manager"] }
|
||||
opensearch = "2"
|
||||
|
||||
# Internal crates
|
||||
wfe-core = { path = "wfe-core" }
|
||||
wfe-sqlite = { path = "wfe-sqlite" }
|
||||
wfe-postgres = { path = "wfe-postgres" }
|
||||
wfe-opensearch = { path = "wfe-opensearch" }
|
||||
wfe-valkey = { path = "wfe-valkey" }
|
||||
wfe-yaml = { path = "wfe-yaml" }
|
||||
wfe-core = { version = "1.8.0", path = "wfe-core", registry = "sunbeam" }
|
||||
wfe-sqlite = { version = "1.8.0", path = "wfe-sqlite", registry = "sunbeam" }
|
||||
wfe-postgres = { version = "1.8.0", path = "wfe-postgres", registry = "sunbeam" }
|
||||
wfe-opensearch = { version = "1.8.0", path = "wfe-opensearch", registry = "sunbeam" }
|
||||
wfe-valkey = { version = "1.8.0", path = "wfe-valkey", registry = "sunbeam" }
|
||||
wfe-yaml = { version = "1.8.0", path = "wfe-yaml", registry = "sunbeam" }
|
||||
wfe-buildkit = { version = "1.8.0", path = "wfe-buildkit", registry = "sunbeam" }
|
||||
wfe-containerd = { version = "1.8.0", path = "wfe-containerd", registry = "sunbeam" }
|
||||
wfe-rustlang = { version = "1.8.0", path = "wfe-rustlang", registry = "sunbeam" }
|
||||
wfe-kubernetes = { version = "1.8.0", path = "wfe-kubernetes", registry = "sunbeam" }
|
||||
|
||||
# YAML
|
||||
serde_yaml = "0.9"
|
||||
yaml-merge-keys = { version = "0.8", features = ["serde_yaml"] }
|
||||
regex = "1"
|
||||
|
||||
# Deno runtime
|
||||
deno_core = "0.394"
|
||||
|
||||
deno_error = "0.7"
|
||||
url = "2"
|
||||
|
||||
# Kubernetes
|
||||
kube = { version = "3.1", features = ["runtime", "client", "ws"] }
|
||||
k8s-openapi = { version = "0.27", features = ["latest"] }
|
||||
futures = "0.3"
|
||||
|
||||
# Dev/Test
|
||||
pretty_assertions = "1"
|
||||
rstest = "0.23"
|
||||
|
||||
90
README.md
90
README.md
@@ -1,20 +1,24 @@
|
||||
# WFE
|
||||
|
||||
A persistent, embeddable workflow engine for Rust. Trait-based, pluggable, built for real infrastructure.
|
||||
|
||||
> Rust port of [workflow-core](https://github.com/danielgerlag/workflow-core), rebuilt from scratch with async/await, pluggable persistence, and a YAML frontend with shell and Deno executors.
|
||||
A persistent, embeddable workflow engine for Rust. Trait-based, pluggable, built for large, highly complex build, test, deployment, and release pipelines of the highest levels of complexity.
|
||||
|
||||
---
|
||||
|
||||
## What is WFE?
|
||||
|
||||
WFE is a workflow engine you embed directly into your Rust application. Define workflows as code using a fluent builder API, or as YAML files with shell and JavaScript steps. Workflows persist across restarts, support event-driven pausing, parallel execution, saga compensation, and distributed locking.
|
||||
WFE is a technical love letter from a former [VMware](https://www.vmware.com) and [Pivotal](https://pivotal.io) engineer (@siennathesane). Its internal workflow architecture is based on the amazing [workflow-core](https://github.com/danielgerlag/workflow-core) library by Daniel Gerlag, and the YAML structure and support is based on [Concourse CI](https://concourse-ci.org). WFE is a pluggable, extendable library that can be used to design embedded business workflows, CLI applications, and CI/CD pipelines. It is designed to be embedded into your application, and can scale open-ended with pluggable architectures. You can deploy Cloud Foundry, Kubernetes, or even bootstrap a public cloud with WFE.
|
||||
|
||||
Built for:
|
||||
You can define workflows as code using a fluent builder API, or as YAML files with shell and JavaScript steps. Workflows persist across restarts, support event-driven pausing, parallel execution, saga compensation, and distributed locking. It also comes with native support for containerd and buildkitd embedded into the application.
|
||||
|
||||
- **Persistent workflows** — steps survive process restarts. Pick up where you left off.
|
||||
- **Embeddable CLIs** — drop it into a binary, no external orchestrator required.
|
||||
- **Portable CI pipelines** — YAML workflows with shell and Deno steps, variable interpolation, structured outputs.
|
||||
The only thing not included is a server and a web UI (open to contributions that have been agreed upon and discussed ahead of time).
|
||||
|
||||
## Why?
|
||||
|
||||
Every CI/CD system [I've](https://src.sunbeam.pt/siennathesane) ever used has been either lovely or terrible. I wanted something that was lovely, but also flexible enough to be used in a variety of contexts. The list of CI systems I've used over the years has been extensive, and they all have their _thing_ that makes them stand out in their own ways. I wanted something that could meet every single requirement I have: a distributed workflow engine that can be embedded into any application, has pluggable executors, a statically-verifiable workflow definition language, a simple, easy to use API, YAML 1.1 merge anchors, YAML 1.2 support, multi-file workflows, can be used as a library, can be used as a CLI, and can be used to write servers.
|
||||
|
||||
With that, I wanted the user experience to be essentially identical for embedded application developers, systems engineers, and CI/CD engineers. Whether you write your workflows in code, YAML, or you have written a web server endpoint that accepts gRPC workflow definitions and you're relying on this library as a hosted service, it should feel like the same piece of software in every context.
|
||||
|
||||
Hell, I'm so dedicated to this being the most useful, most pragmatic, most embeddable workflow engine library ever that I'm willing to accept a C ABI contribution to make it embeddable in any language.
|
||||
|
||||
---
|
||||
|
||||
@@ -245,6 +249,76 @@ SQLite tests use temporary files and run everywhere.
|
||||
|
||||
---
|
||||
|
||||
## Self-hosting CI pipeline
|
||||
|
||||
WFE includes a self-hosting CI pipeline defined in `workflows.yaml` at the repository root. The pipeline uses WFE's own YAML workflow engine to build, test, and publish WFE itself.
|
||||
|
||||
### Pipeline architecture
|
||||
|
||||
```
|
||||
ci (orchestrator)
|
||||
|
|
||||
+-------------------+--------------------+
|
||||
| | |
|
||||
preflight lint test (fan-out)
|
||||
(tool check) (fmt + clippy) |
|
||||
+----------+----------+
|
||||
| | |
|
||||
test-unit test-integration test-containers
|
||||
| (docker compose) (lima VM)
|
||||
| | |
|
||||
+----------+----------+
|
||||
|
|
||||
+---------+---------+
|
||||
| | |
|
||||
cover package tag
|
||||
| | |
|
||||
+---------+---------+
|
||||
|
|
||||
+---------+---------+
|
||||
| |
|
||||
publish release
|
||||
(crates.io) (git tags + notes)
|
||||
```
|
||||
|
||||
### Running the pipeline
|
||||
|
||||
```sh
|
||||
# Default — uses current directory as workspace
|
||||
cargo run --example run_pipeline -p wfe -- workflows.yaml
|
||||
|
||||
# With explicit configuration
|
||||
WFE_CONFIG='{"workspace_dir":"/path/to/wfe","registry":"sunbeam","git_remote":"origin","coverage_threshold":85}' \
|
||||
cargo run --example run_pipeline -p wfe -- workflows.yaml
|
||||
```
|
||||
|
||||
### WFE features demonstrated
|
||||
|
||||
The pipeline exercises every major WFE feature:
|
||||
|
||||
- **Workflow composition** — the `ci` orchestrator invokes child workflows (`lint`, `test`, `cover`, `package`, `tag`, `publish`, `release`) using the `workflow` step type.
|
||||
- **Shell executor** — most steps run bash commands with configurable timeouts.
|
||||
- **Deno executor** — the `cover` workflow uses a Deno step to parse coverage JSON; the `release` workflow uses Deno to generate release notes.
|
||||
- **YAML anchors/templates** — `_templates` defines `shell_defaults` and `long_running` anchors, reused across steps via `<<: *shell_defaults`.
|
||||
- **Structured outputs** — steps emit `##wfe[output key=value]` markers to pass data between steps and workflows.
|
||||
- **Variable interpolation** — `((workspace_dir))` syntax passes inputs through workflow composition.
|
||||
- **Error handling** — `on_failure` handlers, `error_behavior` with retry policies, and `ensure` blocks for cleanup (e.g., `docker-down`, `lima-down`).
|
||||
|
||||
### Preflight tool check
|
||||
|
||||
The `preflight` workflow runs first and checks for all required tools: `cargo`, `cargo-nextest`, `cargo-llvm-cov`, `docker`, `limactl`, `buildctl`, and `git`. Essential tools (cargo, nextest, git) cause a hard failure if missing. Optional tools (docker, lima, buildctl, llvm-cov) are reported but do not block the pipeline.
|
||||
|
||||
### Graceful infrastructure skipping
|
||||
|
||||
Integration and container tests handle missing infrastructure without failing:
|
||||
|
||||
- **test-integration**: The `docker-up` step checks if Docker is available. If `docker info` fails, it sets `docker_started=false` and exits cleanly. Subsequent steps (`postgres-tests`, `valkey-tests`, `opensearch-tests`) check this flag and skip if Docker is not running.
|
||||
- **test-containers**: The `lima-up` step checks if `limactl` is installed. If missing, it sets `lima_started=false` and exits cleanly. The `buildkit-tests` and `containerd-tests` steps check this flag and skip accordingly.
|
||||
|
||||
This means the pipeline runs successfully on any machine with the essential Rust toolchain, reporting which optional tests were skipped rather than failing outright.
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
141
test/lima/wfe-test.yaml
Normal file
141
test/lima/wfe-test.yaml
Normal file
@@ -0,0 +1,141 @@
|
||||
# WFE Test VM — Alpine + containerd + BuildKit
|
||||
#
|
||||
# Lightweight VM for running wfe-buildkit and wfe-containerd integration tests.
|
||||
# Provides system-level containerd and BuildKit daemons with Unix sockets
|
||||
# forwarded to the host.
|
||||
#
|
||||
# Usage:
|
||||
# limactl create --name wfe-test ./test/lima/wfe-test.yaml
|
||||
# limactl start wfe-test
|
||||
#
|
||||
# Sockets (on host after start):
|
||||
# BuildKit: unix://$HOME/.lima/wfe-test/buildkitd.sock
|
||||
# containerd: unix://$HOME/.lima/wfe-test/containerd.sock
|
||||
#
|
||||
# Run tests:
|
||||
# WFE_BUILDKIT_ADDR="unix://$HOME/.lima/wfe-test/buildkitd.sock" \
|
||||
# WFE_CONTAINERD_ADDR="unix://$HOME/.lima/wfe-test/containerd.sock" \
|
||||
# cargo test -p wfe-buildkit -p wfe-containerd --test integration
|
||||
# cargo test -p wfe-yaml --features rustlang,containerd --test rustlang_containerd -- --ignored
|
||||
#
|
||||
# Teardown:
|
||||
# limactl stop wfe-test
|
||||
# limactl delete wfe-test
|
||||
|
||||
message: |
|
||||
WFE integration test VM is ready.
|
||||
|
||||
containerd: http://127.0.0.1:2500 (TCP proxy, use for gRPC)
|
||||
BuildKit: http://127.0.0.1:2501 (TCP proxy, use for gRPC)
|
||||
|
||||
Run tests:
|
||||
WFE_CONTAINERD_ADDR="http://127.0.0.1:2500" \
|
||||
WFE_BUILDKIT_ADDR="http://127.0.0.1:2501" \
|
||||
cargo test -p wfe-yaml --features rustlang,containerd --test rustlang_containerd -- --ignored
|
||||
|
||||
minimumLimaVersion: "2.0.0"
|
||||
|
||||
vmType: vz
|
||||
mountType: virtiofs
|
||||
cpus: 2
|
||||
memory: 4GiB
|
||||
disk: 20GiB
|
||||
|
||||
images:
|
||||
- location: "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/nocloud_alpine-3.21.6-aarch64-uefi-cloudinit-r0.qcow2"
|
||||
arch: "aarch64"
|
||||
- location: "https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/nocloud_alpine-3.21.6-x86_64-uefi-cloudinit-r0.qcow2"
|
||||
arch: "x86_64"
|
||||
|
||||
mounts:
|
||||
# Share /tmp so the containerd shim can access FIFOs created by the host-side executor
|
||||
- location: /tmp/wfe-io
|
||||
mountPoint: /tmp/wfe-io
|
||||
writable: true
|
||||
|
||||
containerd:
|
||||
system: false
|
||||
user: false
|
||||
|
||||
provision:
|
||||
# 1. Base packages + containerd + buildkit from Alpine repos (musl-compatible)
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
apk update
|
||||
apk add --no-cache \
|
||||
curl bash coreutils findutils grep tar gzip pigz \
|
||||
containerd containerd-openrc \
|
||||
runc \
|
||||
buildkit buildkit-openrc \
|
||||
nerdctl
|
||||
|
||||
# 2. Start containerd
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
rc-update add containerd default 2>/dev/null || true
|
||||
rc-service containerd start 2>/dev/null || true
|
||||
# Wait for socket
|
||||
for i in $(seq 1 15); do
|
||||
[ -S /run/containerd/containerd.sock ] && break
|
||||
sleep 1
|
||||
done
|
||||
chmod 666 /run/containerd/containerd.sock 2>/dev/null || true
|
||||
|
||||
# 3. Start BuildKit (Alpine package names the service "buildkitd")
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
rc-update add buildkitd default 2>/dev/null || true
|
||||
rc-service buildkitd start 2>/dev/null || true
|
||||
|
||||
# 4. Fix socket permissions + TCP proxy for gRPC access (persists across reboots)
|
||||
- mode: system
|
||||
script: |
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
apk add --no-cache socat
|
||||
mkdir -p /etc/local.d
|
||||
cat > /etc/local.d/fix-sockets.start << 'EOF'
|
||||
#!/bin/sh
|
||||
# Wait for daemons
|
||||
for i in $(seq 1 30); do
|
||||
[ -S /run/buildkit/buildkitd.sock ] && break
|
||||
sleep 1
|
||||
done
|
||||
# Fix permissions for Lima socket forwarding
|
||||
chmod 755 /run/buildkit /run/containerd 2>/dev/null
|
||||
chmod 666 /run/buildkit/buildkitd.sock /run/containerd/containerd.sock 2>/dev/null
|
||||
# TCP proxy for gRPC (Lima socket forwarding breaks HTTP/2)
|
||||
socat TCP4-LISTEN:2500,fork,reuseaddr UNIX-CONNECT:/run/containerd/containerd.sock &
|
||||
socat TCP4-LISTEN:2501,fork,reuseaddr UNIX-CONNECT:/run/buildkit/buildkitd.sock &
|
||||
EOF
|
||||
chmod +x /etc/local.d/fix-sockets.start
|
||||
rc-update add local default 2>/dev/null || true
|
||||
/etc/local.d/fix-sockets.start
|
||||
|
||||
probes:
|
||||
- script: |
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
sudo test -S /run/containerd/containerd.sock
|
||||
sudo chmod 755 /run/containerd 2>/dev/null
|
||||
sudo chmod 666 /run/containerd/containerd.sock 2>/dev/null
|
||||
hint: "Waiting for containerd socket"
|
||||
- script: |
|
||||
#!/bin/sh
|
||||
set -eux
|
||||
sudo test -S /run/buildkit/buildkitd.sock
|
||||
sudo chmod 755 /run/buildkit 2>/dev/null
|
||||
sudo chmod 666 /run/buildkit/buildkitd.sock 2>/dev/null
|
||||
hint: "Waiting for BuildKit socket"
|
||||
|
||||
portForwards:
|
||||
- guestSocket: "/run/buildkit/buildkitd.sock"
|
||||
hostSocket: "{{.Dir}}/buildkitd.sock"
|
||||
- guestSocket: "/run/containerd/containerd.sock"
|
||||
hostSocket: "{{.Dir}}/containerd.sock"
|
||||
19
wfe-buildkit-protos/Cargo.toml
Normal file
19
wfe-buildkit-protos/Cargo.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "wfe-buildkit-protos"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "Generated gRPC stubs for the full BuildKit API"
|
||||
|
||||
[dependencies]
|
||||
tonic = "0.14"
|
||||
tonic-prost = "0.14"
|
||||
prost = "0.14"
|
||||
prost-types = "0.14"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.14"
|
||||
tonic-prost-build = "0.14"
|
||||
prost-build = "0.14"
|
||||
56
wfe-buildkit-protos/build.rs
Normal file
56
wfe-buildkit-protos/build.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Use Go-style import paths so protoc sees each file only once
|
||||
let proto_dir = PathBuf::from("proto");
|
||||
let go_prefix = "github.com/moby/buildkit";
|
||||
|
||||
let proto_files: Vec<PathBuf> = vec![
|
||||
// Core control service (Solve, Status, ListWorkers, etc.)
|
||||
"api/services/control/control.proto",
|
||||
// Types
|
||||
"api/types/worker.proto",
|
||||
// Solver / LLB definitions
|
||||
"solver/pb/ops.proto",
|
||||
// Source policy
|
||||
"sourcepolicy/pb/policy.proto",
|
||||
// Session protocols
|
||||
"session/auth/auth.proto",
|
||||
"session/filesync/filesync.proto",
|
||||
"session/secrets/secrets.proto",
|
||||
"session/sshforward/ssh.proto",
|
||||
"session/upload/upload.proto",
|
||||
"session/exporter/exporter.proto",
|
||||
// Utilities
|
||||
"util/apicaps/pb/caps.proto",
|
||||
"util/stack/stack.proto",
|
||||
]
|
||||
.into_iter()
|
||||
.map(|p| proto_dir.join(go_prefix).join(p))
|
||||
.collect();
|
||||
|
||||
println!(
|
||||
"cargo:warning=Compiling {} buildkit proto files",
|
||||
proto_files.len()
|
||||
);
|
||||
|
||||
let mut prost_config = prost_build::Config::new();
|
||||
prost_config.include_file("mod.rs");
|
||||
|
||||
tonic_prost_build::configure()
|
||||
.build_server(false)
|
||||
.compile_with_config(
|
||||
prost_config,
|
||||
&proto_files,
|
||||
// Include paths for import resolution:
|
||||
// 1. The vendor dir inside buildkit (for Go-style github.com/... imports)
|
||||
// 2. The buildkit root itself (for relative imports)
|
||||
// 3. Our proto/ dir (for google/rpc/status.proto)
|
||||
&[
|
||||
// proto/ has symlinks that resolve Go-style github.com/... imports
|
||||
PathBuf::from("proto"),
|
||||
],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.runhcs.v1;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options";
|
||||
|
||||
// Options are the set of customizations that can be passed at Create time.
|
||||
message Options {
|
||||
// Enable debug tracing (sets the logrus log level to debug). This may be deprecated in the future, prefer
|
||||
// log_level as this will override debug if both of them are set.
|
||||
bool debug = 1;
|
||||
|
||||
enum DebugType {
|
||||
NPIPE = 0;
|
||||
FILE = 1;
|
||||
ETW = 2;
|
||||
}
|
||||
|
||||
// debug tracing output type
|
||||
DebugType debug_type = 2;
|
||||
|
||||
// registry key root for storage of the runhcs container state
|
||||
string registry_root = 3;
|
||||
|
||||
// sandbox_image is the image to use for the sandbox that matches the
|
||||
// sandbox_platform.
|
||||
string sandbox_image = 4;
|
||||
|
||||
// sandbox_platform is a CRI setting that specifies the platform
|
||||
// architecture for all sandbox's in this runtime. Values are
|
||||
// 'windows/amd64' and 'linux/amd64'.
|
||||
string sandbox_platform = 5;
|
||||
|
||||
enum SandboxIsolation {
|
||||
PROCESS = 0;
|
||||
HYPERVISOR = 1;
|
||||
}
|
||||
|
||||
// sandbox_isolation is a CRI setting that specifies the isolation level of
|
||||
// the sandbox. For Windows runtime PROCESS and HYPERVISOR are valid. For
|
||||
// LCOW only HYPERVISOR is valid and default if omitted.
|
||||
SandboxIsolation sandbox_isolation = 6;
|
||||
|
||||
// boot_files_root_path is the path to the directory containing the LCOW
|
||||
// kernel and root FS files.
|
||||
string boot_files_root_path = 7;
|
||||
|
||||
// vm_processor_count is the default number of processors to create for the
|
||||
// hypervisor isolated utility vm.
|
||||
//
|
||||
// The platform default if omitted is 2, unless the host only has a single
|
||||
// core in which case it is 1.
|
||||
int32 vm_processor_count = 8;
|
||||
|
||||
// vm_memory_size_in_mb is the default amount of memory to assign to the
|
||||
// hypervisor isolated utility vm.
|
||||
//
|
||||
// The platform default is 1024MB if omitted.
|
||||
int32 vm_memory_size_in_mb = 9;
|
||||
|
||||
// GPUVHDPath is the path to the gpu vhd to add to the uvm
|
||||
// when a container requests a gpu
|
||||
string GPUVHDPath = 10;
|
||||
|
||||
// scale_cpu_limits_to_sandbox indicates that container CPU limits should
|
||||
// be adjusted to account for the difference in number of cores between the
|
||||
// host and UVM.
|
||||
bool scale_cpu_limits_to_sandbox = 11;
|
||||
|
||||
// default_container_scratch_size_in_gb is the default scratch size (sandbox.vhdx)
|
||||
// to be used for containers. Every container will get a sandbox of `size_in_gb` assigned
|
||||
// instead of the default of 20GB.
|
||||
int32 default_container_scratch_size_in_gb = 12;
|
||||
|
||||
// default_vm_scratch_size_in_gb is the default scratch size (sandbox.vhdx)
|
||||
// to be used for the UVM. This only applies to WCOW as LCOW doesn't mount a scratch
|
||||
// specifically for the UVM.
|
||||
int32 default_vm_scratch_size_in_gb = 13;
|
||||
|
||||
// share_scratch specifies if we'd like to reuse scratch space between multiple containers.
|
||||
// This currently only affects LCOW. The sandbox containers scratch space is re-used for all
|
||||
// subsequent containers launched in the pod.
|
||||
bool share_scratch = 14;
|
||||
|
||||
// NCProxyAddr is the address of the network configuration proxy service. If omitted
|
||||
// the network is setup locally.
|
||||
string NCProxyAddr = 15;
|
||||
|
||||
// log_level specifies the logrus log level for the shim. Supported values are a string representation of the
|
||||
// logrus log levels: "trace", "debug", "info", "warn", "error", "fatal", "panic". This setting will override
|
||||
// the `debug` field if both are specified, unless the level specified is also "debug", as these are equivalent.
|
||||
string log_level = 16;
|
||||
|
||||
// io_retry_timeout_in_sec is the timeout in seconds for how long to try and reconnect to an upstream IO provider if a connection is lost.
|
||||
// The typical example is if Containerd has restarted but is expected to come back online. A 0 for this field is interpreted as an infinite
|
||||
// timeout.
|
||||
int32 io_retry_timeout_in_sec = 17;
|
||||
|
||||
// default_container_annotations specifies a set of annotations that should be set for every workload container
|
||||
map<string, string> default_container_annotations = 18;
|
||||
|
||||
// no_inherit_host_timezone specifies to skip inheriting the hosts time zone for WCOW UVMs and instead default to
|
||||
// UTC.
|
||||
bool no_inherit_host_timezone = 19;
|
||||
|
||||
// scrub_logs enables removing environment variables and other potentially sensitive information from logs
|
||||
bool scrub_logs = 20;
|
||||
}
|
||||
|
||||
// ProcessDetails contains additional information about a process. This is the additional
|
||||
// info returned in the Pids query.
|
||||
message ProcessDetails {
|
||||
string image_name = 1;
|
||||
google.protobuf.Timestamp created_at = 2;
|
||||
uint64 kernel_time_100_ns = 3;
|
||||
uint64 memory_commit_bytes = 4;
|
||||
uint64 memory_working_set_private_bytes = 5;
|
||||
uint64 memory_working_set_shared_bytes = 6;
|
||||
uint32 process_id = 7;
|
||||
uint64 user_time_100_ns = 8;
|
||||
string exec_id = 9;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package io.containerd.cgroups.v1;
|
||||
|
||||
option go_package = "github.com/containerd/cgroups/cgroup1/stats";
|
||||
|
||||
message Metrics {
|
||||
repeated HugetlbStat hugetlb = 1;
|
||||
PidsStat pids = 2;
|
||||
CPUStat cpu = 3;
|
||||
MemoryStat memory = 4;
|
||||
BlkIOStat blkio = 5;
|
||||
RdmaStat rdma = 6;
|
||||
repeated NetworkStat network = 7;
|
||||
CgroupStats cgroup_stats = 8;
|
||||
MemoryOomControl memory_oom_control = 9;
|
||||
}
|
||||
|
||||
message HugetlbStat {
|
||||
uint64 usage = 1;
|
||||
uint64 max = 2;
|
||||
uint64 failcnt = 3;
|
||||
string pagesize = 4;
|
||||
}
|
||||
|
||||
message PidsStat {
|
||||
uint64 current = 1;
|
||||
uint64 limit = 2;
|
||||
}
|
||||
|
||||
message CPUStat {
|
||||
CPUUsage usage = 1;
|
||||
Throttle throttling = 2;
|
||||
}
|
||||
|
||||
message CPUUsage {
|
||||
// values in nanoseconds
|
||||
uint64 total = 1;
|
||||
uint64 kernel = 2;
|
||||
uint64 user = 3;
|
||||
repeated uint64 per_cpu = 4;
|
||||
|
||||
}
|
||||
|
||||
message Throttle {
|
||||
uint64 periods = 1;
|
||||
uint64 throttled_periods = 2;
|
||||
uint64 throttled_time = 3;
|
||||
}
|
||||
|
||||
message MemoryStat {
|
||||
uint64 cache = 1;
|
||||
uint64 rss = 2;
|
||||
uint64 rss_huge = 3;
|
||||
uint64 mapped_file = 4;
|
||||
uint64 dirty = 5;
|
||||
uint64 writeback = 6;
|
||||
uint64 pg_pg_in = 7;
|
||||
uint64 pg_pg_out = 8;
|
||||
uint64 pg_fault = 9;
|
||||
uint64 pg_maj_fault = 10;
|
||||
uint64 inactive_anon = 11;
|
||||
uint64 active_anon = 12;
|
||||
uint64 inactive_file = 13;
|
||||
uint64 active_file = 14;
|
||||
uint64 unevictable = 15;
|
||||
uint64 hierarchical_memory_limit = 16;
|
||||
uint64 hierarchical_swap_limit = 17;
|
||||
uint64 total_cache = 18;
|
||||
uint64 total_rss = 19;
|
||||
uint64 total_rss_huge = 20;
|
||||
uint64 total_mapped_file = 21;
|
||||
uint64 total_dirty = 22;
|
||||
uint64 total_writeback = 23;
|
||||
uint64 total_pg_pg_in = 24;
|
||||
uint64 total_pg_pg_out = 25;
|
||||
uint64 total_pg_fault = 26;
|
||||
uint64 total_pg_maj_fault = 27;
|
||||
uint64 total_inactive_anon = 28;
|
||||
uint64 total_active_anon = 29;
|
||||
uint64 total_inactive_file = 30;
|
||||
uint64 total_active_file = 31;
|
||||
uint64 total_unevictable = 32;
|
||||
MemoryEntry usage = 33;
|
||||
MemoryEntry swap = 34;
|
||||
MemoryEntry kernel = 35;
|
||||
MemoryEntry kernel_tcp = 36;
|
||||
|
||||
}
|
||||
|
||||
message MemoryEntry {
|
||||
uint64 limit = 1;
|
||||
uint64 usage = 2;
|
||||
uint64 max = 3;
|
||||
uint64 failcnt = 4;
|
||||
}
|
||||
|
||||
message MemoryOomControl {
|
||||
uint64 oom_kill_disable = 1;
|
||||
uint64 under_oom = 2;
|
||||
uint64 oom_kill = 3;
|
||||
}
|
||||
|
||||
message BlkIOStat {
|
||||
repeated BlkIOEntry io_service_bytes_recursive = 1;
|
||||
repeated BlkIOEntry io_serviced_recursive = 2;
|
||||
repeated BlkIOEntry io_queued_recursive = 3;
|
||||
repeated BlkIOEntry io_service_time_recursive = 4;
|
||||
repeated BlkIOEntry io_wait_time_recursive = 5;
|
||||
repeated BlkIOEntry io_merged_recursive = 6;
|
||||
repeated BlkIOEntry io_time_recursive = 7;
|
||||
repeated BlkIOEntry sectors_recursive = 8;
|
||||
}
|
||||
|
||||
message BlkIOEntry {
|
||||
string op = 1;
|
||||
string device = 2;
|
||||
uint64 major = 3;
|
||||
uint64 minor = 4;
|
||||
uint64 value = 5;
|
||||
}
|
||||
|
||||
message RdmaStat {
|
||||
repeated RdmaEntry current = 1;
|
||||
repeated RdmaEntry limit = 2;
|
||||
}
|
||||
|
||||
message RdmaEntry {
|
||||
string device = 1;
|
||||
uint32 hca_handles = 2;
|
||||
uint32 hca_objects = 3;
|
||||
}
|
||||
|
||||
message NetworkStat {
|
||||
string name = 1;
|
||||
uint64 rx_bytes = 2;
|
||||
uint64 rx_packets = 3;
|
||||
uint64 rx_errors = 4;
|
||||
uint64 rx_dropped = 5;
|
||||
uint64 tx_bytes = 6;
|
||||
uint64 tx_packets = 7;
|
||||
uint64 tx_errors = 8;
|
||||
uint64 tx_dropped = 9;
|
||||
}
|
||||
|
||||
// CgroupStats exports per-cgroup statistics.
|
||||
message CgroupStats {
|
||||
// number of tasks sleeping
|
||||
uint64 nr_sleeping = 1;
|
||||
// number of tasks running
|
||||
uint64 nr_running = 2;
|
||||
// number of tasks in stopped state
|
||||
uint64 nr_stopped = 3;
|
||||
// number of tasks in uninterruptible state
|
||||
uint64 nr_uninterruptible = 4;
|
||||
// number of tasks waiting on IO
|
||||
uint64 nr_io_wait = 5;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message ContainerCreate {
|
||||
string id = 1;
|
||||
string image = 2;
|
||||
message Runtime {
|
||||
string name = 1;
|
||||
google.protobuf.Any options = 2;
|
||||
}
|
||||
Runtime runtime = 3;
|
||||
}
|
||||
|
||||
message ContainerUpdate {
|
||||
string id = 1;
|
||||
string image = 2;
|
||||
map<string, string> labels = 3;
|
||||
string snapshot_key = 4;
|
||||
}
|
||||
|
||||
message ContainerDelete {
|
||||
string id = 1;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message ContentCreate {
|
||||
string digest = 1;
|
||||
int64 size = 2;
|
||||
}
|
||||
|
||||
message ContentDelete {
|
||||
string digest = 1;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.images.v1;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message ImageCreate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message ImageUpdate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message ImageDelete {
|
||||
string name = 1;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message NamespaceCreate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message NamespaceUpdate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message NamespaceDelete {
|
||||
string name = 1;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
|
||||
message SandboxCreate {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message SandboxStart {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message SandboxExit {
|
||||
string sandbox_id = 1;
|
||||
uint32 exit_status = 2;
|
||||
google.protobuf.Timestamp exited_at = 3;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message SnapshotPrepare {
|
||||
string key = 1;
|
||||
string parent = 2;
|
||||
string snapshotter = 5;
|
||||
}
|
||||
|
||||
message SnapshotCommit {
|
||||
string key = 1;
|
||||
string name = 2;
|
||||
string snapshotter = 5;
|
||||
}
|
||||
|
||||
message SnapshotRemove {
|
||||
string key = 1;
|
||||
string snapshotter = 5;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message TaskCreate {
|
||||
string container_id = 1;
|
||||
string bundle = 2;
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
TaskIO io = 4;
|
||||
string checkpoint = 5;
|
||||
uint32 pid = 6;
|
||||
}
|
||||
|
||||
message TaskStart {
|
||||
string container_id = 1;
|
||||
uint32 pid = 2;
|
||||
}
|
||||
|
||||
message TaskDelete {
|
||||
string container_id = 1;
|
||||
uint32 pid = 2;
|
||||
uint32 exit_status = 3;
|
||||
google.protobuf.Timestamp exited_at = 4;
|
||||
// id is the specific exec. By default if omitted will be `""` thus matches
|
||||
// the init exec of the task matching `container_id`.
|
||||
string id = 5;
|
||||
}
|
||||
|
||||
message TaskIO {
|
||||
string stdin = 1;
|
||||
string stdout = 2;
|
||||
string stderr = 3;
|
||||
bool terminal = 4;
|
||||
}
|
||||
|
||||
message TaskExit {
|
||||
string container_id = 1;
|
||||
string id = 2;
|
||||
uint32 pid = 3;
|
||||
uint32 exit_status = 4;
|
||||
google.protobuf.Timestamp exited_at = 5;
|
||||
}
|
||||
|
||||
message TaskOOM {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message TaskExecAdded {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message TaskExecStarted {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 pid = 3;
|
||||
}
|
||||
|
||||
message TaskPaused {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message TaskResumed {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message TaskCheckpointed {
|
||||
string container_id = 1;
|
||||
string checkpoint = 2;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.runtime.sandbox.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||
import "github.com/containerd/containerd/api/types/metrics.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/runtime/sandbox/v1;sandbox";
|
||||
|
||||
// Sandbox is an optional interface that shim may implement to support sandboxes environments.
|
||||
// A typical example of sandbox is microVM or pause container - an entity that groups containers and/or
|
||||
// holds resources relevant for this group.
|
||||
service Sandbox {
|
||||
// CreateSandbox will be called right after sandbox shim instance launched.
|
||||
// It is a good place to initialize sandbox environment.
|
||||
rpc CreateSandbox(CreateSandboxRequest) returns (CreateSandboxResponse);
|
||||
|
||||
// StartSandbox will start a previously created sandbox.
|
||||
rpc StartSandbox(StartSandboxRequest) returns (StartSandboxResponse);
|
||||
|
||||
// Platform queries the platform the sandbox is going to run containers on.
|
||||
// containerd will use this to generate a proper OCI spec.
|
||||
rpc Platform(PlatformRequest) returns (PlatformResponse);
|
||||
|
||||
// StopSandbox will stop existing sandbox instance
|
||||
rpc StopSandbox(StopSandboxRequest) returns (StopSandboxResponse);
|
||||
|
||||
// WaitSandbox blocks until sandbox exits.
|
||||
rpc WaitSandbox(WaitSandboxRequest) returns (WaitSandboxResponse);
|
||||
|
||||
// SandboxStatus will return current status of the running sandbox instance
|
||||
rpc SandboxStatus(SandboxStatusRequest) returns (SandboxStatusResponse);
|
||||
|
||||
// PingSandbox is a lightweight API call to check whether sandbox alive.
|
||||
rpc PingSandbox(PingRequest) returns (PingResponse);
|
||||
|
||||
// ShutdownSandbox must shutdown shim instance.
|
||||
rpc ShutdownSandbox(ShutdownSandboxRequest) returns (ShutdownSandboxResponse);
|
||||
|
||||
// SandboxMetrics retrieves metrics about a sandbox instance.
|
||||
rpc SandboxMetrics(SandboxMetricsRequest) returns (SandboxMetricsResponse);
|
||||
}
|
||||
|
||||
message CreateSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
string bundle_path = 2;
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
google.protobuf.Any options = 4;
|
||||
string netns_path = 5;
|
||||
map<string, string> annotations = 6;
|
||||
}
|
||||
|
||||
message CreateSandboxResponse {}
|
||||
|
||||
message StartSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message StartSandboxResponse {
|
||||
uint32 pid = 1;
|
||||
google.protobuf.Timestamp created_at = 2;
|
||||
}
|
||||
|
||||
message PlatformRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message PlatformResponse {
|
||||
containerd.types.Platform platform = 1;
|
||||
}
|
||||
|
||||
message StopSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
uint32 timeout_secs = 2;
|
||||
}
|
||||
|
||||
message StopSandboxResponse {}
|
||||
|
||||
message UpdateSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
google.protobuf.Any resources = 2;
|
||||
map<string, string> annotations = 3;
|
||||
}
|
||||
|
||||
message WaitSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message WaitSandboxResponse {
|
||||
uint32 exit_status = 1;
|
||||
google.protobuf.Timestamp exited_at = 2;
|
||||
}
|
||||
|
||||
message UpdateSandboxResponse {}
|
||||
|
||||
message SandboxStatusRequest {
|
||||
string sandbox_id = 1;
|
||||
bool verbose = 2;
|
||||
}
|
||||
|
||||
message SandboxStatusResponse {
|
||||
string sandbox_id = 1;
|
||||
uint32 pid = 2;
|
||||
string state = 3;
|
||||
map<string, string> info = 4;
|
||||
google.protobuf.Timestamp created_at = 5;
|
||||
google.protobuf.Timestamp exited_at = 6;
|
||||
google.protobuf.Any extra = 7;
|
||||
}
|
||||
|
||||
message PingRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message PingResponse {}
|
||||
|
||||
message ShutdownSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message ShutdownSandboxResponse {}
|
||||
|
||||
message SandboxMetricsRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message SandboxMetricsResponse {
|
||||
containerd.types.Metric metrics = 1;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.containers.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/containers/v1;containers";
|
||||
|
||||
// Containers provides metadata storage for containers used in the execution
|
||||
// service.
|
||||
//
|
||||
// The objects here provide an state-independent view of containers for use in
|
||||
// management and resource pinning. From that perspective, containers do not
|
||||
// have a "state" but rather this is the set of resources that will be
|
||||
// considered in use by the container.
|
||||
//
|
||||
// From the perspective of the execution service, these objects represent the
|
||||
// base parameters for creating a container process.
|
||||
//
|
||||
// In general, when looking to add fields for this type, first ask yourself
|
||||
// whether or not the function of the field has to do with runtime execution or
|
||||
// is invariant of the runtime state of the container. If it has to do with
|
||||
// runtime, or changes as the "container" is started and stops, it probably
|
||||
// doesn't belong on this object.
|
||||
service Containers {
|
||||
rpc Get(GetContainerRequest) returns (GetContainerResponse);
|
||||
rpc List(ListContainersRequest) returns (ListContainersResponse);
|
||||
rpc ListStream(ListContainersRequest) returns (stream ListContainerMessage);
|
||||
rpc Create(CreateContainerRequest) returns (CreateContainerResponse);
|
||||
rpc Update(UpdateContainerRequest) returns (UpdateContainerResponse);
|
||||
rpc Delete(DeleteContainerRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Container {
|
||||
// ID is the user-specified identifier.
|
||||
//
|
||||
// This field may not be updated.
|
||||
string id = 1;
|
||||
|
||||
// Labels provides an area to include arbitrary data on containers.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
//
|
||||
// Note that to add a new value to this field, read the existing set and
|
||||
// include the entire result in the update call.
|
||||
map<string, string> labels = 2;
|
||||
|
||||
// Image contains the reference of the image used to build the
|
||||
// specification and snapshots for running this container.
|
||||
//
|
||||
// If this field is updated, the spec and rootfs needed to updated, as well.
|
||||
string image = 3;
|
||||
|
||||
message Runtime {
|
||||
// Name is the name of the runtime.
|
||||
string name = 1;
|
||||
// Options specify additional runtime initialization options.
|
||||
google.protobuf.Any options = 2;
|
||||
}
|
||||
// Runtime specifies which runtime to use for executing this container.
|
||||
Runtime runtime = 4;
|
||||
|
||||
// Spec to be used when creating the container. This is runtime specific.
|
||||
google.protobuf.Any spec = 5;
|
||||
|
||||
// Snapshotter specifies the snapshotter name used for rootfs
|
||||
string snapshotter = 6;
|
||||
|
||||
// SnapshotKey specifies the snapshot key to use for the container's root
|
||||
// filesystem. When starting a task from this container, a caller should
|
||||
// look up the mounts from the snapshot service and include those on the
|
||||
// task create request.
|
||||
//
|
||||
// Snapshots referenced in this field will not be garbage collected.
|
||||
//
|
||||
// This field is set to empty when the rootfs is not a snapshot.
|
||||
//
|
||||
// This field may be updated.
|
||||
string snapshot_key = 7;
|
||||
|
||||
// CreatedAt is the time the container was first created.
|
||||
google.protobuf.Timestamp created_at = 8;
|
||||
|
||||
// UpdatedAt is the last time the container was mutated.
|
||||
google.protobuf.Timestamp updated_at = 9;
|
||||
|
||||
// Extensions allow clients to provide zero or more blobs that are directly
|
||||
// associated with the container. One may provide protobuf, json, or other
|
||||
// encoding formats. The primary use of this is to further decorate the
|
||||
// container object with fields that may be specific to a client integration.
|
||||
//
|
||||
// The key portion of this map should identify a "name" for the extension
|
||||
// that should be unique against other extensions. When updating extension
|
||||
// data, one should only update the specified extension using field paths
|
||||
// to select a specific map key.
|
||||
map<string, google.protobuf.Any> extensions = 10;
|
||||
|
||||
// Sandbox ID this container belongs to.
|
||||
string sandbox = 11;
|
||||
}
|
||||
|
||||
message GetContainerRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message GetContainerResponse {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
message ListContainersRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListContainersResponse {
|
||||
repeated Container containers = 1;
|
||||
}
|
||||
|
||||
message CreateContainerRequest {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
message CreateContainerResponse {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
// UpdateContainerRequest updates the metadata on one or more container.
|
||||
//
|
||||
// The operation should follow semantics described in
|
||||
// https://developers.google.com/protocol-buffers/docs/reference/csharp/class/google/protobuf/well-known-types/field-mask,
|
||||
// unless otherwise qualified.
|
||||
message UpdateContainerRequest {
|
||||
// Container provides the target values, as declared by the mask, for the update.
|
||||
//
|
||||
// The ID field must be set.
|
||||
Container container = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
}
|
||||
|
||||
message UpdateContainerResponse {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
message DeleteContainerRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ListContainerMessage {
|
||||
Container container = 1;
|
||||
}
|
||||
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.content.v1;
|
||||
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/content/v1;content";
|
||||
|
||||
// Content provides access to a content addressable storage system.
|
||||
service Content {
|
||||
// Info returns information about a committed object.
|
||||
//
|
||||
// This call can be used for getting the size of content and checking for
|
||||
// existence.
|
||||
rpc Info(InfoRequest) returns (InfoResponse);
|
||||
|
||||
// Update updates content metadata.
|
||||
//
|
||||
// This call can be used to manage the mutable content labels. The
|
||||
// immutable metadata such as digest, size, and committed at cannot
|
||||
// be updated.
|
||||
rpc Update(UpdateRequest) returns (UpdateResponse);
|
||||
|
||||
// List streams the entire set of content as Info objects and closes the
|
||||
// stream.
|
||||
//
|
||||
// Typically, this will yield a large response, chunked into messages.
|
||||
// Clients should make provisions to ensure they can handle the entire data
|
||||
// set.
|
||||
rpc List(ListContentRequest) returns (stream ListContentResponse);
|
||||
|
||||
// Delete will delete the referenced object.
|
||||
rpc Delete(DeleteContentRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Read allows one to read an object based on the offset into the content.
|
||||
//
|
||||
// The requested data may be returned in one or more messages.
|
||||
rpc Read(ReadContentRequest) returns (stream ReadContentResponse);
|
||||
|
||||
// Status returns the status for a single reference.
|
||||
rpc Status(StatusRequest) returns (StatusResponse);
|
||||
|
||||
// ListStatuses returns the status of ongoing object ingestions, started via
|
||||
// Write.
|
||||
//
|
||||
// Only those matching the regular expression will be provided in the
|
||||
// response. If the provided regular expression is empty, all ingestions
|
||||
// will be provided.
|
||||
rpc ListStatuses(ListStatusesRequest) returns (ListStatusesResponse);
|
||||
|
||||
// Write begins or resumes writes to a resource identified by a unique ref.
|
||||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
// Writes should be sequential and implementations may throw an error if
|
||||
// this is required.
|
||||
//
|
||||
// If expected_digest is set and already part of the content store, the
|
||||
// write will fail.
|
||||
//
|
||||
// When completed, the commit flag should be set to true. If expected size
|
||||
// or digest is set, the content will be validated against those values.
|
||||
rpc Write(stream WriteContentRequest) returns (stream WriteContentResponse);
|
||||
|
||||
// Abort cancels the ongoing write named in the request. Any resources
|
||||
// associated with the write will be collected.
|
||||
rpc Abort(AbortRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Info {
|
||||
// Digest is the hash identity of the blob.
|
||||
string digest = 1;
|
||||
|
||||
// Size is the total number of bytes in the blob.
|
||||
int64 size = 2;
|
||||
|
||||
// CreatedAt provides the time at which the blob was committed.
|
||||
google.protobuf.Timestamp created_at = 3;
|
||||
|
||||
// UpdatedAt provides the time the info was last updated.
|
||||
google.protobuf.Timestamp updated_at = 4;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 5;
|
||||
}
|
||||
|
||||
message InfoRequest {
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
message InfoResponse {
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message UpdateRequest {
|
||||
Info info = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
//
|
||||
// In info, Digest, Size, and CreatedAt are immutable,
|
||||
// other field may be updated using this mask.
|
||||
// If no mask is provided, all mutable field are updated.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
}
|
||||
|
||||
message UpdateResponse {
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message ListContentRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListContentResponse {
|
||||
repeated Info info = 1;
|
||||
}
|
||||
|
||||
message DeleteContentRequest {
|
||||
// Digest specifies which content to delete.
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
// ReadContentRequest defines the fields that make up a request to read a portion of
|
||||
// data from a stored object.
|
||||
message ReadContentRequest {
|
||||
// Digest is the hash identity to read.
|
||||
string digest = 1;
|
||||
|
||||
// Offset specifies the number of bytes from the start at which to begin
|
||||
// the read. If zero or less, the read will be from the start. This uses
|
||||
// standard zero-indexed semantics.
|
||||
int64 offset = 2;
|
||||
|
||||
// size is the total size of the read. If zero, the entire blob will be
|
||||
// returned by the service.
|
||||
int64 size = 3;
|
||||
}
|
||||
|
||||
// ReadContentResponse carries byte data for a read request.
|
||||
message ReadContentResponse {
|
||||
int64 offset = 1; // offset of the returned data
|
||||
bytes data = 2; // actual data
|
||||
}
|
||||
|
||||
message Status {
|
||||
google.protobuf.Timestamp started_at = 1;
|
||||
google.protobuf.Timestamp updated_at = 2;
|
||||
string ref = 3;
|
||||
int64 offset = 4;
|
||||
int64 total = 5;
|
||||
string expected = 6;
|
||||
}
|
||||
|
||||
|
||||
message StatusRequest {
|
||||
string ref = 1;
|
||||
}
|
||||
|
||||
message StatusResponse {
|
||||
Status status = 1;
|
||||
}
|
||||
|
||||
message ListStatusesRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListStatusesResponse {
|
||||
repeated Status statuses = 1;
|
||||
}
|
||||
|
||||
// WriteAction defines the behavior of a WriteRequest.
|
||||
enum WriteAction {
|
||||
// WriteActionStat instructs the writer to return the current status while
|
||||
// holding the lock on the write.
|
||||
STAT = 0;
|
||||
|
||||
// WriteActionWrite sets the action for the write request to write data.
|
||||
//
|
||||
// Any data included will be written at the provided offset. The
|
||||
// transaction will be left open for further writes.
|
||||
//
|
||||
// This is the default.
|
||||
WRITE = 1;
|
||||
|
||||
// WriteActionCommit will write any outstanding data in the message and
|
||||
// commit the write, storing it under the digest.
|
||||
//
|
||||
// This can be used in a single message to send the data, verify it and
|
||||
// commit it.
|
||||
//
|
||||
// This action will always terminate the write.
|
||||
COMMIT = 2;
|
||||
}
|
||||
|
||||
// WriteContentRequest writes data to the request ref at offset.
|
||||
message WriteContentRequest {
|
||||
// Action sets the behavior of the write.
|
||||
//
|
||||
// When this is a write and the ref is not yet allocated, the ref will be
|
||||
// allocated and the data will be written at offset.
|
||||
//
|
||||
// If the action is write and the ref is allocated, it will accept data to
|
||||
// an offset that has not yet been written.
|
||||
//
|
||||
// If the action is write and there is no data, the current write status
|
||||
// will be returned. This works differently from status because the stream
|
||||
// holds a lock.
|
||||
WriteAction action = 1;
|
||||
|
||||
// Ref identifies the pre-commit object to write to.
|
||||
string ref = 2;
|
||||
|
||||
// Total can be set to have the service validate the total size of the
|
||||
// committed content.
|
||||
//
|
||||
// The latest value before or with the commit action message will be use to
|
||||
// validate the content. If the offset overflows total, the service may
|
||||
// report an error. It is only required on one message for the write.
|
||||
//
|
||||
// If the value is zero or less, no validation of the final content will be
|
||||
// performed.
|
||||
int64 total = 3;
|
||||
|
||||
// Expected can be set to have the service validate the final content against
|
||||
// the provided digest.
|
||||
//
|
||||
// If the digest is already present in the object store, an AlreadyExists
|
||||
// error will be returned.
|
||||
//
|
||||
// Only the latest version will be used to check the content against the
|
||||
// digest. It is only required to include it on a single message, before or
|
||||
// with the commit action message.
|
||||
string expected = 4;
|
||||
|
||||
// Offset specifies the number of bytes from the start at which to begin
|
||||
// the write. For most implementations, this means from the start of the
|
||||
// file. This uses standard, zero-indexed semantics.
|
||||
//
|
||||
// If the action is write, the remote may remove all previously written
|
||||
// data after the offset. Implementations may support arbitrary offsets but
|
||||
// MUST support reseting this value to zero with a write. If an
|
||||
// implementation does not support a write at a particular offset, an
|
||||
// OutOfRange error must be returned.
|
||||
int64 offset = 5;
|
||||
|
||||
// Data is the actual bytes to be written.
|
||||
//
|
||||
// If this is empty and the message is not a commit, a response will be
|
||||
// returned with the current write state.
|
||||
bytes data = 6;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 7;
|
||||
}
|
||||
|
||||
// WriteContentResponse is returned on the culmination of a write call.
|
||||
message WriteContentResponse {
|
||||
// Action contains the action for the final message of the stream. A writer
|
||||
// should confirm that they match the intended result.
|
||||
WriteAction action = 1;
|
||||
|
||||
// StartedAt provides the time at which the write began.
|
||||
//
|
||||
// This must be set for stat and commit write actions. All other write
|
||||
// actions may omit this.
|
||||
google.protobuf.Timestamp started_at = 2;
|
||||
|
||||
// UpdatedAt provides the last time of a successful write.
|
||||
//
|
||||
// This must be set for stat and commit write actions. All other write
|
||||
// actions may omit this.
|
||||
google.protobuf.Timestamp updated_at = 3;
|
||||
|
||||
// Offset is the current committed size for the write.
|
||||
int64 offset = 4;
|
||||
|
||||
// Total provides the current, expected total size of the write.
|
||||
//
|
||||
// We include this to provide consistency with the Status structure on the
|
||||
// client writer.
|
||||
//
|
||||
// This is only valid on the Stat and Commit response.
|
||||
int64 total = 5;
|
||||
|
||||
// Digest, if present, includes the digest up to the currently committed
|
||||
// bytes. If action is commit, this field will be set. It is implementation
|
||||
// defined if this is set for other actions.
|
||||
string digest = 6;
|
||||
}
|
||||
|
||||
message AbortRequest {
|
||||
string ref = 1;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.diff.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/diff/v1;diff";
|
||||
|
||||
// Diff service creates and applies diffs
|
||||
service Diff {
|
||||
// Apply applies the content associated with the provided digests onto
|
||||
// the provided mounts. Archive content will be extracted and
|
||||
// decompressed if necessary.
|
||||
rpc Apply(ApplyRequest) returns (ApplyResponse);
|
||||
|
||||
// Diff creates a diff between the given mounts and uploads the result
|
||||
// to the content store.
|
||||
rpc Diff(DiffRequest) returns (DiffResponse);
|
||||
}
|
||||
|
||||
message ApplyRequest {
|
||||
// Diff is the descriptor of the diff to be extracted
|
||||
containerd.types.Descriptor diff = 1;
|
||||
|
||||
repeated containerd.types.Mount mounts = 2;
|
||||
|
||||
map<string, google.protobuf.Any> payloads = 3;
|
||||
// SyncFs is to synchronize the underlying filesystem containing files.
|
||||
bool sync_fs = 4;
|
||||
}
|
||||
|
||||
message ApplyResponse {
|
||||
// Applied is the descriptor for the object which was applied.
|
||||
// If the input was a compressed blob then the result will be
|
||||
// the descriptor for the uncompressed blob.
|
||||
containerd.types.Descriptor applied = 1;
|
||||
}
|
||||
|
||||
message DiffRequest {
|
||||
// Left are the mounts which represent the older copy
|
||||
// in which is the base of the computed changes.
|
||||
repeated containerd.types.Mount left = 1;
|
||||
|
||||
// Right are the mounts which represents the newer copy
|
||||
// in which changes from the left were made into.
|
||||
repeated containerd.types.Mount right = 2;
|
||||
|
||||
// MediaType is the media type descriptor for the created diff
|
||||
// object
|
||||
string media_type = 3;
|
||||
|
||||
// Ref identifies the pre-commit content store object. This
|
||||
// reference can be used to get the status from the content store.
|
||||
string ref = 4;
|
||||
|
||||
// Labels are the labels to apply to the generated content
|
||||
// on content store commit.
|
||||
map<string, string> labels = 5;
|
||||
|
||||
// SourceDateEpoch specifies the timestamp used to provide control for reproducibility.
|
||||
// See also https://reproducible-builds.org/docs/source-date-epoch/ .
|
||||
//
|
||||
// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01),
|
||||
// not to the source date epoch.
|
||||
google.protobuf.Timestamp source_date_epoch = 6;
|
||||
}
|
||||
|
||||
message DiffResponse {
|
||||
// Diff is the descriptor of the diff which can be applied
|
||||
containerd.types.Descriptor diff = 3;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.events.v1;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/event.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/events/v1;events";
|
||||
|
||||
service Events {
|
||||
// Publish an event to a topic.
|
||||
//
|
||||
// The event will be packed into a timestamp envelope with the namespace
|
||||
// introspected from the context. The envelope will then be dispatched.
|
||||
rpc Publish(PublishRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Forward sends an event that has already been packaged into an envelope
|
||||
// with a timestamp and namespace.
|
||||
//
|
||||
// This is useful if earlier timestamping is required or when forwarding on
|
||||
// behalf of another component, namespace or publisher.
|
||||
rpc Forward(ForwardRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Subscribe to a stream of events, possibly returning only that match any
|
||||
// of the provided filters.
|
||||
//
|
||||
// Unlike many other methods in containerd, subscribers will get messages
|
||||
// from all namespaces unless otherwise specified. If this is not desired,
|
||||
// a filter can be provided in the format 'namespace==<namespace>' to
|
||||
// restrict the received events.
|
||||
rpc Subscribe(SubscribeRequest) returns (stream containerd.types.Envelope);
|
||||
}
|
||||
|
||||
message PublishRequest {
|
||||
string topic = 1;
|
||||
google.protobuf.Any event = 2;
|
||||
}
|
||||
|
||||
message ForwardRequest {
|
||||
containerd.types.Envelope envelope = 1;
|
||||
}
|
||||
|
||||
message SubscribeRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.images.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/images/v1;images";
|
||||
|
||||
// Images is a service that allows one to register images with containerd.
|
||||
//
|
||||
// In containerd, an image is merely the mapping of a name to a content root,
|
||||
// described by a descriptor. The behavior and state of image is purely
|
||||
// dictated by the type of the descriptor.
|
||||
//
|
||||
// From the perspective of this service, these references are mostly shallow,
|
||||
// in that the existence of the required content won't be validated until
|
||||
// required by consuming services.
|
||||
//
|
||||
// As such, this can really be considered a "metadata service".
|
||||
service Images {
|
||||
// Get returns an image by name.
|
||||
rpc Get(GetImageRequest) returns (GetImageResponse);
|
||||
|
||||
// List returns a list of all images known to containerd.
|
||||
rpc List(ListImagesRequest) returns (ListImagesResponse);
|
||||
|
||||
// Create an image record in the metadata store.
|
||||
//
|
||||
// The name of the image must be unique.
|
||||
rpc Create(CreateImageRequest) returns (CreateImageResponse);
|
||||
|
||||
// Update assigns the name to a given target image based on the provided
|
||||
// image.
|
||||
rpc Update(UpdateImageRequest) returns (UpdateImageResponse);
|
||||
|
||||
// Delete deletes the image by name.
|
||||
rpc Delete(DeleteImageRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Image {
|
||||
// Name provides a unique name for the image.
|
||||
//
|
||||
// Containerd treats this as the primary identifier.
|
||||
string name = 1;
|
||||
|
||||
// Labels provides free form labels for the image. These are runtime only
|
||||
// and do not get inherited into the package image in any way.
|
||||
//
|
||||
// Labels may be updated using the field mask.
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 2;
|
||||
|
||||
// Target describes the content entry point of the image.
|
||||
containerd.types.Descriptor target = 3;
|
||||
|
||||
// CreatedAt is the time the image was first created.
|
||||
google.protobuf.Timestamp created_at = 7;
|
||||
|
||||
// UpdatedAt is the last time the image was mutated.
|
||||
google.protobuf.Timestamp updated_at = 8;
|
||||
}
|
||||
|
||||
message GetImageRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message GetImageResponse {
|
||||
Image image = 1;
|
||||
}
|
||||
|
||||
message CreateImageRequest {
|
||||
Image image = 1;
|
||||
|
||||
google.protobuf.Timestamp source_date_epoch = 2;
|
||||
}
|
||||
|
||||
message CreateImageResponse {
|
||||
Image image = 1;
|
||||
}
|
||||
|
||||
message UpdateImageRequest {
|
||||
// Image provides a full or partial image for update.
|
||||
//
|
||||
// The name field must be set or an error will be returned.
|
||||
Image image = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
|
||||
google.protobuf.Timestamp source_date_epoch = 3;
|
||||
}
|
||||
|
||||
message UpdateImageResponse {
|
||||
Image image = 1;
|
||||
}
|
||||
|
||||
message ListImagesRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, images that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListImagesResponse {
|
||||
repeated Image images = 1;
|
||||
}
|
||||
|
||||
message DeleteImageRequest {
|
||||
string name = 1;
|
||||
|
||||
// Sync indicates that the delete and cleanup should be done
|
||||
// synchronously before returning to the caller
|
||||
//
|
||||
// Default is false
|
||||
bool sync = 2;
|
||||
|
||||
// Target value for image to be deleted
|
||||
//
|
||||
// If image descriptor does not match the same digest,
|
||||
// the delete operation will return "not found" error.
|
||||
optional containerd.types.Descriptor target = 3;
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.introspection.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "github.com/containerd/containerd/api/types/introspection.proto";
|
||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||
import "google/rpc/status.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/introspection/v1;introspection";
|
||||
|
||||
service Introspection {
|
||||
// Plugins returns a list of plugins in containerd.
|
||||
//
|
||||
// Clients can use this to detect features and capabilities when using
|
||||
// containerd.
|
||||
rpc Plugins(PluginsRequest) returns (PluginsResponse);
|
||||
// Server returns information about the containerd server
|
||||
rpc Server(google.protobuf.Empty) returns (ServerResponse);
|
||||
// PluginInfo returns information directly from a plugin if the plugin supports it
|
||||
rpc PluginInfo(PluginInfoRequest) returns (PluginInfoResponse);
|
||||
}
|
||||
|
||||
message Plugin {
|
||||
// Type defines the type of plugin.
|
||||
//
|
||||
// See package plugin for a list of possible values. Non core plugins may
|
||||
// define their own values during registration.
|
||||
string type = 1;
|
||||
|
||||
// ID identifies the plugin uniquely in the system.
|
||||
string id = 2;
|
||||
|
||||
// Requires lists the plugin types required by this plugin.
|
||||
repeated string requires = 3;
|
||||
|
||||
// Platforms enumerates the platforms this plugin will support.
|
||||
//
|
||||
// If values are provided here, the plugin will only be operable under the
|
||||
// provided platforms.
|
||||
//
|
||||
// If this is empty, the plugin will work across all platforms.
|
||||
//
|
||||
// If the plugin prefers certain platforms over others, they should be
|
||||
// listed from most to least preferred.
|
||||
repeated types.Platform platforms = 4;
|
||||
|
||||
// Exports allows plugins to provide values about state or configuration to
|
||||
// interested parties.
|
||||
//
|
||||
// One example is exposing the configured path of a snapshotter plugin.
|
||||
map<string, string> exports = 5;
|
||||
|
||||
// Capabilities allows plugins to communicate feature switches to allow
|
||||
// clients to detect features that may not be on be default or may be
|
||||
// different from version to version.
|
||||
//
|
||||
// Use this sparingly.
|
||||
repeated string capabilities = 6;
|
||||
|
||||
// InitErr will be set if the plugin fails initialization.
|
||||
//
|
||||
// This means the plugin may have been registered but a non-terminal error
|
||||
// was encountered during initialization.
|
||||
//
|
||||
// Plugins that have this value set cannot be used.
|
||||
google.rpc.Status init_err = 7;
|
||||
}
|
||||
|
||||
message PluginsRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, plugins that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message PluginsResponse {
|
||||
repeated Plugin plugins = 1;
|
||||
}
|
||||
|
||||
message ServerResponse {
|
||||
string uuid = 1;
|
||||
uint64 pid = 2;
|
||||
uint64 pidns = 3; // PID namespace, such as 4026531836
|
||||
repeated DeprecationWarning deprecations = 4;
|
||||
}
|
||||
|
||||
message DeprecationWarning {
|
||||
string id = 1;
|
||||
string message = 2;
|
||||
google.protobuf.Timestamp last_occurrence = 3;
|
||||
}
|
||||
|
||||
message PluginInfoRequest {
|
||||
string type = 1;
|
||||
string id = 2;
|
||||
|
||||
// Options may be used to request extra dynamic information from
|
||||
// a plugin.
|
||||
// This object is determined by the plugin and the plugin may return
|
||||
// NotImplemented or InvalidArgument if it is not supported
|
||||
google.protobuf.Any options = 3;
|
||||
}
|
||||
|
||||
message PluginInfoResponse {
|
||||
Plugin plugin = 1;
|
||||
google.protobuf.Any extra = 2;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.leases.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/leases/v1;leases";
|
||||
|
||||
// Leases service manages resources leases within the metadata store.
|
||||
service Leases {
|
||||
// Create creates a new lease for managing changes to metadata. A lease
|
||||
// can be used to protect objects from being removed.
|
||||
rpc Create(CreateRequest) returns (CreateResponse);
|
||||
|
||||
// Delete deletes the lease and makes any unreferenced objects created
|
||||
// during the lease eligible for garbage collection if not referenced
|
||||
// or retained by other resources during the lease.
|
||||
rpc Delete(DeleteRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// List lists all active leases, returning the full list of
|
||||
// leases and optionally including the referenced resources.
|
||||
rpc List(ListRequest) returns (ListResponse);
|
||||
|
||||
// AddResource references the resource by the provided lease.
|
||||
rpc AddResource(AddResourceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// DeleteResource dereferences the resource by the provided lease.
|
||||
rpc DeleteResource(DeleteResourceRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// ListResources lists all the resources referenced by the lease.
|
||||
rpc ListResources(ListResourcesRequest) returns (ListResourcesResponse);
|
||||
}
|
||||
|
||||
// Lease is an object which retains resources while it exists.
|
||||
message Lease {
|
||||
string id = 1;
|
||||
|
||||
google.protobuf.Timestamp created_at = 2;
|
||||
|
||||
map<string, string> labels = 3;
|
||||
}
|
||||
|
||||
message CreateRequest {
|
||||
// ID is used to identity the lease, when the id is not set the service
|
||||
// generates a random identifier for the lease.
|
||||
string id = 1;
|
||||
|
||||
map<string, string> labels = 3;
|
||||
}
|
||||
|
||||
message CreateResponse {
|
||||
Lease lease = 1;
|
||||
}
|
||||
|
||||
message DeleteRequest {
|
||||
string id = 1;
|
||||
|
||||
// Sync indicates that the delete and cleanup should be done
|
||||
// synchronously before returning to the caller
|
||||
//
|
||||
// Default is false
|
||||
bool sync = 2;
|
||||
}
|
||||
|
||||
message ListRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListResponse {
|
||||
repeated Lease leases = 1;
|
||||
}
|
||||
|
||||
message Resource {
|
||||
string id = 1;
|
||||
|
||||
// For snapshotter resource, there are many snapshotter types here, like
|
||||
// overlayfs, devmapper etc. The type will be formatted with type,
|
||||
// like "snapshotter/overlayfs".
|
||||
string type = 2;
|
||||
}
|
||||
|
||||
message AddResourceRequest {
|
||||
string id = 1;
|
||||
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message DeleteResourceRequest {
|
||||
string id = 1;
|
||||
|
||||
Resource resource = 2;
|
||||
}
|
||||
|
||||
message ListResourcesRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ListResourcesResponse {
|
||||
repeated Resource resources = 1 ;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.mounts.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/mounts/v1;mounts";
|
||||
|
||||
// Mounts service manages mounts
|
||||
service Mounts {
|
||||
rpc Activate(ActivateRequest) returns (ActivateResponse);
|
||||
rpc Deactivate(DeactivateRequest) returns (google.protobuf.Empty);
|
||||
rpc Info(InfoRequest) returns (InfoResponse);
|
||||
rpc Update(UpdateRequest) returns (UpdateResponse);
|
||||
rpc List(ListRequest) returns (stream ListMessage);
|
||||
}
|
||||
|
||||
message ActivateRequest {
|
||||
string name = 1;
|
||||
|
||||
repeated containerd.types.Mount mounts = 2;
|
||||
|
||||
map<string, string> labels = 3;
|
||||
|
||||
bool temporary = 4;
|
||||
|
||||
}
|
||||
|
||||
message ActivateResponse {
|
||||
containerd.types.ActivationInfo info = 1;
|
||||
}
|
||||
|
||||
message DeactivateRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message InfoRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message InfoResponse {
|
||||
containerd.types.ActivationInfo info = 1;
|
||||
}
|
||||
|
||||
message UpdateRequest {
|
||||
containerd.types.ActivationInfo info = 1;
|
||||
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
}
|
||||
|
||||
message UpdateResponse {
|
||||
containerd.types.ActivationInfo info = 1;
|
||||
}
|
||||
|
||||
message ListRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListMessage {
|
||||
containerd.types.ActivationInfo info = 1;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.namespaces.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/namespaces/v1;namespaces";
|
||||
|
||||
// Namespaces provides the ability to manipulate containerd namespaces.
|
||||
//
|
||||
// All objects in the system are required to be a member of a namespace. If a
|
||||
// namespace is deleted, all objects, including containers, images and
|
||||
// snapshots, will be deleted, as well.
|
||||
//
|
||||
// Unless otherwise noted, operations in containerd apply only to the namespace
|
||||
// supplied per request.
|
||||
//
|
||||
// I hope this goes without saying, but namespaces are themselves NOT
|
||||
// namespaced.
|
||||
service Namespaces {
|
||||
rpc Get(GetNamespaceRequest) returns (GetNamespaceResponse);
|
||||
rpc List(ListNamespacesRequest) returns (ListNamespacesResponse);
|
||||
rpc Create(CreateNamespaceRequest) returns (CreateNamespaceResponse);
|
||||
rpc Update(UpdateNamespaceRequest) returns (UpdateNamespaceResponse);
|
||||
rpc Delete(DeleteNamespaceRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Namespace {
|
||||
string name = 1;
|
||||
|
||||
// Labels provides an area to include arbitrary data on namespaces.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
//
|
||||
// Note that to add a new value to this field, read the existing set and
|
||||
// include the entire result in the update call.
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message GetNamespaceRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message GetNamespaceResponse {
|
||||
Namespace namespace = 1;
|
||||
}
|
||||
|
||||
message ListNamespacesRequest {
|
||||
string filter = 1;
|
||||
}
|
||||
|
||||
message ListNamespacesResponse {
|
||||
repeated Namespace namespaces = 1;
|
||||
}
|
||||
|
||||
message CreateNamespaceRequest {
|
||||
Namespace namespace = 1;
|
||||
}
|
||||
|
||||
message CreateNamespaceResponse {
|
||||
Namespace namespace = 1;
|
||||
}
|
||||
|
||||
// UpdateNamespaceRequest updates the metadata for a namespace.
|
||||
//
|
||||
// The operation should follow semantics described in
|
||||
// https://developers.google.com/protocol-buffers/docs/reference/csharp/class/google/protobuf/well-known-types/field-mask,
|
||||
// unless otherwise qualified.
|
||||
message UpdateNamespaceRequest {
|
||||
// Namespace provides the target value, as declared by the mask, for the update.
|
||||
//
|
||||
// The namespace field must be set.
|
||||
Namespace namespace = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
//
|
||||
// For the most part, this applies only to selectively updating labels on
|
||||
// the namespace. While field masks are typically limited to ascii alphas
|
||||
// and digits, we just take everything after the "labels." as the map key.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
}
|
||||
|
||||
message UpdateNamespaceResponse {
|
||||
Namespace namespace = 1;
|
||||
}
|
||||
|
||||
message DeleteNamespaceRequest {
|
||||
string name = 1;
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
// Sandbox is a v2 runtime extension that allows more complex execution environments for containers.
|
||||
// This adds a notion of groups of containers that share same lifecycle and/or resources.
|
||||
// A few good fits for sandbox can be:
|
||||
// - A "pause" container in k8s, that acts as a parent process for child containers to hold network namespace.
|
||||
// - (micro)VMs that launch a VM process and executes containers inside guest OS.
|
||||
// containerd in this case remains implementation agnostic and delegates sandbox handling to runtimes.
|
||||
// See proposal and discussion here: https://github.com/containerd/containerd/issues/4131
|
||||
package containerd.services.sandbox.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
import "github.com/containerd/containerd/api/types/sandbox.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||
import "github.com/containerd/containerd/api/types/metrics.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/sandbox/v1;sandbox";
|
||||
|
||||
// Store provides a metadata storage interface for sandboxes. Similarly to `Containers`,
|
||||
// sandbox object includes info required to start a new instance, but no runtime state.
|
||||
// When running a new sandbox instance, store objects are used as base type to create from.
|
||||
service Store {
|
||||
rpc Create(StoreCreateRequest) returns (StoreCreateResponse);
|
||||
rpc Update(StoreUpdateRequest) returns (StoreUpdateResponse);
|
||||
rpc Delete(StoreDeleteRequest) returns (StoreDeleteResponse);
|
||||
rpc List(StoreListRequest) returns (StoreListResponse);
|
||||
rpc Get(StoreGetRequest) returns (StoreGetResponse);
|
||||
}
|
||||
|
||||
message StoreCreateRequest {
|
||||
containerd.types.Sandbox sandbox = 1;
|
||||
}
|
||||
|
||||
message StoreCreateResponse {
|
||||
containerd.types.Sandbox sandbox = 1;
|
||||
}
|
||||
|
||||
message StoreUpdateRequest {
|
||||
containerd.types.Sandbox sandbox = 1;
|
||||
repeated string fields = 2;
|
||||
}
|
||||
|
||||
message StoreUpdateResponse {
|
||||
containerd.types.Sandbox sandbox = 1;
|
||||
}
|
||||
|
||||
message StoreDeleteRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message StoreDeleteResponse {}
|
||||
|
||||
message StoreListRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message StoreListResponse {
|
||||
repeated containerd.types.Sandbox list = 1;
|
||||
}
|
||||
|
||||
message StoreGetRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message StoreGetResponse {
|
||||
containerd.types.Sandbox sandbox = 1;
|
||||
}
|
||||
|
||||
// Controller is an interface to manage runtime sandbox instances.
|
||||
service Controller {
|
||||
rpc Create(ControllerCreateRequest) returns (ControllerCreateResponse);
|
||||
rpc Start(ControllerStartRequest) returns (ControllerStartResponse);
|
||||
rpc Platform(ControllerPlatformRequest) returns (ControllerPlatformResponse);
|
||||
rpc Stop(ControllerStopRequest) returns (ControllerStopResponse);
|
||||
rpc Wait(ControllerWaitRequest) returns (ControllerWaitResponse);
|
||||
rpc Status(ControllerStatusRequest) returns (ControllerStatusResponse);
|
||||
rpc Shutdown(ControllerShutdownRequest) returns (ControllerShutdownResponse);
|
||||
rpc Metrics(ControllerMetricsRequest) returns (ControllerMetricsResponse);
|
||||
rpc Update(ControllerUpdateRequest) returns (ControllerUpdateResponse);
|
||||
}
|
||||
|
||||
message ControllerCreateRequest {
|
||||
string sandbox_id = 1;
|
||||
repeated containerd.types.Mount rootfs = 2;
|
||||
google.protobuf.Any options = 3;
|
||||
string netns_path = 4;
|
||||
map<string, string> annotations = 5;
|
||||
containerd.types.Sandbox sandbox = 6;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerCreateResponse {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message ControllerStartRequest {
|
||||
string sandbox_id = 1;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerStartResponse {
|
||||
string sandbox_id = 1;
|
||||
uint32 pid = 2;
|
||||
google.protobuf.Timestamp created_at = 3;
|
||||
map<string, string> labels = 4;
|
||||
// Address of the sandbox for containerd to connect,
|
||||
// for calling Task or other APIs serving in the sandbox.
|
||||
// it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://<vsock cid>:<port>.
|
||||
string address = 5;
|
||||
uint32 version = 6;
|
||||
}
|
||||
|
||||
message ControllerPlatformRequest {
|
||||
string sandbox_id = 1;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerPlatformResponse {
|
||||
containerd.types.Platform platform = 1;
|
||||
}
|
||||
|
||||
message ControllerStopRequest {
|
||||
string sandbox_id = 1;
|
||||
uint32 timeout_secs = 2;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerStopResponse {}
|
||||
|
||||
message ControllerWaitRequest {
|
||||
string sandbox_id = 1;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerWaitResponse {
|
||||
uint32 exit_status = 1;
|
||||
google.protobuf.Timestamp exited_at = 2;
|
||||
}
|
||||
|
||||
message ControllerStatusRequest {
|
||||
string sandbox_id = 1;
|
||||
bool verbose = 2;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerStatusResponse {
|
||||
string sandbox_id = 1;
|
||||
uint32 pid = 2;
|
||||
string state = 3;
|
||||
map<string, string> info = 4;
|
||||
google.protobuf.Timestamp created_at = 5;
|
||||
google.protobuf.Timestamp exited_at = 6;
|
||||
google.protobuf.Any extra = 7;
|
||||
// Address of the sandbox for containerd to connect,
|
||||
// for calling Task or other APIs serving in the sandbox.
|
||||
// it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://<vsock cid>:<port>.
|
||||
string address = 8;
|
||||
uint32 version = 9;
|
||||
}
|
||||
|
||||
message ControllerShutdownRequest {
|
||||
string sandbox_id = 1;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerShutdownResponse {}
|
||||
|
||||
message ControllerMetricsRequest {
|
||||
string sandbox_id = 1;
|
||||
string sandboxer = 10;
|
||||
}
|
||||
|
||||
message ControllerMetricsResponse {
|
||||
types.Metric metrics = 1;
|
||||
}
|
||||
|
||||
message ControllerUpdateRequest {
|
||||
string sandbox_id = 1;
|
||||
string sandboxer = 2;
|
||||
containerd.types.Sandbox sandbox = 3;
|
||||
repeated string fields = 4;
|
||||
}
|
||||
|
||||
message ControllerUpdateResponse {
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.snapshots.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/snapshots/v1;snapshots";
|
||||
|
||||
// Snapshot service manages snapshots
|
||||
service Snapshots {
|
||||
rpc Prepare(PrepareSnapshotRequest) returns (PrepareSnapshotResponse);
|
||||
rpc View(ViewSnapshotRequest) returns (ViewSnapshotResponse);
|
||||
rpc Mounts(MountsRequest) returns (MountsResponse);
|
||||
rpc Commit(CommitSnapshotRequest) returns (google.protobuf.Empty);
|
||||
rpc Remove(RemoveSnapshotRequest) returns (google.protobuf.Empty);
|
||||
rpc Stat(StatSnapshotRequest) returns (StatSnapshotResponse);
|
||||
rpc Update(UpdateSnapshotRequest) returns (UpdateSnapshotResponse);
|
||||
rpc List(ListSnapshotsRequest) returns (stream ListSnapshotsResponse);
|
||||
rpc Usage(UsageRequest) returns (UsageResponse);
|
||||
rpc Cleanup(CleanupRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message PrepareSnapshotRequest {
|
||||
string snapshotter = 1;
|
||||
string key = 2;
|
||||
string parent = 3;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 4;
|
||||
}
|
||||
|
||||
message PrepareSnapshotResponse {
|
||||
repeated containerd.types.Mount mounts = 1;
|
||||
}
|
||||
|
||||
message ViewSnapshotRequest {
|
||||
string snapshotter = 1;
|
||||
string key = 2;
|
||||
string parent = 3;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 4;
|
||||
}
|
||||
|
||||
message ViewSnapshotResponse {
|
||||
repeated containerd.types.Mount mounts = 1;
|
||||
}
|
||||
|
||||
message MountsRequest {
|
||||
string snapshotter = 1;
|
||||
string key = 2;
|
||||
}
|
||||
|
||||
message MountsResponse {
|
||||
repeated containerd.types.Mount mounts = 1;
|
||||
}
|
||||
|
||||
message RemoveSnapshotRequest {
|
||||
string snapshotter = 1;
|
||||
string key = 2;
|
||||
}
|
||||
|
||||
message CommitSnapshotRequest {
|
||||
string snapshotter = 1;
|
||||
string name = 2;
|
||||
string key = 3;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 4;
|
||||
|
||||
string parent = 5;
|
||||
}
|
||||
|
||||
message StatSnapshotRequest {
|
||||
string snapshotter = 1;
|
||||
string key = 2;
|
||||
}
|
||||
|
||||
enum Kind {
|
||||
UNKNOWN = 0;
|
||||
VIEW = 1;
|
||||
ACTIVE = 2;
|
||||
COMMITTED = 3;
|
||||
}
|
||||
|
||||
message Info {
|
||||
string name = 1;
|
||||
string parent = 2;
|
||||
Kind kind = 3;
|
||||
|
||||
// CreatedAt provides the time at which the snapshot was created.
|
||||
google.protobuf.Timestamp created_at = 4;
|
||||
|
||||
// UpdatedAt provides the time the info was last updated.
|
||||
google.protobuf.Timestamp updated_at = 5;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 6;
|
||||
}
|
||||
|
||||
message StatSnapshotResponse {
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message UpdateSnapshotRequest {
|
||||
string snapshotter = 1;
|
||||
Info info = 2;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
//
|
||||
// In info, Name, Parent, Kind, Created are immutable,
|
||||
// other field may be updated using this mask.
|
||||
// If no mask is provided, all mutable field are updated.
|
||||
google.protobuf.FieldMask update_mask = 3;
|
||||
}
|
||||
|
||||
message UpdateSnapshotResponse {
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message ListSnapshotsRequest{
|
||||
string snapshotter = 1;
|
||||
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, images that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 2;
|
||||
}
|
||||
|
||||
message ListSnapshotsResponse {
|
||||
repeated Info info = 1;
|
||||
}
|
||||
|
||||
message UsageRequest {
|
||||
string snapshotter = 1;
|
||||
string key = 2;
|
||||
}
|
||||
|
||||
message UsageResponse {
|
||||
int64 size = 1;
|
||||
int64 inodes = 2;
|
||||
}
|
||||
|
||||
message CleanupRequest {
|
||||
string snapshotter = 1;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.streaming.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/streaming/v1;streaming";
|
||||
|
||||
service Streaming {
|
||||
rpc Stream(stream google.protobuf.Any) returns (stream google.protobuf.Any);
|
||||
}
|
||||
|
||||
message StreamInit {
|
||||
string id = 1;
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.tasks.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "github.com/containerd/containerd/api/types/mount.proto";
|
||||
import "github.com/containerd/containerd/api/types/metrics.proto";
|
||||
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||
import "github.com/containerd/containerd/api/types/task/task.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/tasks/v1;tasks";
|
||||
|
||||
service Tasks {
|
||||
// Create a task.
|
||||
rpc Create(CreateTaskRequest) returns (CreateTaskResponse);
|
||||
|
||||
// Start a process.
|
||||
rpc Start(StartRequest) returns (StartResponse);
|
||||
|
||||
// Delete a task and on disk state.
|
||||
rpc Delete(DeleteTaskRequest) returns (DeleteResponse);
|
||||
|
||||
rpc DeleteProcess(DeleteProcessRequest) returns (DeleteResponse);
|
||||
|
||||
rpc Get(GetRequest) returns (GetResponse);
|
||||
|
||||
rpc List(ListTasksRequest) returns (ListTasksResponse);
|
||||
|
||||
// Kill a task or process.
|
||||
rpc Kill(KillRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc Exec(ExecProcessRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc ResizePty(ResizePtyRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc CloseIO(CloseIORequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc Pause(PauseTaskRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc Resume(ResumeTaskRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc ListPids(ListPidsRequest) returns (ListPidsResponse);
|
||||
|
||||
rpc Checkpoint(CheckpointTaskRequest) returns (CheckpointTaskResponse);
|
||||
|
||||
rpc Update(UpdateTaskRequest) returns (google.protobuf.Empty);
|
||||
|
||||
rpc Metrics(MetricsRequest) returns (MetricsResponse);
|
||||
|
||||
rpc Wait(WaitRequest) returns (WaitResponse);
|
||||
}
|
||||
|
||||
message CreateTaskRequest {
|
||||
string container_id = 1;
|
||||
|
||||
// RootFS provides the pre-chroot mounts to perform in the shim before
|
||||
// executing the container task.
|
||||
//
|
||||
// These are for mounts that cannot be performed in the user namespace.
|
||||
// Typically, these mounts should be resolved from snapshots specified on
|
||||
// the container object.
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
|
||||
string stdin = 4;
|
||||
string stdout = 5;
|
||||
string stderr = 6;
|
||||
bool terminal = 7;
|
||||
|
||||
containerd.types.Descriptor checkpoint = 8;
|
||||
|
||||
google.protobuf.Any options = 9;
|
||||
|
||||
string runtime_path = 10;
|
||||
}
|
||||
|
||||
message CreateTaskResponse {
|
||||
string container_id = 1;
|
||||
uint32 pid = 2;
|
||||
}
|
||||
|
||||
message StartRequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message StartResponse {
|
||||
uint32 pid = 1;
|
||||
}
|
||||
|
||||
message DeleteTaskRequest {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
string id = 1;
|
||||
uint32 pid = 2;
|
||||
uint32 exit_status = 3;
|
||||
google.protobuf.Timestamp exited_at = 4;
|
||||
}
|
||||
|
||||
message DeleteProcessRequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message GetRequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message GetResponse {
|
||||
containerd.v1.types.Process process = 1;
|
||||
}
|
||||
|
||||
message ListTasksRequest {
|
||||
string filter = 1;
|
||||
}
|
||||
|
||||
message ListTasksResponse {
|
||||
repeated containerd.v1.types.Process tasks = 1;
|
||||
}
|
||||
|
||||
message KillRequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 signal = 3;
|
||||
bool all = 4;
|
||||
}
|
||||
|
||||
message ExecProcessRequest {
|
||||
string container_id = 1;
|
||||
string stdin = 2;
|
||||
string stdout = 3;
|
||||
string stderr = 4;
|
||||
bool terminal = 5;
|
||||
// Spec for starting a process in the target container.
|
||||
//
|
||||
// For runc, this is a process spec, for example.
|
||||
google.protobuf.Any spec = 6;
|
||||
// id of the exec process
|
||||
string exec_id = 7;
|
||||
}
|
||||
|
||||
message ExecProcessResponse {
|
||||
}
|
||||
|
||||
message ResizePtyRequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 width = 3;
|
||||
uint32 height = 4;
|
||||
}
|
||||
|
||||
message CloseIORequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
bool stdin = 3;
|
||||
}
|
||||
|
||||
message PauseTaskRequest {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message ResumeTaskRequest {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message ListPidsRequest {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message ListPidsResponse {
|
||||
// Processes includes the process ID and additional process information
|
||||
repeated containerd.v1.types.ProcessInfo processes = 1;
|
||||
}
|
||||
|
||||
message CheckpointTaskRequest {
|
||||
string container_id = 1;
|
||||
string parent_checkpoint = 2;
|
||||
google.protobuf.Any options = 3;
|
||||
}
|
||||
|
||||
message CheckpointTaskResponse {
|
||||
repeated containerd.types.Descriptor descriptors = 1;
|
||||
}
|
||||
|
||||
message UpdateTaskRequest {
|
||||
string container_id = 1;
|
||||
google.protobuf.Any resources = 2;
|
||||
map<string, string> annotations = 3;
|
||||
}
|
||||
|
||||
message MetricsRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message MetricsResponse {
|
||||
repeated types.Metric metrics = 1;
|
||||
}
|
||||
|
||||
message WaitRequest {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message WaitResponse {
|
||||
uint32 exit_status = 1;
|
||||
google.protobuf.Timestamp exited_at = 2;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.transfer.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/transfer/v1;transfer";
|
||||
|
||||
service Transfer {
|
||||
rpc Transfer(TransferRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message TransferRequest {
|
||||
google.protobuf.Any source = 1;
|
||||
google.protobuf.Any destination = 2;
|
||||
TransferOptions options = 3;
|
||||
}
|
||||
|
||||
message TransferOptions {
|
||||
string progress_stream = 1;
|
||||
// Progress min interval
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.version.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
// TODO(stevvooe): Should version service actually be versioned?
|
||||
option go_package = "github.com/containerd/containerd/api/services/version/v1;version";
|
||||
|
||||
service Version {
|
||||
rpc Version(google.protobuf.Empty) returns (VersionResponse);
|
||||
}
|
||||
|
||||
message VersionResponse {
|
||||
string version = 1;
|
||||
string revision = 2;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
// Descriptor describes a blob in a content store.
|
||||
//
|
||||
// This descriptor can be used to reference content from an
|
||||
// oci descriptor found in a manifest.
|
||||
// See https://godoc.org/github.com/opencontainers/image-spec/specs-go/v1#Descriptor
|
||||
message Descriptor {
|
||||
string media_type = 1;
|
||||
string digest = 2;
|
||||
int64 size = 3;
|
||||
map<string, string> annotations = 5;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/fieldpath.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
message Envelope {
|
||||
option (containerd.types.fieldpath) = true;
|
||||
google.protobuf.Timestamp timestamp = 1;
|
||||
string namespace = 2;
|
||||
string topic = 3;
|
||||
google.protobuf.Any event = 4;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Protocol Buffers for Go with Gadgets
|
||||
//
|
||||
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
|
||||
// http://github.com/gogo/protobuf
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
syntax = "proto3";
|
||||
package containerd.types;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
extend google.protobuf.FileOptions {
|
||||
optional bool fieldpath_all = 63300;
|
||||
}
|
||||
|
||||
extend google.protobuf.MessageOptions {
|
||||
optional bool fieldpath = 64400;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
message RuntimeRequest {
|
||||
string runtime_path = 1;
|
||||
// Options correspond to CreateTaskRequest.options.
|
||||
// This is needed to pass the runc binary path, etc.
|
||||
google.protobuf.Any options = 2;
|
||||
}
|
||||
|
||||
message RuntimeVersion {
|
||||
string version = 1;
|
||||
string revision = 2;
|
||||
}
|
||||
|
||||
message RuntimeInfo {
|
||||
string name = 1;
|
||||
RuntimeVersion version = 2;
|
||||
// Options correspond to RuntimeInfoRequest.Options (contains runc binary path, etc.)
|
||||
google.protobuf.Any options = 3;
|
||||
// OCI-compatible runtimes should use https://github.com/opencontainers/runtime-spec/blob/main/features.md
|
||||
google.protobuf.Any features = 4;
|
||||
// Annotations of the shim. Irrelevant to features.Annotations.
|
||||
map<string, string> annotations = 5;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
message Metric {
|
||||
google.protobuf.Timestamp timestamp = 1;
|
||||
string id = 2;
|
||||
google.protobuf.Any data = 3;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
// Mount describes mounts for a container.
|
||||
//
|
||||
// This type is the lingua franca of ContainerD. All services provide mounts
|
||||
// to be used with the container at creation time.
|
||||
//
|
||||
// The Mount type follows the structure of the mount syscall, including a type,
|
||||
// source, target and options.
|
||||
message Mount {
|
||||
// Type defines the nature of the mount.
|
||||
string type = 1;
|
||||
|
||||
// Source specifies the name of the mount. Depending on mount type, this
|
||||
// may be a volume name or a host path, or even ignored.
|
||||
string source = 2;
|
||||
|
||||
// Target path in container
|
||||
string target = 3;
|
||||
|
||||
// Options specifies zero or more fstab style mount options.
|
||||
repeated string options = 4;
|
||||
}
|
||||
|
||||
message ActiveMount {
|
||||
Mount mount = 1;
|
||||
|
||||
google.protobuf.Timestamp mounted_at = 2;
|
||||
|
||||
string mount_point = 3;
|
||||
|
||||
map<string, string> data = 4;
|
||||
}
|
||||
|
||||
message ActivationInfo {
|
||||
string name = 1;
|
||||
|
||||
repeated ActiveMount active = 2;
|
||||
|
||||
repeated Mount system = 3;
|
||||
|
||||
map<string, string> labels = 4;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
// Platform follows the structure of the OCI platform specification, from
|
||||
// descriptors.
|
||||
message Platform {
|
||||
string os = 1;
|
||||
string architecture = 2;
|
||||
string variant = 3;
|
||||
string os_version = 4;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.runc.v1;
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/runc/options;options";
|
||||
|
||||
message Options {
|
||||
// disable pivot root when creating a container
|
||||
bool no_pivot_root = 1;
|
||||
// create a new keyring for the container
|
||||
bool no_new_keyring = 2;
|
||||
// place the shim in a cgroup
|
||||
string shim_cgroup = 3;
|
||||
// set the I/O's pipes uid
|
||||
uint32 io_uid = 4;
|
||||
// set the I/O's pipes gid
|
||||
uint32 io_gid = 5;
|
||||
// binary name of the runc binary
|
||||
string binary_name = 6;
|
||||
// runc root directory
|
||||
string root = 7;
|
||||
// criu binary path.
|
||||
//
|
||||
// Removed in containerd v2.0: string criu_path = 8;
|
||||
reserved 8;
|
||||
// enable systemd cgroups
|
||||
bool systemd_cgroup = 9;
|
||||
// criu image path
|
||||
string criu_image_path = 10;
|
||||
// criu work path
|
||||
string criu_work_path = 11;
|
||||
// task api address, can be a unix domain socket, or vsock address.
|
||||
// it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://<vsock cid>:<port>.
|
||||
string task_api_address = 12;
|
||||
// task api version, currently supported value is 2 and 3.
|
||||
uint32 task_api_version = 13;
|
||||
}
|
||||
|
||||
message CheckpointOptions {
|
||||
// exit the container after a checkpoint
|
||||
bool exit = 1;
|
||||
// checkpoint open tcp connections
|
||||
bool open_tcp = 2;
|
||||
// checkpoint external unix sockets
|
||||
bool external_unix_sockets = 3;
|
||||
// checkpoint terminals (ptys)
|
||||
bool terminal = 4;
|
||||
// allow checkpointing of file locks
|
||||
bool file_locks = 5;
|
||||
// restore provided namespaces as empty namespaces
|
||||
repeated string empty_namespaces = 6;
|
||||
// set the cgroups mode, soft, full, strict
|
||||
string cgroups_mode = 7;
|
||||
// checkpoint image path
|
||||
string image_path = 8;
|
||||
// checkpoint work path
|
||||
string work_path = 9;
|
||||
}
|
||||
|
||||
message ProcessDetails {
|
||||
// exec process id if the process is managed by a shim
|
||||
string exec_id = 1;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// To regenerate api.pb.go run `make protos`
|
||||
syntax = "proto3";
|
||||
|
||||
package runtimeoptions.v1;
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/runtimeoptions/v1;runtimeoptions";
|
||||
|
||||
message Options {
|
||||
// TypeUrl specifies the type of the content inside the config file.
|
||||
string type_url = 1;
|
||||
// ConfigPath specifies the filesystem location of the config file
|
||||
// used by the runtime.
|
||||
string config_path = 2;
|
||||
// Blob specifies an in-memory TOML blob passed from containerd's configuration section
|
||||
// for this runtime. This will be used if config_path is not specified.
|
||||
bytes config_body = 3;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types;types";
|
||||
|
||||
// Sandbox represents a sandbox metadata object that keeps all info required by controller to
|
||||
// work with a particular instance.
|
||||
message Sandbox {
|
||||
// SandboxID is a unique instance identifier within namespace
|
||||
string sandbox_id = 1;
|
||||
message Runtime {
|
||||
// Name is the name of the runtime.
|
||||
string name = 1;
|
||||
// Options specify additional runtime initialization options for the shim (this data will be available in StartShim).
|
||||
// Typically this data expected to be runtime shim implementation specific.
|
||||
google.protobuf.Any options = 2;
|
||||
}
|
||||
// Runtime specifies which runtime to use for executing this container.
|
||||
Runtime runtime = 2;
|
||||
// Spec is sandbox configuration (kin of OCI runtime spec), spec's data will be written to a config.json file in the
|
||||
// bundle directory (similary to OCI spec).
|
||||
google.protobuf.Any spec = 3;
|
||||
// Labels provides an area to include arbitrary data on containers.
|
||||
map<string, string> labels = 4;
|
||||
// CreatedAt is the time the container was first created.
|
||||
google.protobuf.Timestamp created_at = 5;
|
||||
// UpdatedAt is the last time the container was mutated.
|
||||
google.protobuf.Timestamp updated_at = 6;
|
||||
// Extensions allow clients to provide optional blobs that can be handled by runtime.
|
||||
map<string, google.protobuf.Any> extensions = 7;
|
||||
// Sandboxer is the name of the sandbox controller who manages the sandbox.
|
||||
string sandboxer = 10;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.v1.types;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/task";
|
||||
|
||||
enum Status {
|
||||
UNKNOWN = 0;
|
||||
CREATED = 1;
|
||||
RUNNING = 2;
|
||||
STOPPED = 3;
|
||||
PAUSED = 4;
|
||||
PAUSING = 5;
|
||||
}
|
||||
|
||||
message Process {
|
||||
string container_id = 1;
|
||||
string id = 2;
|
||||
uint32 pid = 3;
|
||||
Status status = 4;
|
||||
string stdin = 5;
|
||||
string stdout = 6;
|
||||
string stderr = 7;
|
||||
bool terminal = 8;
|
||||
uint32 exit_status = 9;
|
||||
google.protobuf.Timestamp exited_at = 10;
|
||||
}
|
||||
|
||||
message ProcessInfo {
|
||||
// PID is the process ID.
|
||||
uint32 pid = 1;
|
||||
// Info contains additional process information.
|
||||
//
|
||||
// Info varies by platform.
|
||||
google.protobuf.Any info = 2;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types.transfer;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/transfer";
|
||||
|
||||
message ImageStore {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
|
||||
// Content filters
|
||||
|
||||
repeated types.Platform platforms = 3;
|
||||
bool all_metadata = 4;
|
||||
uint32 manifest_limit = 5;
|
||||
|
||||
// Import naming
|
||||
|
||||
// extra_references are used to set image names on imports of sub-images from the index
|
||||
repeated ImageReference extra_references = 6;
|
||||
|
||||
// Unpack Configuration, multiple allowed
|
||||
|
||||
repeated UnpackConfiguration unpacks = 10;
|
||||
}
|
||||
|
||||
message UnpackConfiguration {
|
||||
// platform is the platform to unpack for, used for resolving manifest and snapshotter
|
||||
// if not provided
|
||||
types.Platform platform = 1;
|
||||
|
||||
// snapshotter to unpack to, if not provided default for platform shoudl be used
|
||||
string snapshotter = 2;
|
||||
}
|
||||
|
||||
// ImageReference is used to create or find a reference for an image
|
||||
message ImageReference {
|
||||
string name = 1;
|
||||
|
||||
// is_prefix determines whether the Name should be considered
|
||||
// a prefix (without tag or digest).
|
||||
// For lookup, this may allow matching multiple tags.
|
||||
// For store, this must have a tag or digest added.
|
||||
bool is_prefix = 2;
|
||||
|
||||
// allow_overwrite allows overwriting or ignoring the name if
|
||||
// another reference is provided (such as through an annotation).
|
||||
// Only used if IsPrefix is true.
|
||||
bool allow_overwrite = 3;
|
||||
|
||||
// add_digest adds the manifest digest to the reference.
|
||||
// For lookup, this allows matching tags with any digest.
|
||||
// For store, this allows adding the digest to the name.
|
||||
// Only used if IsPrefix is true.
|
||||
bool add_digest = 4;
|
||||
|
||||
// skip_named_digest only considers digest references which do not
|
||||
// have a non-digested named reference.
|
||||
// For lookup, this will deduplicate digest references when there is a named match.
|
||||
// For store, this only adds this digest reference when there is no matching full
|
||||
// name reference from the prefix.
|
||||
// Only used if IsPrefix is true.
|
||||
bool skip_named_digest = 5;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types.transfer;
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/transfer";
|
||||
|
||||
import "github.com/containerd/containerd/api/types/platform.proto";
|
||||
|
||||
message ImageImportStream {
|
||||
// Stream is used to identify the binary input stream for the import operation.
|
||||
// The stream uses the transfer binary stream protocol with the client as the sender.
|
||||
// The binary data is expected to be a raw tar stream.
|
||||
string stream = 1;
|
||||
|
||||
string media_type = 2;
|
||||
|
||||
bool force_compress = 3;
|
||||
}
|
||||
|
||||
message ImageExportStream {
|
||||
// Stream is used to identify the binary output stream for the export operation.
|
||||
// The stream uses the transfer binary stream protocol with the server as the sender.
|
||||
// The binary data is expected to be a raw tar stream.
|
||||
string stream = 1;
|
||||
|
||||
string media_type = 2;
|
||||
|
||||
// The specified platforms
|
||||
repeated types.Platform platforms = 3;
|
||||
// Whether to include all platforms
|
||||
bool all_platforms = 4;
|
||||
// Skips the creation of the Docker compatible manifest.json file
|
||||
bool skip_compatibility_manifest = 5;
|
||||
// Excludes non-distributable blobs such as Windows base layers.
|
||||
bool skip_non_distributable = 6;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types.transfer;
|
||||
|
||||
import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/transfer";
|
||||
|
||||
message Progress {
|
||||
string event = 1;
|
||||
string name = 2;
|
||||
repeated string parents = 3;
|
||||
int64 progress = 4;
|
||||
int64 total = 5;
|
||||
containerd.types.Descriptor desc = 6;
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types.transfer;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/transfer";
|
||||
|
||||
message OCIRegistry {
|
||||
string reference = 1;
|
||||
RegistryResolver resolver = 2;
|
||||
}
|
||||
|
||||
enum HTTPDebug {
|
||||
DISABLED = 0;
|
||||
// Enable HTTP debugging
|
||||
DEBUG = 1;
|
||||
// Enable HTTP requests tracing
|
||||
TRACE = 2;
|
||||
// Enable both HTTP debugging and requests tracing
|
||||
BOTH = 3;
|
||||
}
|
||||
|
||||
message RegistryResolver {
|
||||
// auth_stream is used to refer to a stream which auth callbacks may be
|
||||
// made on.
|
||||
string auth_stream = 1;
|
||||
|
||||
// Headers
|
||||
map<string, string> headers = 2;
|
||||
|
||||
string host_dir = 3;
|
||||
|
||||
string default_scheme = 4;
|
||||
// Force skip verify
|
||||
// CA callback? Client TLS callback?
|
||||
|
||||
// Whether to debug/trace HTTP requests to OCI registry.
|
||||
HTTPDebug http_debug = 5;
|
||||
|
||||
// Stream ID to use for HTTP logs (when logs are streamed to client).
|
||||
// When empty, logs are written to containerd logs.
|
||||
string logs_stream = 6;
|
||||
}
|
||||
|
||||
// AuthRequest is sent as a callback on a stream
|
||||
message AuthRequest {
|
||||
// host is the registry host
|
||||
string host = 1;
|
||||
|
||||
// reference is the namespace and repository name requested from the registry
|
||||
string reference = 2;
|
||||
|
||||
// wwwauthenticate is the HTTP WWW-Authenticate header values returned from the registry
|
||||
repeated string wwwauthenticate = 3;
|
||||
}
|
||||
|
||||
enum AuthType {
|
||||
NONE = 0;
|
||||
|
||||
// CREDENTIALS is used to exchange username/password for access token
|
||||
// using an oauth or "Docker Registry Token" server
|
||||
CREDENTIALS = 1;
|
||||
|
||||
// REFRESH is used to exchange secret for access token using an oauth
|
||||
// or "Docker Registry Token" server
|
||||
REFRESH = 2;
|
||||
|
||||
// HEADER is used to set the HTTP Authorization header to secret
|
||||
// directly for the registry.
|
||||
// Value should be `<auth-scheme> <authorization-parameters>`
|
||||
HEADER = 3;
|
||||
}
|
||||
|
||||
message AuthResponse {
|
||||
AuthType authType = 1;
|
||||
string secret = 2;
|
||||
string username = 3;
|
||||
google.protobuf.Timestamp expire_at = 4;
|
||||
// TODO: Stream error
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.types.transfer;
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/types/transfer";
|
||||
|
||||
message Data {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
message WindowUpdate {
|
||||
int32 update = 1;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package proto;
|
||||
option go_package = "github.com/containerd/continuity/proto;proto";
|
||||
|
||||
// Manifest specifies the entries in a container bundle, keyed and sorted by
|
||||
// path.
|
||||
message Manifest {
|
||||
repeated Resource resource = 1;
|
||||
}
|
||||
|
||||
message Resource {
|
||||
// Path specifies the path from the bundle root. If more than one
|
||||
// path is present, the entry may represent a hardlink, rather than using
|
||||
// a link target. The path format is operating system specific.
|
||||
repeated string path = 1;
|
||||
|
||||
// NOTE(stevvooe): Need to define clear precedence for user/group/uid/gid precedence.
|
||||
|
||||
// Uid specifies the user id for the resource.
|
||||
int64 uid = 2;
|
||||
|
||||
// Gid specifies the group id for the resource.
|
||||
int64 gid = 3;
|
||||
|
||||
// user and group are not currently used but their field numbers have been
|
||||
// reserved for future use. As such, they are marked as deprecated.
|
||||
string user = 4 [deprecated=true]; // "deprecated" stands for "reserved" here
|
||||
string group = 5 [deprecated=true]; // "deprecated" stands for "reserved" here
|
||||
|
||||
// Mode defines the file mode and permissions. We've used the same
|
||||
// bit-packing from Go's os package,
|
||||
// http://golang.org/pkg/os/#FileMode, since they've done the work of
|
||||
// creating a cross-platform layout.
|
||||
uint32 mode = 6;
|
||||
|
||||
// NOTE(stevvooe): Beyond here, we start defining type specific fields.
|
||||
|
||||
// Size specifies the size in bytes of the resource. This is only valid
|
||||
// for regular files.
|
||||
uint64 size = 7;
|
||||
|
||||
// Digest specifies the content digest of the target file. Only valid for
|
||||
// regular files. The strings are formatted in OCI style, i.e. <alg>:<encoded>.
|
||||
// For detailed information about the format, please refer to OCI Image Spec:
|
||||
// https://github.com/opencontainers/image-spec/blob/master/descriptor.md#digests-and-verification
|
||||
// The digests are sorted in lexical order and implementations may choose
|
||||
// which algorithms they prefer.
|
||||
repeated string digest = 8;
|
||||
|
||||
// Target defines the target of a hard or soft link. Absolute links start
|
||||
// with a slash and specify the resource relative to the bundle root.
|
||||
// Relative links do not start with a slash and are relative to the
|
||||
// resource path.
|
||||
string target = 9;
|
||||
|
||||
// Major specifies the major device number for character and block devices.
|
||||
uint64 major = 10;
|
||||
|
||||
// Minor specifies the minor device number for character and block devices.
|
||||
uint64 minor = 11;
|
||||
|
||||
// Xattr provides storage for extended attributes for the target resource.
|
||||
repeated XAttr xattr = 12;
|
||||
|
||||
// Ads stores one or more alternate data streams for the target resource.
|
||||
repeated ADSEntry ads = 13;
|
||||
|
||||
}
|
||||
|
||||
// XAttr encodes extended attributes for a resource.
|
||||
message XAttr {
|
||||
// Name specifies the attribute name.
|
||||
string name = 1;
|
||||
|
||||
// Data specifies the associated data for the attribute.
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
// ADSEntry encodes information for a Windows Alternate Data Stream.
|
||||
message ADSEntry {
|
||||
// Name specifices the stream name.
|
||||
string name = 1;
|
||||
|
||||
// Data specifies the stream data.
|
||||
// See also the description about the digest below.
|
||||
bytes data = 2;
|
||||
|
||||
// Digest is a CAS representation of the stream data.
|
||||
//
|
||||
// At least one of data or digest MUST be specified, and either one of them
|
||||
// SHOULD be specified.
|
||||
//
|
||||
// How to access the actual data using the digest is implementation-specific,
|
||||
// and implementations can choose not to implement digest.
|
||||
// So, digest SHOULD be used only when the stream data is large.
|
||||
string digest = 3;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ttrpc;
|
||||
|
||||
import "proto/status.proto";
|
||||
|
||||
option go_package = "github.com/containerd/ttrpc";
|
||||
|
||||
message Request {
|
||||
string service = 1;
|
||||
string method = 2;
|
||||
bytes payload = 3;
|
||||
int64 timeout_nano = 4;
|
||||
repeated KeyValue metadata = 5;
|
||||
}
|
||||
|
||||
message Response {
|
||||
Status status = 1;
|
||||
bytes payload = 2;
|
||||
}
|
||||
|
||||
message StringList {
|
||||
repeated string list = 1;
|
||||
}
|
||||
|
||||
message KeyValue {
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package ttrpc;
|
||||
|
||||
option go_package = "github.com/containerd/ttrpc/internal";
|
||||
|
||||
message TestPayload {
|
||||
string foo = 1;
|
||||
int64 deadline = 2;
|
||||
string metadata = 3;
|
||||
}
|
||||
|
||||
message EchoPayload {
|
||||
int64 seq = 1;
|
||||
string msg = 2;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2017 Google LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package configpb;
|
||||
|
||||
option go_package = "github.com/google/certificate-transparency-go/client/multilog/configpb";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
// TemporalLogConfig is a set of LogShardConfig messages, whose
|
||||
// time limits should be contiguous.
|
||||
message TemporalLogConfig {
|
||||
repeated LogShardConfig shard = 1;
|
||||
}
|
||||
|
||||
// LogShardConfig describes the acceptable date range for a single shard of a temporal
|
||||
// log.
|
||||
message LogShardConfig {
|
||||
string uri = 1;
|
||||
|
||||
// The log's public key in DER-encoded PKIX form.
|
||||
bytes public_key_der = 2;
|
||||
|
||||
// not_after_start defines the start of the range of acceptable NotAfter
|
||||
// values, inclusive.
|
||||
// Leaving this unset implies no lower bound to the range.
|
||||
google.protobuf.Timestamp not_after_start = 3;
|
||||
// not_after_limit defines the end of the range of acceptable NotAfter values,
|
||||
// exclusive.
|
||||
// Leaving this unset implies no upper bound to the range.
|
||||
google.protobuf.Timestamp not_after_limit = 4;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.gateway.protoc_gen_openapiv2.options;
|
||||
|
||||
import "google/protobuf/descriptor.proto";
|
||||
import "protoc-gen-openapiv2/options/openapiv2.proto";
|
||||
|
||||
option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options";
|
||||
|
||||
extend google.protobuf.FileOptions {
|
||||
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||
//
|
||||
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||
// different descriptor messages.
|
||||
Swagger openapiv2_swagger = 1042;
|
||||
}
|
||||
extend google.protobuf.MethodOptions {
|
||||
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||
//
|
||||
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||
// different descriptor messages.
|
||||
Operation openapiv2_operation = 1042;
|
||||
}
|
||||
extend google.protobuf.MessageOptions {
|
||||
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||
//
|
||||
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||
// different descriptor messages.
|
||||
Schema openapiv2_schema = 1042;
|
||||
}
|
||||
extend google.protobuf.EnumOptions {
|
||||
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||
//
|
||||
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||
// different descriptor messages.
|
||||
EnumSchema openapiv2_enum = 1042;
|
||||
}
|
||||
extend google.protobuf.ServiceOptions {
|
||||
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||
//
|
||||
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||
// different descriptor messages.
|
||||
Tag openapiv2_tag = 1042;
|
||||
}
|
||||
extend google.protobuf.FieldOptions {
|
||||
// ID assigned by protobuf-global-extension-registry@google.com for gRPC-Gateway project.
|
||||
//
|
||||
// All IDs are the same, as assigned. It is okay that they are the same, as they extend
|
||||
// different descriptor messages.
|
||||
JSONSchema openapiv2_field = 1042;
|
||||
}
|
||||
@@ -0,0 +1,762 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package grpc.gateway.protoc_gen_openapiv2.options;
|
||||
|
||||
import "google/protobuf/struct.proto";
|
||||
|
||||
option go_package = "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options";
|
||||
|
||||
// Scheme describes the schemes supported by the OpenAPI Swagger
|
||||
// and Operation objects.
|
||||
enum Scheme {
|
||||
UNKNOWN = 0;
|
||||
HTTP = 1;
|
||||
HTTPS = 2;
|
||||
WS = 3;
|
||||
WSS = 4;
|
||||
}
|
||||
|
||||
// `Swagger` is a representation of OpenAPI v2 specification's Swagger object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#swaggerObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
// info: {
|
||||
// title: "Echo API";
|
||||
// version: "1.0";
|
||||
// description: "";
|
||||
// contact: {
|
||||
// name: "gRPC-Gateway project";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||
// email: "none@example.com";
|
||||
// };
|
||||
// license: {
|
||||
// name: "BSD 3-Clause License";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE";
|
||||
// };
|
||||
// };
|
||||
// schemes: HTTPS;
|
||||
// consumes: "application/json";
|
||||
// produces: "application/json";
|
||||
// };
|
||||
//
|
||||
message Swagger {
|
||||
// Specifies the OpenAPI Specification version being used. It can be
|
||||
// used by the OpenAPI UI and other clients to interpret the API listing. The
|
||||
// value MUST be "2.0".
|
||||
string swagger = 1;
|
||||
// Provides metadata about the API. The metadata can be used by the
|
||||
// clients if needed.
|
||||
Info info = 2;
|
||||
// The host (name or ip) serving the API. This MUST be the host only and does
|
||||
// not include the scheme nor sub-paths. It MAY include a port. If the host is
|
||||
// not included, the host serving the documentation is to be used (including
|
||||
// the port). The host does not support path templating.
|
||||
string host = 3;
|
||||
// The base path on which the API is served, which is relative to the host. If
|
||||
// it is not included, the API is served directly under the host. The value
|
||||
// MUST start with a leading slash (/). The basePath does not support path
|
||||
// templating.
|
||||
// Note that using `base_path` does not change the endpoint paths that are
|
||||
// generated in the resulting OpenAPI file. If you wish to use `base_path`
|
||||
// with relatively generated OpenAPI paths, the `base_path` prefix must be
|
||||
// manually removed from your `google.api.http` paths and your code changed to
|
||||
// serve the API from the `base_path`.
|
||||
string base_path = 4;
|
||||
// The transfer protocol of the API. Values MUST be from the list: "http",
|
||||
// "https", "ws", "wss". If the schemes is not included, the default scheme to
|
||||
// be used is the one used to access the OpenAPI definition itself.
|
||||
repeated Scheme schemes = 5;
|
||||
// A list of MIME types the APIs can consume. This is global to all APIs but
|
||||
// can be overridden on specific API calls. Value MUST be as described under
|
||||
// Mime Types.
|
||||
repeated string consumes = 6;
|
||||
// A list of MIME types the APIs can produce. This is global to all APIs but
|
||||
// can be overridden on specific API calls. Value MUST be as described under
|
||||
// Mime Types.
|
||||
repeated string produces = 7;
|
||||
// field 8 is reserved for 'paths'.
|
||||
reserved 8;
|
||||
// field 9 is reserved for 'definitions', which at this time are already
|
||||
// exposed as and customizable as proto messages.
|
||||
reserved 9;
|
||||
// An object to hold responses that can be used across operations. This
|
||||
// property does not define global responses for all operations.
|
||||
map<string, Response> responses = 10;
|
||||
// Security scheme definitions that can be used across the specification.
|
||||
SecurityDefinitions security_definitions = 11;
|
||||
// A declaration of which security schemes are applied for the API as a whole.
|
||||
// The list of values describes alternative security schemes that can be used
|
||||
// (that is, there is a logical OR between the security requirements).
|
||||
// Individual operations can override this definition.
|
||||
repeated SecurityRequirement security = 12;
|
||||
// A list of tags for API documentation control. Tags can be used for logical
|
||||
// grouping of operations by resources or any other qualifier.
|
||||
repeated Tag tags = 13;
|
||||
// Additional external documentation.
|
||||
ExternalDocumentation external_docs = 14;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 15;
|
||||
}
|
||||
|
||||
// `Operation` is a representation of OpenAPI v2 specification's Operation object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#operationObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// service EchoService {
|
||||
// rpc Echo(SimpleMessage) returns (SimpleMessage) {
|
||||
// option (google.api.http) = {
|
||||
// get: "/v1/example/echo/{id}"
|
||||
// };
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
// summary: "Get a message.";
|
||||
// operation_id: "getMessage";
|
||||
// tags: "echo";
|
||||
// responses: {
|
||||
// key: "200"
|
||||
// value: {
|
||||
// description: "OK";
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
message Operation {
|
||||
// A list of tags for API documentation control. Tags can be used for logical
|
||||
// grouping of operations by resources or any other qualifier.
|
||||
repeated string tags = 1;
|
||||
// A short summary of what the operation does. For maximum readability in the
|
||||
// swagger-ui, this field SHOULD be less than 120 characters.
|
||||
string summary = 2;
|
||||
// A verbose explanation of the operation behavior. GFM syntax can be used for
|
||||
// rich text representation.
|
||||
string description = 3;
|
||||
// Additional external documentation for this operation.
|
||||
ExternalDocumentation external_docs = 4;
|
||||
// Unique string used to identify the operation. The id MUST be unique among
|
||||
// all operations described in the API. Tools and libraries MAY use the
|
||||
// operationId to uniquely identify an operation, therefore, it is recommended
|
||||
// to follow common programming naming conventions.
|
||||
string operation_id = 5;
|
||||
// A list of MIME types the operation can consume. This overrides the consumes
|
||||
// definition at the OpenAPI Object. An empty value MAY be used to clear the
|
||||
// global definition. Value MUST be as described under Mime Types.
|
||||
repeated string consumes = 6;
|
||||
// A list of MIME types the operation can produce. This overrides the produces
|
||||
// definition at the OpenAPI Object. An empty value MAY be used to clear the
|
||||
// global definition. Value MUST be as described under Mime Types.
|
||||
repeated string produces = 7;
|
||||
// field 8 is reserved for 'parameters'.
|
||||
reserved 8;
|
||||
// The list of possible responses as they are returned from executing this
|
||||
// operation.
|
||||
map<string, Response> responses = 9;
|
||||
// The transfer protocol for the operation. Values MUST be from the list:
|
||||
// "http", "https", "ws", "wss". The value overrides the OpenAPI Object
|
||||
// schemes definition.
|
||||
repeated Scheme schemes = 10;
|
||||
// Declares this operation to be deprecated. Usage of the declared operation
|
||||
// should be refrained. Default value is false.
|
||||
bool deprecated = 11;
|
||||
// A declaration of which security schemes are applied for this operation. The
|
||||
// list of values describes alternative security schemes that can be used
|
||||
// (that is, there is a logical OR between the security requirements). This
|
||||
// definition overrides any declared top-level security. To remove a top-level
|
||||
// security declaration, an empty array can be used.
|
||||
repeated SecurityRequirement security = 12;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 13;
|
||||
// Custom parameters such as HTTP request headers.
|
||||
// See: https://swagger.io/docs/specification/2-0/describing-parameters/
|
||||
// and https://swagger.io/specification/v2/#parameter-object.
|
||||
Parameters parameters = 14;
|
||||
}
|
||||
|
||||
// `Parameters` is a representation of OpenAPI v2 specification's parameters object.
|
||||
// Note: This technically breaks compatibility with the OpenAPI 2 definition structure as we only
|
||||
// allow header parameters to be set here since we do not want users specifying custom non-header
|
||||
// parameters beyond those inferred from the Protobuf schema.
|
||||
// See: https://swagger.io/specification/v2/#parameter-object
|
||||
message Parameters {
|
||||
// `Headers` is one or more HTTP header parameter.
|
||||
// See: https://swagger.io/docs/specification/2-0/describing-parameters/#header-parameters
|
||||
repeated HeaderParameter headers = 1;
|
||||
}
|
||||
|
||||
// `HeaderParameter` a HTTP header parameter.
|
||||
// See: https://swagger.io/specification/v2/#parameter-object
|
||||
message HeaderParameter {
|
||||
// `Type` is a supported HTTP header type.
|
||||
// See https://swagger.io/specification/v2/#parameterType.
|
||||
enum Type {
|
||||
UNKNOWN = 0;
|
||||
STRING = 1;
|
||||
NUMBER = 2;
|
||||
INTEGER = 3;
|
||||
BOOLEAN = 4;
|
||||
}
|
||||
|
||||
// `Name` is the header name.
|
||||
string name = 1;
|
||||
// `Description` is a short description of the header.
|
||||
string description = 2;
|
||||
// `Type` is the type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported.
|
||||
// See: https://swagger.io/specification/v2/#parameterType.
|
||||
Type type = 3;
|
||||
// `Format` The extending format for the previously mentioned type.
|
||||
string format = 4;
|
||||
// `Required` indicates if the header is optional
|
||||
bool required = 5;
|
||||
// field 6 is reserved for 'items', but in OpenAPI-specific way.
|
||||
reserved 6;
|
||||
// field 7 is reserved `Collection Format`. Determines the format of the array if type array is used.
|
||||
reserved 7;
|
||||
}
|
||||
|
||||
// `Header` is a representation of OpenAPI v2 specification's Header object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#headerObject
|
||||
//
|
||||
message Header {
|
||||
// `Description` is a short description of the header.
|
||||
string description = 1;
|
||||
// The type of the object. The value MUST be one of "string", "number", "integer", or "boolean". The "array" type is not supported.
|
||||
string type = 2;
|
||||
// `Format` The extending format for the previously mentioned type.
|
||||
string format = 3;
|
||||
// field 4 is reserved for 'items', but in OpenAPI-specific way.
|
||||
reserved 4;
|
||||
// field 5 is reserved `Collection Format` Determines the format of the array if type array is used.
|
||||
reserved 5;
|
||||
// `Default` Declares the value of the header that the server will use if none is provided.
|
||||
// See: https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2.
|
||||
// Unlike JSON Schema this value MUST conform to the defined type for the header.
|
||||
string default = 6;
|
||||
// field 7 is reserved for 'maximum'.
|
||||
reserved 7;
|
||||
// field 8 is reserved for 'exclusiveMaximum'.
|
||||
reserved 8;
|
||||
// field 9 is reserved for 'minimum'.
|
||||
reserved 9;
|
||||
// field 10 is reserved for 'exclusiveMinimum'.
|
||||
reserved 10;
|
||||
// field 11 is reserved for 'maxLength'.
|
||||
reserved 11;
|
||||
// field 12 is reserved for 'minLength'.
|
||||
reserved 12;
|
||||
// 'Pattern' See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.2.3.
|
||||
string pattern = 13;
|
||||
// field 14 is reserved for 'maxItems'.
|
||||
reserved 14;
|
||||
// field 15 is reserved for 'minItems'.
|
||||
reserved 15;
|
||||
// field 16 is reserved for 'uniqueItems'.
|
||||
reserved 16;
|
||||
// field 17 is reserved for 'enum'.
|
||||
reserved 17;
|
||||
// field 18 is reserved for 'multipleOf'.
|
||||
reserved 18;
|
||||
}
|
||||
|
||||
// `Response` is a representation of OpenAPI v2 specification's Response object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#responseObject
|
||||
//
|
||||
message Response {
|
||||
// `Description` is a short description of the response.
|
||||
// GFM syntax can be used for rich text representation.
|
||||
string description = 1;
|
||||
// `Schema` optionally defines the structure of the response.
|
||||
// If `Schema` is not provided, it means there is no content to the response.
|
||||
Schema schema = 2;
|
||||
// `Headers` A list of headers that are sent with the response.
|
||||
// `Header` name is expected to be a string in the canonical format of the MIME header key
|
||||
// See: https://golang.org/pkg/net/textproto/#CanonicalMIMEHeaderKey
|
||||
map<string, Header> headers = 3;
|
||||
// `Examples` gives per-mimetype response examples.
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#example-object
|
||||
map<string, string> examples = 4;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 5;
|
||||
}
|
||||
|
||||
// `Info` is a representation of OpenAPI v2 specification's Info object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#infoObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
// info: {
|
||||
// title: "Echo API";
|
||||
// version: "1.0";
|
||||
// description: "";
|
||||
// contact: {
|
||||
// name: "gRPC-Gateway project";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||
// email: "none@example.com";
|
||||
// };
|
||||
// license: {
|
||||
// name: "BSD 3-Clause License";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE";
|
||||
// };
|
||||
// };
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
message Info {
|
||||
// The title of the application.
|
||||
string title = 1;
|
||||
// A short description of the application. GFM syntax can be used for rich
|
||||
// text representation.
|
||||
string description = 2;
|
||||
// The Terms of Service for the API.
|
||||
string terms_of_service = 3;
|
||||
// The contact information for the exposed API.
|
||||
Contact contact = 4;
|
||||
// The license information for the exposed API.
|
||||
License license = 5;
|
||||
// Provides the version of the application API (not to be confused
|
||||
// with the specification version).
|
||||
string version = 6;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 7;
|
||||
}
|
||||
|
||||
// `Contact` is a representation of OpenAPI v2 specification's Contact object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#contactObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
// info: {
|
||||
// ...
|
||||
// contact: {
|
||||
// name: "gRPC-Gateway project";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||
// email: "none@example.com";
|
||||
// };
|
||||
// ...
|
||||
// };
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
message Contact {
|
||||
// The identifying name of the contact person/organization.
|
||||
string name = 1;
|
||||
// The URL pointing to the contact information. MUST be in the format of a
|
||||
// URL.
|
||||
string url = 2;
|
||||
// The email address of the contact person/organization. MUST be in the format
|
||||
// of an email address.
|
||||
string email = 3;
|
||||
}
|
||||
|
||||
// `License` is a representation of OpenAPI v2 specification's License object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#licenseObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
// info: {
|
||||
// ...
|
||||
// license: {
|
||||
// name: "BSD 3-Clause License";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway/blob/main/LICENSE";
|
||||
// };
|
||||
// ...
|
||||
// };
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
message License {
|
||||
// The license name used for the API.
|
||||
string name = 1;
|
||||
// A URL to the license used for the API. MUST be in the format of a URL.
|
||||
string url = 2;
|
||||
}
|
||||
|
||||
// `ExternalDocumentation` is a representation of OpenAPI v2 specification's
|
||||
// ExternalDocumentation object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#externalDocumentationObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
|
||||
// ...
|
||||
// external_docs: {
|
||||
// description: "More about gRPC-Gateway";
|
||||
// url: "https://github.com/grpc-ecosystem/grpc-gateway";
|
||||
// }
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
message ExternalDocumentation {
|
||||
// A short description of the target documentation. GFM syntax can be used for
|
||||
// rich text representation.
|
||||
string description = 1;
|
||||
// The URL for the target documentation. Value MUST be in the format
|
||||
// of a URL.
|
||||
string url = 2;
|
||||
}
|
||||
|
||||
// `Schema` is a representation of OpenAPI v2 specification's Schema object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||
//
|
||||
message Schema {
|
||||
JSONSchema json_schema = 1;
|
||||
// Adds support for polymorphism. The discriminator is the schema property
|
||||
// name that is used to differentiate between other schema that inherit this
|
||||
// schema. The property name used MUST be defined at this schema and it MUST
|
||||
// be in the required property list. When used, the value MUST be the name of
|
||||
// this schema or any schema that inherits it.
|
||||
string discriminator = 2;
|
||||
// Relevant only for Schema "properties" definitions. Declares the property as
|
||||
// "read only". This means that it MAY be sent as part of a response but MUST
|
||||
// NOT be sent as part of the request. Properties marked as readOnly being
|
||||
// true SHOULD NOT be in the required list of the defined schema. Default
|
||||
// value is false.
|
||||
bool read_only = 3;
|
||||
// field 4 is reserved for 'xml'.
|
||||
reserved 4;
|
||||
// Additional external documentation for this schema.
|
||||
ExternalDocumentation external_docs = 5;
|
||||
// A free-form property to include an example of an instance for this schema in JSON.
|
||||
// This is copied verbatim to the output.
|
||||
string example = 6;
|
||||
}
|
||||
|
||||
// `EnumSchema` is subset of fields from the OpenAPI v2 specification's Schema object.
|
||||
// Only fields that are applicable to Enums are included
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_enum) = {
|
||||
// ...
|
||||
// title: "MyEnum";
|
||||
// description:"This is my nice enum";
|
||||
// example: "ZERO";
|
||||
// required: true;
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
message EnumSchema {
|
||||
// A short description of the schema.
|
||||
string description = 1;
|
||||
string default = 2;
|
||||
// The title of the schema.
|
||||
string title = 3;
|
||||
bool required = 4;
|
||||
bool read_only = 5;
|
||||
// Additional external documentation for this schema.
|
||||
ExternalDocumentation external_docs = 6;
|
||||
string example = 7;
|
||||
// Ref is used to define an external reference to include in the message.
|
||||
// This could be a fully qualified proto message reference, and that type must
|
||||
// be imported into the protofile. If no message is identified, the Ref will
|
||||
// be used verbatim in the output.
|
||||
// For example:
|
||||
// `ref: ".google.protobuf.Timestamp"`.
|
||||
string ref = 8;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 9;
|
||||
}
|
||||
|
||||
// `JSONSchema` represents properties from JSON Schema taken, and as used, in
|
||||
// the OpenAPI v2 spec.
|
||||
//
|
||||
// This includes changes made by OpenAPI v2.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||
//
|
||||
// See also: https://cswr.github.io/JsonSchema/spec/basic_types/,
|
||||
// https://github.com/json-schema-org/json-schema-spec/blob/master/schema.json
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// message SimpleMessage {
|
||||
// option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
|
||||
// json_schema: {
|
||||
// title: "SimpleMessage"
|
||||
// description: "A simple message."
|
||||
// required: ["id"]
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// // Id represents the message identifier.
|
||||
// string id = 1; [
|
||||
// (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = {
|
||||
// description: "The unique identifier of the simple message."
|
||||
// }];
|
||||
// }
|
||||
//
|
||||
message JSONSchema {
|
||||
// field 1 is reserved for '$id', omitted from OpenAPI v2.
|
||||
reserved 1;
|
||||
// field 2 is reserved for '$schema', omitted from OpenAPI v2.
|
||||
reserved 2;
|
||||
// Ref is used to define an external reference to include in the message.
|
||||
// This could be a fully qualified proto message reference, and that type must
|
||||
// be imported into the protofile. If no message is identified, the Ref will
|
||||
// be used verbatim in the output.
|
||||
// For example:
|
||||
// `ref: ".google.protobuf.Timestamp"`.
|
||||
string ref = 3;
|
||||
// field 4 is reserved for '$comment', omitted from OpenAPI v2.
|
||||
reserved 4;
|
||||
// The title of the schema.
|
||||
string title = 5;
|
||||
// A short description of the schema.
|
||||
string description = 6;
|
||||
string default = 7;
|
||||
bool read_only = 8;
|
||||
// A free-form property to include a JSON example of this field. This is copied
|
||||
// verbatim to the output swagger.json. Quotes must be escaped.
|
||||
// This property is the same for 2.0 and 3.0.0 https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/3.0.0.md#schemaObject https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#schemaObject
|
||||
string example = 9;
|
||||
double multiple_of = 10;
|
||||
// Maximum represents an inclusive upper limit for a numeric instance. The
|
||||
// value of MUST be a number,
|
||||
double maximum = 11;
|
||||
bool exclusive_maximum = 12;
|
||||
// minimum represents an inclusive lower limit for a numeric instance. The
|
||||
// value of MUST be a number,
|
||||
double minimum = 13;
|
||||
bool exclusive_minimum = 14;
|
||||
uint64 max_length = 15;
|
||||
uint64 min_length = 16;
|
||||
string pattern = 17;
|
||||
// field 18 is reserved for 'additionalItems', omitted from OpenAPI v2.
|
||||
reserved 18;
|
||||
// field 19 is reserved for 'items', but in OpenAPI-specific way.
|
||||
// TODO(ivucica): add 'items'?
|
||||
reserved 19;
|
||||
uint64 max_items = 20;
|
||||
uint64 min_items = 21;
|
||||
bool unique_items = 22;
|
||||
// field 23 is reserved for 'contains', omitted from OpenAPI v2.
|
||||
reserved 23;
|
||||
uint64 max_properties = 24;
|
||||
uint64 min_properties = 25;
|
||||
repeated string required = 26;
|
||||
// field 27 is reserved for 'additionalProperties', but in OpenAPI-specific
|
||||
// way. TODO(ivucica): add 'additionalProperties'?
|
||||
reserved 27;
|
||||
// field 28 is reserved for 'definitions', omitted from OpenAPI v2.
|
||||
reserved 28;
|
||||
// field 29 is reserved for 'properties', but in OpenAPI-specific way.
|
||||
// TODO(ivucica): add 'additionalProperties'?
|
||||
reserved 29;
|
||||
// following fields are reserved, as the properties have been omitted from
|
||||
// OpenAPI v2:
|
||||
// patternProperties, dependencies, propertyNames, const
|
||||
reserved 30 to 33;
|
||||
// Items in 'array' must be unique.
|
||||
repeated string array = 34;
|
||||
|
||||
enum JSONSchemaSimpleTypes {
|
||||
UNKNOWN = 0;
|
||||
ARRAY = 1;
|
||||
BOOLEAN = 2;
|
||||
INTEGER = 3;
|
||||
NULL = 4;
|
||||
NUMBER = 5;
|
||||
OBJECT = 6;
|
||||
STRING = 7;
|
||||
}
|
||||
|
||||
repeated JSONSchemaSimpleTypes type = 35;
|
||||
// `Format`
|
||||
string format = 36;
|
||||
// following fields are reserved, as the properties have been omitted from
|
||||
// OpenAPI v2: contentMediaType, contentEncoding, if, then, else
|
||||
reserved 37 to 41;
|
||||
// field 42 is reserved for 'allOf', but in OpenAPI-specific way.
|
||||
// TODO(ivucica): add 'allOf'?
|
||||
reserved 42;
|
||||
// following fields are reserved, as the properties have been omitted from
|
||||
// OpenAPI v2:
|
||||
// anyOf, oneOf, not
|
||||
reserved 43 to 45;
|
||||
// Items in `enum` must be unique https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-5.5.1
|
||||
repeated string enum = 46;
|
||||
|
||||
// Additional field level properties used when generating the OpenAPI v2 file.
|
||||
FieldConfiguration field_configuration = 1001;
|
||||
|
||||
// 'FieldConfiguration' provides additional field level properties used when generating the OpenAPI v2 file.
|
||||
// These properties are not defined by OpenAPIv2, but they are used to control the generation.
|
||||
message FieldConfiguration {
|
||||
// Alternative parameter name when used as path parameter. If set, this will
|
||||
// be used as the complete parameter name when this field is used as a path
|
||||
// parameter. Use this to avoid having auto generated path parameter names
|
||||
// for overlapping paths.
|
||||
string path_param_name = 47;
|
||||
// Declares this field to be deprecated. Allows for the generated OpenAPI
|
||||
// parameter to be marked as deprecated without affecting the proto field.
|
||||
bool deprecated = 49;
|
||||
}
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 48;
|
||||
}
|
||||
|
||||
// `Tag` is a representation of OpenAPI v2 specification's Tag object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#tagObject
|
||||
//
|
||||
message Tag {
|
||||
// The name of the tag. Use it to allow override of the name of a
|
||||
// global Tag object, then use that name to reference the tag throughout the
|
||||
// OpenAPI file.
|
||||
string name = 1;
|
||||
// A short description for the tag. GFM syntax can be used for rich text
|
||||
// representation.
|
||||
string description = 2;
|
||||
// Additional external documentation for this tag.
|
||||
ExternalDocumentation external_docs = 3;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 4;
|
||||
}
|
||||
|
||||
// `SecurityDefinitions` is a representation of OpenAPI v2 specification's
|
||||
// Security Definitions object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityDefinitionsObject
|
||||
//
|
||||
// A declaration of the security schemes available to be used in the
|
||||
// specification. This does not enforce the security schemes on the operations
|
||||
// and only serves to provide the relevant details for each scheme.
|
||||
message SecurityDefinitions {
|
||||
// A single security scheme definition, mapping a "name" to the scheme it
|
||||
// defines.
|
||||
map<string, SecurityScheme> security = 1;
|
||||
}
|
||||
|
||||
// `SecurityScheme` is a representation of OpenAPI v2 specification's
|
||||
// Security Scheme object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securitySchemeObject
|
||||
//
|
||||
// Allows the definition of a security scheme that can be used by the
|
||||
// operations. Supported schemes are basic authentication, an API key (either as
|
||||
// a header or as a query parameter) and OAuth2's common flows (implicit,
|
||||
// password, application and access code).
|
||||
message SecurityScheme {
|
||||
// The type of the security scheme. Valid values are "basic",
|
||||
// "apiKey" or "oauth2".
|
||||
enum Type {
|
||||
TYPE_INVALID = 0;
|
||||
TYPE_BASIC = 1;
|
||||
TYPE_API_KEY = 2;
|
||||
TYPE_OAUTH2 = 3;
|
||||
}
|
||||
|
||||
// The location of the API key. Valid values are "query" or "header".
|
||||
enum In {
|
||||
IN_INVALID = 0;
|
||||
IN_QUERY = 1;
|
||||
IN_HEADER = 2;
|
||||
}
|
||||
|
||||
// The flow used by the OAuth2 security scheme. Valid values are
|
||||
// "implicit", "password", "application" or "accessCode".
|
||||
enum Flow {
|
||||
FLOW_INVALID = 0;
|
||||
FLOW_IMPLICIT = 1;
|
||||
FLOW_PASSWORD = 2;
|
||||
FLOW_APPLICATION = 3;
|
||||
FLOW_ACCESS_CODE = 4;
|
||||
}
|
||||
|
||||
// The type of the security scheme. Valid values are "basic",
|
||||
// "apiKey" or "oauth2".
|
||||
Type type = 1;
|
||||
// A short description for security scheme.
|
||||
string description = 2;
|
||||
// The name of the header or query parameter to be used.
|
||||
// Valid for apiKey.
|
||||
string name = 3;
|
||||
// The location of the API key. Valid values are "query" or
|
||||
// "header".
|
||||
// Valid for apiKey.
|
||||
In in = 4;
|
||||
// The flow used by the OAuth2 security scheme. Valid values are
|
||||
// "implicit", "password", "application" or "accessCode".
|
||||
// Valid for oauth2.
|
||||
Flow flow = 5;
|
||||
// The authorization URL to be used for this flow. This SHOULD be in
|
||||
// the form of a URL.
|
||||
// Valid for oauth2/implicit and oauth2/accessCode.
|
||||
string authorization_url = 6;
|
||||
// The token URL to be used for this flow. This SHOULD be in the
|
||||
// form of a URL.
|
||||
// Valid for oauth2/password, oauth2/application and oauth2/accessCode.
|
||||
string token_url = 7;
|
||||
// The available scopes for the OAuth2 security scheme.
|
||||
// Valid for oauth2.
|
||||
Scopes scopes = 8;
|
||||
// Custom properties that start with "x-" such as "x-foo" used to describe
|
||||
// extra functionality that is not covered by the standard OpenAPI Specification.
|
||||
// See: https://swagger.io/docs/specification/2-0/swagger-extensions/
|
||||
map<string, google.protobuf.Value> extensions = 9;
|
||||
}
|
||||
|
||||
// `SecurityRequirement` is a representation of OpenAPI v2 specification's
|
||||
// Security Requirement object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#securityRequirementObject
|
||||
//
|
||||
// Lists the required security schemes to execute this operation. The object can
|
||||
// have multiple security schemes declared in it which are all required (that
|
||||
// is, there is a logical AND between the schemes).
|
||||
//
|
||||
// The name used for each property MUST correspond to a security scheme
|
||||
// declared in the Security Definitions.
|
||||
message SecurityRequirement {
|
||||
// If the security scheme is of type "oauth2", then the value is a list of
|
||||
// scope names required for the execution. For other security scheme types,
|
||||
// the array MUST be empty.
|
||||
message SecurityRequirementValue {
|
||||
repeated string scope = 1;
|
||||
}
|
||||
// Each name must correspond to a security scheme which is declared in
|
||||
// the Security Definitions. If the security scheme is of type "oauth2",
|
||||
// then the value is a list of scope names required for the execution.
|
||||
// For other security scheme types, the array MUST be empty.
|
||||
map<string, SecurityRequirementValue> security_requirement = 1;
|
||||
}
|
||||
|
||||
// `Scopes` is a representation of OpenAPI v2 specification's Scopes object.
|
||||
//
|
||||
// See: https://github.com/OAI/OpenAPI-Specification/blob/3.0.0/versions/2.0.md#scopesObject
|
||||
//
|
||||
// Lists the available scopes for an OAuth2 security scheme.
|
||||
message Scopes {
|
||||
// Maps between a name of a scope to a short description of it (as the value
|
||||
// of the property).
|
||||
map<string, string> scope = 1;
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/api/services/control;moby_buildkit_v1";
|
||||
|
||||
// import "github.com/containerd/containerd/api/types/descriptor.proto";
|
||||
import "github.com/moby/buildkit/api/types/worker.proto";
|
||||
import "github.com/moby/buildkit/solver/pb/ops.proto";
|
||||
import "github.com/moby/buildkit/sourcepolicy/pb/policy.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/rpc/status.proto";
|
||||
|
||||
service Control {
|
||||
rpc DiskUsage(DiskUsageRequest) returns (DiskUsageResponse);
|
||||
rpc Prune(PruneRequest) returns (stream UsageRecord);
|
||||
rpc Solve(SolveRequest) returns (SolveResponse);
|
||||
rpc Status(StatusRequest) returns (stream StatusResponse);
|
||||
rpc Session(stream BytesMessage) returns (stream BytesMessage);
|
||||
rpc ListWorkers(ListWorkersRequest) returns (ListWorkersResponse);
|
||||
rpc Info(InfoRequest) returns (InfoResponse);
|
||||
|
||||
rpc ListenBuildHistory(BuildHistoryRequest) returns (stream BuildHistoryEvent);
|
||||
rpc UpdateBuildHistory(UpdateBuildHistoryRequest) returns (UpdateBuildHistoryResponse);
|
||||
}
|
||||
|
||||
message PruneRequest {
|
||||
repeated string filter = 1;
|
||||
bool all = 2;
|
||||
int64 keepDuration = 3;
|
||||
|
||||
int64 reservedSpace = 4;
|
||||
int64 maxUsedSpace = 5;
|
||||
int64 minFreeSpace = 6;
|
||||
}
|
||||
|
||||
message DiskUsageRequest {
|
||||
repeated string filter = 1;
|
||||
int64 ageLimit = 2;
|
||||
}
|
||||
|
||||
message DiskUsageResponse {
|
||||
repeated UsageRecord record = 1;
|
||||
}
|
||||
|
||||
message UsageRecord {
|
||||
string ID = 1;
|
||||
bool Mutable = 2;
|
||||
bool InUse = 3;
|
||||
int64 Size = 4;
|
||||
string Parent = 5 [deprecated=true];
|
||||
google.protobuf.Timestamp CreatedAt = 6;
|
||||
google.protobuf.Timestamp LastUsedAt = 7;
|
||||
int64 UsageCount = 8;
|
||||
string Description = 9;
|
||||
string RecordType = 10;
|
||||
bool Shared = 11;
|
||||
repeated string Parents = 12;
|
||||
}
|
||||
|
||||
message SolveRequest {
|
||||
string Ref = 1;
|
||||
pb.Definition Definition = 2;
|
||||
// ExporterDeprecated and ExporterAttrsDeprecated are deprecated in favor
|
||||
// of the new Exporters. If these fields are set, then they will be
|
||||
// appended to the Exporters field if Exporters was not explicitly set.
|
||||
string ExporterDeprecated = 3;
|
||||
map<string, string> ExporterAttrsDeprecated = 4;
|
||||
string Session = 5;
|
||||
string Frontend = 6;
|
||||
map<string, string> FrontendAttrs = 7;
|
||||
CacheOptions Cache = 8;
|
||||
repeated string Entitlements = 9;
|
||||
map<string, pb.Definition> FrontendInputs = 10;
|
||||
bool Internal = 11; // Internal builds are not recorded in build history
|
||||
moby.buildkit.v1.sourcepolicy.Policy SourcePolicy = 12;
|
||||
repeated Exporter Exporters = 13;
|
||||
bool EnableSessionExporter = 14;
|
||||
string SourcePolicySession = 15;
|
||||
}
|
||||
|
||||
message CacheOptions {
|
||||
// ExportRefDeprecated is deprecated in favor or the new Exports since BuildKit v0.4.0.
|
||||
// When ExportRefDeprecated is set, the solver appends
|
||||
// {.Type = "registry", .Attrs = ExportAttrs.add("ref", ExportRef)}
|
||||
// to Exports for compatibility. (planned to be removed)
|
||||
string ExportRefDeprecated = 1;
|
||||
// ImportRefsDeprecated is deprecated in favor or the new Imports since BuildKit v0.4.0.
|
||||
// When ImportRefsDeprecated is set, the solver appends
|
||||
// {.Type = "registry", .Attrs = {"ref": importRef}}
|
||||
// for each of the ImportRefs entry to Imports for compatibility. (planned to be removed)
|
||||
repeated string ImportRefsDeprecated = 2;
|
||||
// ExportAttrsDeprecated is deprecated since BuildKit v0.4.0.
|
||||
// See the description of ExportRefDeprecated.
|
||||
map<string, string> ExportAttrsDeprecated = 3;
|
||||
// Exports was introduced in BuildKit v0.4.0.
|
||||
repeated CacheOptionsEntry Exports = 4;
|
||||
// Imports was introduced in BuildKit v0.4.0.
|
||||
repeated CacheOptionsEntry Imports = 5;
|
||||
}
|
||||
|
||||
message CacheOptionsEntry {
|
||||
// Type is like "registry" or "local"
|
||||
string Type = 1;
|
||||
// Attrs are like mode=(min,max), ref=example.com:5000/foo/bar .
|
||||
// See cache importer/exporter implementations' documentation.
|
||||
map<string, string> Attrs = 2;
|
||||
}
|
||||
|
||||
message SolveResponse {
|
||||
map<string, string> ExporterResponse = 1;
|
||||
}
|
||||
|
||||
message StatusRequest {
|
||||
string Ref = 1;
|
||||
}
|
||||
|
||||
message StatusResponse {
|
||||
repeated Vertex vertexes = 1;
|
||||
repeated VertexStatus statuses = 2;
|
||||
repeated VertexLog logs = 3;
|
||||
repeated VertexWarning warnings = 4;
|
||||
}
|
||||
|
||||
message Vertex {
|
||||
string digest = 1;
|
||||
repeated string inputs = 2;
|
||||
string name = 3;
|
||||
bool cached = 4;
|
||||
google.protobuf.Timestamp started = 5;
|
||||
google.protobuf.Timestamp completed = 6;
|
||||
string error = 7; // typed errors?
|
||||
pb.ProgressGroup progressGroup = 8;
|
||||
}
|
||||
|
||||
message VertexStatus {
|
||||
string ID = 1;
|
||||
string vertex = 2;
|
||||
string name = 3;
|
||||
int64 current = 4;
|
||||
int64 total = 5;
|
||||
google.protobuf.Timestamp timestamp = 6;
|
||||
google.protobuf.Timestamp started = 7;
|
||||
google.protobuf.Timestamp completed = 8;
|
||||
}
|
||||
|
||||
message VertexLog {
|
||||
string vertex = 1;
|
||||
google.protobuf.Timestamp timestamp = 2;
|
||||
int64 stream = 3;
|
||||
bytes msg = 4;
|
||||
}
|
||||
|
||||
message VertexWarning {
|
||||
string vertex = 1;
|
||||
int64 level = 2;
|
||||
bytes short = 3;
|
||||
repeated bytes detail = 4;
|
||||
string url = 5;
|
||||
pb.SourceInfo info = 6;
|
||||
repeated pb.Range ranges = 7;
|
||||
}
|
||||
|
||||
message BytesMessage {
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
message ListWorkersRequest {
|
||||
repeated string filter = 1; // containerd style
|
||||
}
|
||||
|
||||
message ListWorkersResponse {
|
||||
repeated moby.buildkit.v1.types.WorkerRecord record = 1;
|
||||
}
|
||||
|
||||
message InfoRequest {}
|
||||
|
||||
message InfoResponse {
|
||||
moby.buildkit.v1.types.BuildkitVersion buildkitVersion = 1;
|
||||
}
|
||||
|
||||
message BuildHistoryRequest {
|
||||
bool ActiveOnly = 1;
|
||||
string Ref = 2;
|
||||
bool EarlyExit = 3;
|
||||
repeated string Filter = 4;
|
||||
int32 Limit = 5;
|
||||
}
|
||||
|
||||
enum BuildHistoryEventType {
|
||||
STARTED = 0;
|
||||
COMPLETE = 1;
|
||||
DELETED = 2;
|
||||
}
|
||||
|
||||
message BuildHistoryEvent {
|
||||
BuildHistoryEventType type = 1;
|
||||
BuildHistoryRecord record = 2;
|
||||
}
|
||||
|
||||
message BuildHistoryRecord {
|
||||
string Ref = 1;
|
||||
string Frontend = 2;
|
||||
map<string, string> FrontendAttrs = 3;
|
||||
repeated Exporter Exporters = 4;
|
||||
google.rpc.Status error = 5;
|
||||
google.protobuf.Timestamp CreatedAt = 6;
|
||||
google.protobuf.Timestamp CompletedAt = 7;
|
||||
Descriptor logs = 8;
|
||||
map<string, string> ExporterResponse = 9;
|
||||
BuildResultInfo Result = 10;
|
||||
map<string, BuildResultInfo> Results = 11;
|
||||
int32 Generation = 12;
|
||||
Descriptor trace = 13;
|
||||
bool pinned = 14;
|
||||
int32 numCachedSteps = 15;
|
||||
int32 numTotalSteps = 16;
|
||||
int32 numCompletedSteps = 17;
|
||||
Descriptor externalError = 18;
|
||||
int32 numWarnings = 19;
|
||||
// TODO: tags
|
||||
// TODO: unclipped logs
|
||||
}
|
||||
|
||||
message UpdateBuildHistoryRequest {
|
||||
string Ref = 1;
|
||||
bool Pinned = 2;
|
||||
bool Delete = 3;
|
||||
bool Finalize = 4;
|
||||
}
|
||||
|
||||
message UpdateBuildHistoryResponse {}
|
||||
|
||||
message Descriptor {
|
||||
string media_type = 1;
|
||||
string digest = 2;
|
||||
int64 size = 3;
|
||||
map<string, string> annotations = 5;
|
||||
}
|
||||
|
||||
message BuildResultInfo {
|
||||
Descriptor ResultDeprecated = 1;
|
||||
repeated Descriptor Attestations = 2;
|
||||
map<int64, Descriptor> Results = 3;
|
||||
}
|
||||
|
||||
// Exporter describes the output exporter
|
||||
message Exporter {
|
||||
// Type identifies the exporter
|
||||
string Type = 1;
|
||||
// Attrs specifies exporter configuration
|
||||
map<string, string> Attrs = 2;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.v1.types;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/api/types;moby_buildkit_v1_types";
|
||||
|
||||
import "github.com/moby/buildkit/solver/pb/ops.proto";
|
||||
|
||||
message WorkerRecord {
|
||||
string ID = 1;
|
||||
map<string, string> Labels = 2;
|
||||
repeated pb.Platform platforms = 3;
|
||||
repeated GCPolicy GCPolicy = 4;
|
||||
BuildkitVersion BuildkitVersion = 5;
|
||||
repeated CDIDevice CDIDevices = 6;
|
||||
}
|
||||
|
||||
message GCPolicy {
|
||||
bool all = 1;
|
||||
int64 keepDuration = 2;
|
||||
repeated string filters = 4;
|
||||
|
||||
// reservedSpace was renamed from freeBytes
|
||||
int64 reservedSpace = 3;
|
||||
int64 maxUsedSpace = 5;
|
||||
int64 minFreeSpace = 6;
|
||||
}
|
||||
|
||||
message BuildkitVersion {
|
||||
string package = 1;
|
||||
string version = 2;
|
||||
string revision = 3;
|
||||
}
|
||||
|
||||
message CDIDevice {
|
||||
string Name = 1;
|
||||
bool AutoAllow = 2;
|
||||
map<string, string> Annotations = 3;
|
||||
bool OnDemand = 4;
|
||||
}
|
||||
27
wfe-buildkit-protos/proto/github.com/moby/buildkit/cache/contenthash/checksum.proto
vendored
Normal file
27
wfe-buildkit-protos/proto/github.com/moby/buildkit/cache/contenthash/checksum.proto
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package contenthash;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/cache/contenthash";
|
||||
|
||||
enum CacheRecordType {
|
||||
FILE = 0;
|
||||
DIR = 1;
|
||||
DIR_HEADER = 2;
|
||||
SYMLINK = 3;
|
||||
}
|
||||
|
||||
message CacheRecord {
|
||||
string digest = 1;
|
||||
CacheRecordType type = 2;
|
||||
string linkname = 3;
|
||||
}
|
||||
|
||||
message CacheRecordWithPath {
|
||||
string path = 1;
|
||||
CacheRecord record = 2;
|
||||
}
|
||||
|
||||
message CacheRecords {
|
||||
repeated CacheRecordWithPath paths = 1;
|
||||
}
|
||||
@@ -0,0 +1,407 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.v1.frontend;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/frontend/gateway/pb;moby_buildkit_v1_frontend";
|
||||
|
||||
import "github.com/moby/buildkit/api/types/worker.proto";
|
||||
import "github.com/moby/buildkit/solver/pb/ops.proto";
|
||||
import "github.com/moby/buildkit/sourcepolicy/pb/policy.proto";
|
||||
import "github.com/moby/buildkit/util/apicaps/pb/caps.proto";
|
||||
import "github.com/tonistiigi/fsutil/types/stat.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/rpc/status.proto";
|
||||
|
||||
service LLBBridge {
|
||||
// apicaps:CapResolveImage
|
||||
rpc ResolveImageConfig(ResolveImageConfigRequest) returns (ResolveImageConfigResponse);
|
||||
// apicaps:CapSourceMetaResolver
|
||||
rpc ResolveSourceMeta(ResolveSourceMetaRequest) returns (ResolveSourceMetaResponse);
|
||||
// apicaps:CapSolveBase
|
||||
rpc Solve(SolveRequest) returns (SolveResponse);
|
||||
// apicaps:CapReadFile
|
||||
rpc ReadFile(ReadFileRequest) returns (ReadFileResponse);
|
||||
// apicaps:CapReadDir
|
||||
rpc ReadDir(ReadDirRequest) returns (ReadDirResponse);
|
||||
// apicaps:CapStatFile
|
||||
rpc StatFile(StatFileRequest) returns (StatFileResponse);
|
||||
// apicaps:CapGatewayEvaluate
|
||||
rpc Evaluate(EvaluateRequest) returns (EvaluateResponse);
|
||||
rpc Ping(PingRequest) returns (PongResponse);
|
||||
rpc Return(ReturnRequest) returns (ReturnResponse);
|
||||
// apicaps:CapFrontendInputs
|
||||
rpc Inputs(InputsRequest) returns (InputsResponse);
|
||||
|
||||
rpc NewContainer(NewContainerRequest) returns (NewContainerResponse);
|
||||
rpc ReleaseContainer(ReleaseContainerRequest) returns (ReleaseContainerResponse);
|
||||
rpc ExecProcess(stream ExecMessage) returns (stream ExecMessage);
|
||||
|
||||
// apicaps:CapGatewayExecFilesystem
|
||||
rpc ReadFileContainer(ReadFileRequest) returns (ReadFileResponse);
|
||||
rpc ReadDirContainer(ReadDirRequest) returns (ReadDirResponse);
|
||||
rpc StatFileContainer(StatFileRequest) returns (StatFileResponse);
|
||||
|
||||
// apicaps:CapGatewayWarnings
|
||||
rpc Warn(WarnRequest) returns (WarnResponse);
|
||||
}
|
||||
|
||||
message Result {
|
||||
oneof result {
|
||||
// Deprecated non-array refs.
|
||||
string refDeprecated = 1;
|
||||
RefMapDeprecated refsDeprecated = 2;
|
||||
|
||||
Ref ref = 3;
|
||||
RefMap refs = 4;
|
||||
}
|
||||
map<string, bytes> metadata = 10;
|
||||
// 11 was used during development and is reserved for old attestation format
|
||||
map<string, Attestations> attestations = 12;
|
||||
}
|
||||
|
||||
message RefMapDeprecated {
|
||||
map<string, string> refs = 1;
|
||||
}
|
||||
|
||||
message Ref {
|
||||
string id = 1;
|
||||
pb.Definition def = 2;
|
||||
}
|
||||
|
||||
message RefMap {
|
||||
map<string, Ref> refs = 1;
|
||||
}
|
||||
|
||||
message Attestations {
|
||||
repeated Attestation attestation = 1;
|
||||
}
|
||||
|
||||
message Attestation {
|
||||
AttestationKind kind = 1;
|
||||
map<string, bytes> metadata = 2;
|
||||
|
||||
Ref ref = 3;
|
||||
string path = 4;
|
||||
string inTotoPredicateType = 5;
|
||||
repeated InTotoSubject inTotoSubjects = 6;
|
||||
}
|
||||
|
||||
enum AttestationKind {
|
||||
InToto = 0;
|
||||
Bundle = 1;
|
||||
}
|
||||
|
||||
message InTotoSubject {
|
||||
InTotoSubjectKind kind = 1;
|
||||
|
||||
repeated string digest = 2;
|
||||
string name = 3;
|
||||
}
|
||||
|
||||
enum InTotoSubjectKind {
|
||||
Self = 0;
|
||||
Raw = 1;
|
||||
}
|
||||
|
||||
message ReturnRequest {
|
||||
Result result = 1;
|
||||
google.rpc.Status error = 2;
|
||||
}
|
||||
|
||||
message ReturnResponse {
|
||||
}
|
||||
|
||||
message InputsRequest {
|
||||
}
|
||||
|
||||
message InputsResponse {
|
||||
map<string, pb.Definition> Definitions = 1;
|
||||
}
|
||||
|
||||
message ResolveImageConfigRequest {
|
||||
string Ref = 1;
|
||||
pb.Platform Platform = 2;
|
||||
string ResolveMode = 3;
|
||||
string LogName = 4;
|
||||
int32 ResolverType = 5;
|
||||
string SessionID = 6;
|
||||
string StoreID = 7;
|
||||
repeated moby.buildkit.v1.sourcepolicy.Policy SourcePolicies = 8;
|
||||
}
|
||||
|
||||
message ResolveImageConfigResponse {
|
||||
string Digest = 1;
|
||||
bytes Config = 2;
|
||||
string Ref = 3;
|
||||
}
|
||||
|
||||
message ResolveSourceMetaRequest {
|
||||
pb.SourceOp Source = 1;
|
||||
pb.Platform Platform = 2;
|
||||
string LogName = 3;
|
||||
string ResolveMode = 4;
|
||||
ResolveSourceGitRequest Git = 5;
|
||||
ResolveSourceImageRequest Image = 6;
|
||||
ResolveSourceHTTPRequest HTTP = 7;
|
||||
repeated moby.buildkit.v1.sourcepolicy.Policy SourcePolicies = 8;
|
||||
}
|
||||
|
||||
message ResolveSourceMetaResponse {
|
||||
pb.SourceOp Source = 1;
|
||||
ResolveSourceImageResponse Image = 2;
|
||||
ResolveSourceGitResponse Git = 3;
|
||||
ResolveSourceHTTPResponse HTTP = 4;
|
||||
}
|
||||
|
||||
message ResolveSourceImageRequest {
|
||||
bool NoConfig = 1;
|
||||
bool AttestationChain = 2;
|
||||
repeated string ResolveAttestations = 3;
|
||||
}
|
||||
|
||||
message AttestationChain {
|
||||
string Root = 1;
|
||||
string ImageManifest = 2;
|
||||
string AttestationManifest = 3;
|
||||
repeated string SignatureManifests = 4;
|
||||
map<string, Blob> Blobs = 5;
|
||||
}
|
||||
|
||||
message ResolveSourceImageResponse {
|
||||
string Digest = 1;
|
||||
bytes Config = 2;
|
||||
AttestationChain AttestationChain = 3;
|
||||
}
|
||||
|
||||
message ResolveSourceGitRequest {
|
||||
// Return full commit and tag object bytes.
|
||||
bool ReturnObject = 1;
|
||||
}
|
||||
|
||||
message ResolveSourceGitResponse {
|
||||
string Checksum = 1;
|
||||
string Ref = 2;
|
||||
string CommitChecksum = 3;
|
||||
bytes CommitObject = 4;
|
||||
bytes TagObject = 5;
|
||||
}
|
||||
|
||||
message ResolveSourceHTTPResponse {
|
||||
string Checksum = 1;
|
||||
string Filename = 2;
|
||||
google.protobuf.Timestamp LastModified = 3;
|
||||
ChecksumResponse ChecksumResponse = 4;
|
||||
}
|
||||
|
||||
message ResolveSourceHTTPRequest {
|
||||
ChecksumRequest ChecksumRequest = 1;
|
||||
}
|
||||
|
||||
message ChecksumRequest {
|
||||
enum ChecksumAlgo {
|
||||
CHECKSUM_ALGO_SHA256 = 0;
|
||||
CHECKSUM_ALGO_SHA384 = 1;
|
||||
CHECKSUM_ALGO_SHA512 = 2;
|
||||
}
|
||||
ChecksumAlgo Algo = 1;
|
||||
bytes Suffix = 2;
|
||||
}
|
||||
|
||||
message ChecksumResponse {
|
||||
string Digest = 1;
|
||||
bytes Suffix = 2;
|
||||
}
|
||||
|
||||
message SolveRequest {
|
||||
pb.Definition Definition = 1;
|
||||
string Frontend = 2;
|
||||
map<string, string> FrontendOpt = 3;
|
||||
// 4 was removed in BuildKit v0.11.0.
|
||||
bool allowResultReturn = 5;
|
||||
bool allowResultArrayRef = 6;
|
||||
|
||||
// apicaps.CapSolveInlineReturn deprecated
|
||||
bool Final = 10;
|
||||
bytes ExporterAttr = 11;
|
||||
// CacheImports was added in BuildKit v0.4.0.
|
||||
// apicaps:CapImportCaches
|
||||
repeated CacheOptionsEntry CacheImports = 12;
|
||||
|
||||
// apicaps:CapFrontendInputs
|
||||
map<string, pb.Definition> FrontendInputs = 13;
|
||||
|
||||
bool Evaluate = 14;
|
||||
|
||||
repeated moby.buildkit.v1.sourcepolicy.Policy SourcePolicies = 15;
|
||||
}
|
||||
|
||||
// CacheOptionsEntry corresponds to the control.CacheOptionsEntry
|
||||
message CacheOptionsEntry {
|
||||
string Type = 1;
|
||||
map<string, string> Attrs = 2;
|
||||
}
|
||||
|
||||
message SolveResponse {
|
||||
// deprecated
|
||||
string ref = 1; // can be used by readfile request
|
||||
// deprecated
|
||||
// bytes ExporterAttr = 2;
|
||||
|
||||
// these fields are returned when allowMapReturn was set
|
||||
Result result = 3;
|
||||
}
|
||||
|
||||
message ReadFileRequest {
|
||||
string Ref = 1;
|
||||
string FilePath = 2;
|
||||
FileRange Range = 3;
|
||||
int32 MountIndex = 4;
|
||||
}
|
||||
|
||||
message FileRange {
|
||||
int64 Offset = 1;
|
||||
int64 Length = 2;
|
||||
}
|
||||
|
||||
message ReadFileResponse {
|
||||
bytes Data = 1;
|
||||
}
|
||||
|
||||
message ReadDirRequest {
|
||||
string Ref = 1;
|
||||
string DirPath = 2;
|
||||
string IncludePattern = 3;
|
||||
int32 MountIndex = 4;
|
||||
}
|
||||
|
||||
message ReadDirResponse {
|
||||
repeated fsutil.types.Stat entries = 1;
|
||||
}
|
||||
|
||||
message StatFileRequest {
|
||||
string Ref = 1;
|
||||
string Path = 2;
|
||||
int32 MountIndex = 3;
|
||||
}
|
||||
|
||||
message StatFileResponse {
|
||||
fsutil.types.Stat stat = 1;
|
||||
}
|
||||
|
||||
message EvaluateRequest {
|
||||
string Ref = 1;
|
||||
}
|
||||
|
||||
message EvaluateResponse {
|
||||
}
|
||||
|
||||
message PingRequest{
|
||||
}
|
||||
message PongResponse{
|
||||
repeated moby.buildkit.v1.apicaps.APICap FrontendAPICaps = 1;
|
||||
repeated moby.buildkit.v1.apicaps.APICap LLBCaps = 2;
|
||||
repeated moby.buildkit.v1.types.WorkerRecord Workers = 3;
|
||||
}
|
||||
|
||||
message WarnRequest {
|
||||
string digest = 1;
|
||||
int64 level = 2;
|
||||
bytes short = 3;
|
||||
repeated bytes detail = 4;
|
||||
string url = 5;
|
||||
pb.SourceInfo info = 6;
|
||||
repeated pb.Range ranges = 7;
|
||||
}
|
||||
|
||||
message WarnResponse{}
|
||||
|
||||
message NewContainerRequest {
|
||||
string ContainerID = 1;
|
||||
// For mount input values we can use random identifiers passed with ref
|
||||
repeated pb.Mount Mounts = 2;
|
||||
pb.NetMode Network = 3;
|
||||
pb.Platform platform = 4;
|
||||
pb.WorkerConstraints constraints = 5;
|
||||
repeated pb.HostIP extraHosts = 6;
|
||||
string hostname = 7;
|
||||
}
|
||||
|
||||
message NewContainerResponse{}
|
||||
|
||||
message ReleaseContainerRequest {
|
||||
string ContainerID = 1;
|
||||
}
|
||||
|
||||
message ReleaseContainerResponse{}
|
||||
|
||||
message ExecMessage {
|
||||
string ProcessID = 1;
|
||||
oneof Input {
|
||||
// InitMessage sent from client to server will start a new process in a
|
||||
// container
|
||||
InitMessage Init = 2;
|
||||
// FdMessage used from client to server for input (stdin) and
|
||||
// from server to client for output (stdout, stderr)
|
||||
FdMessage File = 3;
|
||||
// ResizeMessage used from client to server for terminal resize events
|
||||
ResizeMessage Resize = 4;
|
||||
// StartedMessage sent from server to client after InitMessage to
|
||||
// indicate the process has started.
|
||||
StartedMessage Started = 5;
|
||||
// ExitMessage sent from server to client will contain the exit code
|
||||
// when the process ends.
|
||||
ExitMessage Exit = 6;
|
||||
// DoneMessage from server to client will be the last message for any
|
||||
// process. Note that FdMessage might be sent after ExitMessage.
|
||||
DoneMessage Done = 7;
|
||||
// SignalMessage is used from client to server to send signal events
|
||||
SignalMessage Signal = 8;
|
||||
}
|
||||
}
|
||||
|
||||
message InitMessage{
|
||||
string ContainerID = 1;
|
||||
pb.Meta Meta = 2;
|
||||
repeated uint32 Fds = 3;
|
||||
bool Tty = 4;
|
||||
pb.SecurityMode Security = 5;
|
||||
repeated pb.SecretEnv secretenv = 6;
|
||||
}
|
||||
|
||||
message ExitMessage {
|
||||
uint32 Code = 1;
|
||||
google.rpc.Status Error = 2;
|
||||
}
|
||||
|
||||
message StartedMessage{}
|
||||
|
||||
message DoneMessage{}
|
||||
|
||||
message FdMessage{
|
||||
uint32 Fd = 1; // what fd the data was from
|
||||
bool EOF = 2; // true if eof was reached
|
||||
bytes Data = 3;
|
||||
}
|
||||
|
||||
message ResizeMessage{
|
||||
uint32 Rows = 1;
|
||||
uint32 Cols = 2;
|
||||
}
|
||||
|
||||
message SignalMessage {
|
||||
// we only send name (ie HUP, INT) because the int values
|
||||
// are platform dependent.
|
||||
string Name = 1;
|
||||
}
|
||||
|
||||
message Blob {
|
||||
Descriptor descriptor = 1;
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
message Descriptor {
|
||||
string media_type = 1;
|
||||
string digest = 2;
|
||||
int64 size = 3;
|
||||
map<string, string> annotations = 5;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.filesync.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/session/auth";
|
||||
|
||||
service Auth{
|
||||
rpc Credentials(CredentialsRequest) returns (CredentialsResponse);
|
||||
rpc FetchToken(FetchTokenRequest) returns (FetchTokenResponse);
|
||||
rpc GetTokenAuthority(GetTokenAuthorityRequest) returns (GetTokenAuthorityResponse);
|
||||
rpc VerifyTokenAuthority(VerifyTokenAuthorityRequest) returns (VerifyTokenAuthorityResponse);
|
||||
}
|
||||
|
||||
message CredentialsRequest {
|
||||
string Host = 1;
|
||||
}
|
||||
|
||||
message CredentialsResponse {
|
||||
string Username = 1;
|
||||
string Secret = 2;
|
||||
}
|
||||
|
||||
message FetchTokenRequest {
|
||||
string ClientID = 1;
|
||||
string Host = 2;
|
||||
string Realm = 3;
|
||||
string Service = 4;
|
||||
repeated string Scopes = 5;
|
||||
}
|
||||
|
||||
message FetchTokenResponse {
|
||||
string Token = 1;
|
||||
int64 ExpiresIn = 2; // seconds
|
||||
int64 IssuedAt = 3; // timestamp
|
||||
}
|
||||
|
||||
message GetTokenAuthorityRequest {
|
||||
string Host = 1;
|
||||
bytes Salt = 2;
|
||||
}
|
||||
|
||||
message GetTokenAuthorityResponse {
|
||||
bytes PublicKey = 1;
|
||||
}
|
||||
|
||||
message VerifyTokenAuthorityRequest {
|
||||
string Host = 1;
|
||||
bytes Payload = 2;
|
||||
bytes Salt = 3;
|
||||
}
|
||||
|
||||
message VerifyTokenAuthorityResponse {
|
||||
bytes Signed = 1;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.exporter.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/session/exporter";
|
||||
|
||||
service Exporter {
|
||||
rpc FindExporters(FindExportersRequest) returns (FindExportersResponse);
|
||||
}
|
||||
|
||||
message FindExportersRequest{
|
||||
map<string, bytes> metadata = 1;
|
||||
repeated string refs = 2;
|
||||
}
|
||||
|
||||
message FindExportersResponse {
|
||||
repeated ExporterRequest exporters = 1;
|
||||
}
|
||||
|
||||
message ExporterRequest {
|
||||
string Type = 1;
|
||||
map<string, string> Attrs = 2;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.filesync.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/session/filesync";
|
||||
|
||||
import "github.com/tonistiigi/fsutil/types/wire.proto";
|
||||
|
||||
// FileSync exposes local files from the client to the server.
|
||||
service FileSync{
|
||||
rpc DiffCopy(stream fsutil.types.Packet) returns (stream fsutil.types.Packet);
|
||||
rpc TarStream(stream fsutil.types.Packet) returns (stream fsutil.types.Packet);
|
||||
}
|
||||
|
||||
// FileSend allows sending files from the server back to the client.
|
||||
service FileSend{
|
||||
rpc DiffCopy(stream BytesMessage) returns (stream BytesMessage);
|
||||
}
|
||||
|
||||
// BytesMessage contains a chunk of byte data
|
||||
message BytesMessage {
|
||||
bytes data = 1;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.secrets.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/session/secrets";
|
||||
|
||||
service Secrets{
|
||||
rpc GetSecret(GetSecretRequest) returns (GetSecretResponse);
|
||||
}
|
||||
|
||||
|
||||
message GetSecretRequest {
|
||||
string ID = 1;
|
||||
map<string, string> annotations = 2;
|
||||
}
|
||||
|
||||
message GetSecretResponse {
|
||||
bytes data = 1;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.sshforward.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/session/sshforward";
|
||||
|
||||
service SSH {
|
||||
rpc CheckAgent(CheckAgentRequest) returns (CheckAgentResponse);
|
||||
rpc ForwardAgent(stream BytesMessage) returns (stream BytesMessage);
|
||||
}
|
||||
|
||||
// BytesMessage contains a chunk of byte data
|
||||
message BytesMessage{
|
||||
bytes data = 1;
|
||||
}
|
||||
|
||||
message CheckAgentRequest {
|
||||
string ID = 1;
|
||||
}
|
||||
|
||||
message CheckAgentResponse {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.upload.v1;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/session/upload";
|
||||
|
||||
service Upload {
|
||||
rpc Pull(stream BytesMessage) returns (stream BytesMessage);
|
||||
}
|
||||
|
||||
// BytesMessage contains a chunk of byte data
|
||||
message BytesMessage{
|
||||
bytes data = 1;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package errdefs;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/solver/errdefs";
|
||||
|
||||
import "github.com/moby/buildkit/solver/pb/ops.proto";
|
||||
|
||||
message Vertex {
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
message Source {
|
||||
pb.SourceInfo info = 1;
|
||||
repeated pb.Range ranges = 2;
|
||||
}
|
||||
|
||||
message Frontend {
|
||||
string name = 1; // frontend name e.g. dockerfile.v0 or gateway.v0
|
||||
string source = 2; // used by the gateway frontend to identify the source, which corresponds to the image name
|
||||
}
|
||||
|
||||
message FrontendCap {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message Subrequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message Solve {
|
||||
repeated string inputIDs = 1;
|
||||
repeated string mountIDs = 2;
|
||||
pb.Op op = 3;
|
||||
|
||||
oneof subject {
|
||||
FileAction file = 4;
|
||||
ContentCache cache = 5;
|
||||
}
|
||||
|
||||
map<string, string> description = 6;
|
||||
}
|
||||
|
||||
message FileAction {
|
||||
// Index of the file action that failed the exec.
|
||||
int64 index = 1;
|
||||
}
|
||||
|
||||
message ContentCache {
|
||||
// Original index of result that failed the slow cache calculation.
|
||||
int64 index = 1;
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
syntax = "proto3";
|
||||
|
||||
// Package pb provides the protobuf definition of LLB: low-level builder instruction.
|
||||
// LLB is DAG-structured; Op represents a vertex, and Definition represents a graph.
|
||||
package pb;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/solver/pb";
|
||||
|
||||
// Op represents a vertex of the LLB DAG.
|
||||
message Op {
|
||||
// changes to this structure must be represented in json.go.
|
||||
// inputs is a set of input edges.
|
||||
repeated Input inputs = 1;
|
||||
oneof op {
|
||||
ExecOp exec = 2;
|
||||
SourceOp source = 3;
|
||||
FileOp file = 4;
|
||||
BuildOp build = 5;
|
||||
MergeOp merge = 6;
|
||||
DiffOp diff = 7;
|
||||
}
|
||||
Platform platform = 10;
|
||||
WorkerConstraints constraints = 11;
|
||||
}
|
||||
|
||||
// Platform is github.com/opencontainers/image-spec/specs-go/v1.Platform
|
||||
message Platform {
|
||||
string Architecture = 1;
|
||||
string OS = 2;
|
||||
string Variant = 3;
|
||||
string OSVersion = 4;
|
||||
repeated string OSFeatures = 5; // unused
|
||||
}
|
||||
|
||||
// Input represents an input edge for an Op.
|
||||
message Input {
|
||||
// digest of the marshaled input Op
|
||||
string digest = 1;
|
||||
// output index of the input Op
|
||||
int64 index = 2;
|
||||
}
|
||||
|
||||
// ExecOp executes a command in a container.
|
||||
message ExecOp {
|
||||
Meta meta = 1;
|
||||
repeated Mount mounts = 2;
|
||||
NetMode network = 3;
|
||||
SecurityMode security = 4;
|
||||
repeated SecretEnv secretenv = 5;
|
||||
repeated CDIDevice cdiDevices = 6;
|
||||
}
|
||||
|
||||
// Meta is a set of arguments for ExecOp.
|
||||
// Meta is unrelated to LLB metadata.
|
||||
// FIXME: rename (ExecContext? ExecArgs?)
|
||||
message Meta {
|
||||
repeated string args = 1;
|
||||
repeated string env = 2;
|
||||
string cwd = 3;
|
||||
string user = 4;
|
||||
ProxyEnv proxy_env = 5;
|
||||
repeated HostIP extraHosts = 6;
|
||||
string hostname = 7;
|
||||
repeated Ulimit ulimit = 9;
|
||||
string cgroupParent = 10;
|
||||
bool removeMountStubsRecursive = 11;
|
||||
repeated int32 validExitCodes = 12;
|
||||
}
|
||||
|
||||
message HostIP {
|
||||
string Host = 1;
|
||||
string IP = 2;
|
||||
}
|
||||
|
||||
message Ulimit {
|
||||
string Name = 1;
|
||||
int64 Soft = 2;
|
||||
int64 Hard = 3;
|
||||
}
|
||||
|
||||
enum NetMode {
|
||||
UNSET = 0; // sandbox
|
||||
HOST = 1;
|
||||
NONE = 2;
|
||||
}
|
||||
|
||||
enum SecurityMode {
|
||||
SANDBOX = 0;
|
||||
INSECURE = 1; // privileged mode
|
||||
}
|
||||
|
||||
// SecretEnv is an environment variable that is backed by a secret.
|
||||
message SecretEnv {
|
||||
string ID = 1;
|
||||
string name = 2;
|
||||
bool optional = 3;
|
||||
}
|
||||
|
||||
// CDIDevice specifies a CDI device information.
|
||||
message CDIDevice {
|
||||
// Fully qualified CDI device name (e.g., vendor.com/gpu=gpudevice1)
|
||||
// https://github.com/cncf-tags/container-device-interface/blob/main/SPEC.md
|
||||
string name = 1;
|
||||
// Optional defines if CDI device is required.
|
||||
bool optional = 2;
|
||||
}
|
||||
|
||||
// Mount specifies how to mount an input Op as a filesystem.
|
||||
message Mount {
|
||||
int64 input = 1;
|
||||
string selector = 2;
|
||||
string dest = 3;
|
||||
int64 output = 4;
|
||||
bool readonly = 5;
|
||||
MountType mountType = 6;
|
||||
TmpfsOpt TmpfsOpt = 19;
|
||||
CacheOpt cacheOpt = 20;
|
||||
SecretOpt secretOpt = 21;
|
||||
SSHOpt SSHOpt = 22;
|
||||
string resultID = 23;
|
||||
MountContentCache contentCache = 24;
|
||||
}
|
||||
|
||||
// MountType defines a type of a mount from a supported set
|
||||
enum MountType {
|
||||
BIND = 0;
|
||||
SECRET = 1;
|
||||
SSH = 2;
|
||||
CACHE = 3;
|
||||
TMPFS = 4;
|
||||
}
|
||||
|
||||
// MountContentCache ...
|
||||
enum MountContentCache {
|
||||
DEFAULT = 0;
|
||||
ON = 1;
|
||||
OFF = 2;
|
||||
}
|
||||
|
||||
// TmpfsOpt defines options describing tpmfs mounts
|
||||
message TmpfsOpt {
|
||||
// Specify an upper limit on the size of the filesystem.
|
||||
int64 size = 1;
|
||||
}
|
||||
|
||||
// CacheOpt defines options specific to cache mounts
|
||||
message CacheOpt {
|
||||
// ID is an optional namespace for the mount
|
||||
string ID = 1;
|
||||
// Sharing is the sharing mode for the mount
|
||||
CacheSharingOpt sharing = 2;
|
||||
}
|
||||
|
||||
// CacheSharingOpt defines different sharing modes for cache mount
|
||||
enum CacheSharingOpt {
|
||||
// SHARED cache mount can be used concurrently by multiple writers
|
||||
SHARED = 0;
|
||||
// PRIVATE creates a new mount if there are multiple writers
|
||||
PRIVATE = 1;
|
||||
// LOCKED pauses second writer until first one releases the mount
|
||||
LOCKED = 2;
|
||||
}
|
||||
|
||||
// SecretOpt defines options describing secret mounts
|
||||
message SecretOpt {
|
||||
// ID of secret. Used for quering the value.
|
||||
string ID = 1;
|
||||
// UID of secret file
|
||||
uint32 uid = 2;
|
||||
// GID of secret file
|
||||
uint32 gid = 3;
|
||||
// Mode is the filesystem mode of secret file
|
||||
uint32 mode = 4;
|
||||
// Optional defines if secret value is required. Error is produced
|
||||
// if value is not found and optional is false.
|
||||
bool optional = 5;
|
||||
}
|
||||
|
||||
// SSHOpt defines options describing ssh mounts
|
||||
message SSHOpt {
|
||||
// ID of exposed ssh rule. Used for quering the value.
|
||||
string ID = 1;
|
||||
// UID of agent socket
|
||||
uint32 uid = 2;
|
||||
// GID of agent socket
|
||||
uint32 gid = 3;
|
||||
// Mode is the filesystem mode of agent socket
|
||||
uint32 mode = 4;
|
||||
// Optional defines if ssh socket is required. Error is produced
|
||||
// if client does not expose ssh.
|
||||
bool optional = 5;
|
||||
}
|
||||
|
||||
// SourceOp specifies a source such as build contexts and images.
|
||||
message SourceOp {
|
||||
// TODO: use source type or any type instead of URL protocol.
|
||||
// identifier e.g. local://, docker-image://, git://, https://...
|
||||
string identifier = 1;
|
||||
// attrs are defined in attr.go
|
||||
map<string, string> attrs = 2;
|
||||
}
|
||||
|
||||
// BuildOp is used for nested build invocation.
|
||||
// BuildOp is experimental and can break without backwards compatibility
|
||||
message BuildOp {
|
||||
int64 builder = 1;
|
||||
map<string, BuildInput> inputs = 2;
|
||||
Definition def = 3;
|
||||
map<string, string> attrs = 4;
|
||||
// outputs
|
||||
}
|
||||
|
||||
// BuildInput is used for BuildOp.
|
||||
message BuildInput {
|
||||
int64 input = 1;
|
||||
}
|
||||
|
||||
// OpMetadata is a per-vertex metadata entry, which can be defined for arbitrary Op vertex and overridable on the run time.
|
||||
message OpMetadata {
|
||||
// ignore_cache specifies to ignore the cache for this Op.
|
||||
bool ignore_cache = 1;
|
||||
// Description can be used for keeping any text fields that builder doesn't parse
|
||||
map<string, string> description = 2;
|
||||
// index 3 reserved for WorkerConstraint in previous versions
|
||||
// WorkerConstraint worker_constraint = 3;
|
||||
ExportCache export_cache = 4;
|
||||
|
||||
map<string, bool> caps = 5;
|
||||
|
||||
ProgressGroup progress_group = 6;
|
||||
}
|
||||
|
||||
// Source is a source mapping description for a file
|
||||
message Source {
|
||||
map<string, Locations> locations = 1;
|
||||
repeated SourceInfo infos = 2;
|
||||
}
|
||||
|
||||
// Locations is a list of ranges with a index to its source map.
|
||||
message Locations {
|
||||
repeated Location locations = 1;
|
||||
}
|
||||
|
||||
// Source info contains the shared metadata of a source mapping
|
||||
message SourceInfo {
|
||||
string filename = 1;
|
||||
bytes data = 2;
|
||||
Definition definition = 3;
|
||||
string language = 4;
|
||||
}
|
||||
|
||||
// Location defines list of areas in to source file
|
||||
message Location {
|
||||
int32 sourceIndex = 1;
|
||||
repeated Range ranges = 2;
|
||||
}
|
||||
|
||||
// Range is an area in the source file
|
||||
message Range {
|
||||
Position start = 1;
|
||||
Position end = 2;
|
||||
}
|
||||
|
||||
// Position is single location in a source file
|
||||
message Position {
|
||||
int32 line = 1;
|
||||
int32 character = 2;
|
||||
}
|
||||
|
||||
message ExportCache {
|
||||
bool Value = 1;
|
||||
}
|
||||
|
||||
message ProgressGroup {
|
||||
string id = 1;
|
||||
string name = 2;
|
||||
bool weak = 3;
|
||||
}
|
||||
|
||||
message ProxyEnv {
|
||||
string http_proxy = 1;
|
||||
string https_proxy = 2;
|
||||
string ftp_proxy = 3;
|
||||
string no_proxy = 4;
|
||||
string all_proxy = 5;
|
||||
}
|
||||
|
||||
// WorkerConstraints defines conditions for the worker
|
||||
message WorkerConstraints {
|
||||
repeated string filter = 1; // containerd-style filter
|
||||
}
|
||||
|
||||
// Definition is the LLB definition structure with per-vertex metadata entries
|
||||
message Definition {
|
||||
// def is a list of marshaled Op messages
|
||||
repeated bytes def = 1;
|
||||
// metadata contains metadata for the each of the Op messages.
|
||||
// A key must be an LLB op digest string. Currently, empty string is not expected as a key, but it may change in the future.
|
||||
map<string, OpMetadata> metadata = 2;
|
||||
// Source contains the source mapping information for the vertexes in the definition
|
||||
Source Source = 3;
|
||||
}
|
||||
|
||||
message FileOp {
|
||||
repeated FileAction actions = 2;
|
||||
}
|
||||
|
||||
message FileAction {
|
||||
// changes to this structure must be represented in json.go.
|
||||
int64 input = 1; // could be real input or target (target index + max input index)
|
||||
int64 secondaryInput = 2; // --//--
|
||||
int64 output = 3;
|
||||
oneof action {
|
||||
// FileActionCopy copies files from secondaryInput on top of input
|
||||
FileActionCopy copy = 4;
|
||||
// FileActionMkFile creates a new file
|
||||
FileActionMkFile mkfile = 5;
|
||||
// FileActionMkDir creates a new directory
|
||||
FileActionMkDir mkdir = 6;
|
||||
// FileActionRm removes a file
|
||||
FileActionRm rm = 7;
|
||||
// FileActionSymlink creates a symlink
|
||||
FileActionSymlink symlink = 8;
|
||||
}
|
||||
}
|
||||
|
||||
message FileActionCopy {
|
||||
// src is the source path
|
||||
string src = 1;
|
||||
// dest path
|
||||
string dest = 2;
|
||||
// optional owner override
|
||||
ChownOpt owner = 3;
|
||||
// optional permission bits override
|
||||
int32 mode = 4;
|
||||
// followSymlink resolves symlinks in src
|
||||
bool followSymlink = 5;
|
||||
// dirCopyContents only copies contents if src is a directory
|
||||
bool dirCopyContents = 6;
|
||||
// attemptUnpackDockerCompatibility detects if src is an archive to unpack it instead
|
||||
bool attemptUnpackDockerCompatibility = 7;
|
||||
// createDestPath creates dest path directories if needed
|
||||
bool createDestPath = 8;
|
||||
// allowWildcard allows filepath.Match wildcards in src path
|
||||
bool allowWildcard = 9;
|
||||
// allowEmptyWildcard doesn't fail the whole copy if wildcard doesn't resolve to files
|
||||
bool allowEmptyWildcard = 10;
|
||||
// optional created time override
|
||||
int64 timestamp = 11;
|
||||
// include only files/dirs matching at least one of these patterns
|
||||
repeated string include_patterns = 12;
|
||||
// exclude files/dir matching any of these patterns (even if they match an include pattern)
|
||||
repeated string exclude_patterns = 13;
|
||||
// alwaysReplaceExistingDestPaths results in an existing dest path that differs in type from the src path being replaced rather than the default of returning an error
|
||||
bool alwaysReplaceExistingDestPaths = 14;
|
||||
// mode in non-octal format
|
||||
string modeStr = 15;
|
||||
// required paths that must be included in the copy. This is only used when
|
||||
// include_patterns has at least one pattern.
|
||||
repeated string required_paths = 16;
|
||||
}
|
||||
|
||||
message FileActionMkFile {
|
||||
// path for the new file
|
||||
string path = 1;
|
||||
// permission bits
|
||||
int32 mode = 2;
|
||||
// data is the new file contents
|
||||
bytes data = 3;
|
||||
// optional owner for the new file
|
||||
ChownOpt owner = 4;
|
||||
// optional created time override
|
||||
int64 timestamp = 5;
|
||||
}
|
||||
|
||||
message FileActionSymlink {
|
||||
// destination path for the new file representing the link
|
||||
string oldpath = 1;
|
||||
// source path for the link
|
||||
string newpath = 2;
|
||||
// optional owner for the new file
|
||||
ChownOpt owner = 3;
|
||||
// optional created time override
|
||||
int64 timestamp = 4;
|
||||
}
|
||||
|
||||
message FileActionMkDir {
|
||||
// path for the new directory
|
||||
string path = 1;
|
||||
// permission bits
|
||||
int32 mode = 2;
|
||||
// makeParents creates parent directories as well if needed
|
||||
bool makeParents = 3;
|
||||
// optional owner for the new directory
|
||||
ChownOpt owner = 4;
|
||||
// optional created time override
|
||||
int64 timestamp = 5;
|
||||
}
|
||||
|
||||
message FileActionRm {
|
||||
// path to remove
|
||||
string path = 1;
|
||||
// allowNotFound doesn't fail the rm if file is not found
|
||||
bool allowNotFound = 2;
|
||||
// allowWildcard allows filepath.Match wildcards in path
|
||||
bool allowWildcard = 3;
|
||||
}
|
||||
|
||||
message ChownOpt {
|
||||
UserOpt user = 1;
|
||||
UserOpt group = 2;
|
||||
}
|
||||
|
||||
message UserOpt {
|
||||
// changes to this structure must be represented in json.go.
|
||||
oneof user {
|
||||
NamedUserOpt byName = 1;
|
||||
uint32 byID = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message NamedUserOpt {
|
||||
string name = 1;
|
||||
int64 input = 2;
|
||||
}
|
||||
|
||||
message MergeInput {
|
||||
int64 input = 1;
|
||||
}
|
||||
|
||||
message MergeOp {
|
||||
repeated MergeInput inputs = 1;
|
||||
}
|
||||
|
||||
message LowerDiffInput {
|
||||
int64 input = 1;
|
||||
}
|
||||
|
||||
message UpperDiffInput {
|
||||
int64 input = 1;
|
||||
}
|
||||
|
||||
message DiffOp {
|
||||
LowerDiffInput lower = 1;
|
||||
UpperDiffInput upper = 2;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.v1.sourcepolicy;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/sourcepolicy/pb;moby_buildkit_v1_sourcepolicy";
|
||||
|
||||
// Rule defines the action(s) to take when a source is matched
|
||||
message Rule {
|
||||
PolicyAction action = 1;
|
||||
Selector selector = 2;
|
||||
Update updates = 3;
|
||||
}
|
||||
|
||||
// Update contains updates to the matched build step after rule is applied
|
||||
message Update {
|
||||
string identifier = 1;
|
||||
map<string, string> attrs = 2;
|
||||
}
|
||||
|
||||
// Selector identifies a source to match a policy to
|
||||
message Selector {
|
||||
string identifier = 1;
|
||||
// MatchType is the type of match to perform on the source identifier
|
||||
MatchType match_type = 2;
|
||||
repeated AttrConstraint constraints = 3;
|
||||
}
|
||||
|
||||
// PolicyAction defines the action to take when a source is matched
|
||||
enum PolicyAction {
|
||||
ALLOW = 0;
|
||||
DENY = 1;
|
||||
CONVERT = 2;
|
||||
}
|
||||
|
||||
// AttrConstraint defines a constraint on a source attribute
|
||||
message AttrConstraint {
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
AttrMatch condition = 3;
|
||||
}
|
||||
|
||||
// AttrMatch defines the condition to match a source attribute
|
||||
enum AttrMatch {
|
||||
EQUAL = 0;
|
||||
NOTEQUAL = 1;
|
||||
MATCHES = 2;
|
||||
}
|
||||
|
||||
// Policy is the list of rules the policy engine will perform
|
||||
message Policy {
|
||||
int64 version = 1; // Currently 1
|
||||
repeated Rule rules = 2;
|
||||
}
|
||||
|
||||
// Match type is used to determine how a rule source is matched
|
||||
enum MatchType {
|
||||
// WILDCARD is the default matching type.
|
||||
// It may first attempt to due an exact match but will follow up with a wildcard match
|
||||
// For something more powerful, use REGEX
|
||||
WILDCARD = 0;
|
||||
// EXACT treats the source identifier as a litteral string match
|
||||
EXACT = 1;
|
||||
// REGEX treats the source identifier as a regular expression
|
||||
// With regex matching you can also use match groups to replace values in the destination identifier
|
||||
REGEX = 2;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.v1.sourcepolicy.policysession;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/sourcepolicy/policysession";
|
||||
|
||||
import "github.com/moby/buildkit/frontend/gateway/pb/gateway.proto";
|
||||
import "github.com/moby/buildkit/solver/pb/ops.proto";
|
||||
import "github.com/moby/buildkit/sourcepolicy/pb/policy.proto";
|
||||
|
||||
service PolicyVerifier {
|
||||
rpc CheckPolicy(CheckPolicyRequest) returns (CheckPolicyResponse);
|
||||
}
|
||||
|
||||
message CheckPolicyRequest {
|
||||
pb.Platform Platform = 1;
|
||||
moby.buildkit.v1.frontend.ResolveSourceMetaResponse Source = 2;
|
||||
map<string, bool> caps = 3;
|
||||
}
|
||||
|
||||
message CheckPolicyResponse {
|
||||
oneof result {
|
||||
DecisionResponse decision = 1;
|
||||
moby.buildkit.v1.frontend.ResolveSourceMetaRequest request = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message DecisionResponse {
|
||||
moby.buildkit.v1.sourcepolicy.PolicyAction action = 1;
|
||||
repeated DenyMessage denyMessages = 2;
|
||||
pb.SourceOp update = 3;
|
||||
}
|
||||
|
||||
message DenyMessage {
|
||||
string message = 1;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package moby.buildkit.v1.apicaps;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/util/apicaps/pb;moby_buildkit_v1_apicaps";
|
||||
|
||||
// APICap defines a capability supported by the service
|
||||
message APICap {
|
||||
string ID = 1;
|
||||
bool Enabled = 2;
|
||||
bool Deprecated = 3; // Unused. May be used for warnings in the future
|
||||
string DisabledReason = 4; // Reason key for detection code
|
||||
string DisabledReasonMsg = 5; // Message to the user
|
||||
string DisabledAlternative = 6; // Identifier that updated client could catch.
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package stack;
|
||||
|
||||
option go_package = "github.com/moby/buildkit/util/stack";
|
||||
|
||||
message Stack {
|
||||
repeated Frame frames = 1;
|
||||
repeated string cmdline = 2;
|
||||
int32 pid = 3;
|
||||
string version = 4;
|
||||
string revision = 5;
|
||||
}
|
||||
|
||||
message Frame {
|
||||
string Name = 1;
|
||||
string File = 2;
|
||||
int32 Line = 3;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// Stub for vtprotobuf extensions — not needed for Rust codegen
|
||||
syntax = "proto3";
|
||||
package vtproto;
|
||||
import "google/protobuf/descriptor.proto";
|
||||
extend google.protobuf.MessageOptions {
|
||||
bool mempool = 64101;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package fsutil.types;
|
||||
|
||||
option go_package = "github.com/tonistiigi/fsutil/types";
|
||||
|
||||
import "github.com/planetscale/vtprotobuf/vtproto/ext.proto";
|
||||
|
||||
message Stat {
|
||||
string path = 1;
|
||||
uint32 mode = 2;
|
||||
uint32 uid = 3;
|
||||
uint32 gid = 4;
|
||||
int64 size = 5;
|
||||
int64 modTime = 6;
|
||||
// int32 typeflag = 7;
|
||||
string linkname = 7;
|
||||
int64 devmajor = 8;
|
||||
int64 devminor = 9;
|
||||
map<string, bytes> xattrs = 10;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package fsutil.types;
|
||||
|
||||
option go_package = "github.com/tonistiigi/fsutil/types";
|
||||
|
||||
import "github.com/planetscale/vtprotobuf/vtproto/ext.proto";
|
||||
import "github.com/tonistiigi/fsutil/types/stat.proto";
|
||||
|
||||
message Packet {
|
||||
option (vtproto.mempool) = true;
|
||||
enum PacketType {
|
||||
PACKET_STAT = 0;
|
||||
PACKET_REQ = 1;
|
||||
PACKET_DATA = 2;
|
||||
PACKET_FIN = 3;
|
||||
PACKET_ERR = 4;
|
||||
}
|
||||
PacketType type = 1;
|
||||
Stat stat = 2;
|
||||
uint32 ID = 3;
|
||||
bytes data = 4;
|
||||
}
|
||||
49
wfe-buildkit-protos/proto/google/rpc/status.proto
Normal file
49
wfe-buildkit-protos/proto/google/rpc/status.proto
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2025 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package google.rpc;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option cc_enable_arenas = true;
|
||||
option go_package = "google.golang.org/genproto/googleapis/rpc/status;status";
|
||||
option java_multiple_files = true;
|
||||
option java_outer_classname = "StatusProto";
|
||||
option java_package = "com.google.rpc";
|
||||
option objc_class_prefix = "RPC";
|
||||
|
||||
// The `Status` type defines a logical error model that is suitable for
|
||||
// different programming environments, including REST APIs and RPC APIs. It is
|
||||
// used by [gRPC](https://github.com/grpc). Each `Status` message contains
|
||||
// three pieces of data: error code, error message, and error details.
|
||||
//
|
||||
// You can find out more about this error model and how to work with it in the
|
||||
// [API Design Guide](https://cloud.google.com/apis/design/errors).
|
||||
message Status {
|
||||
// The status code, which should be an enum value of
|
||||
// [google.rpc.Code][google.rpc.Code].
|
||||
int32 code = 1;
|
||||
|
||||
// A developer-facing error message, which should be in English. Any
|
||||
// user-facing error message should be localized and sent in the
|
||||
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized
|
||||
// by the client.
|
||||
string message = 2;
|
||||
|
||||
// A list of messages that carry the error details. There is a common set of
|
||||
// message types for APIs to use.
|
||||
repeated google.protobuf.Any details = 3;
|
||||
}
|
||||
19
wfe-buildkit-protos/src/lib.rs
Normal file
19
wfe-buildkit-protos/src/lib.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
//! Generated gRPC stubs for the full BuildKit API.
|
||||
//!
|
||||
//! Built from the official BuildKit proto files at
|
||||
//! <https://github.com/moby/buildkit>.
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! use wfe_buildkit_protos::moby::buildkit::v1::control_client::ControlClient;
|
||||
//! use wfe_buildkit_protos::moby::buildkit::v1::StatusResponse;
|
||||
//! ```
|
||||
|
||||
#![allow(clippy::all)]
|
||||
#![allow(warnings)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
|
||||
|
||||
/// Re-export tonic and prost for downstream convenience.
|
||||
pub use prost;
|
||||
pub use prost_types;
|
||||
pub use tonic;
|
||||
30
wfe-buildkit/Cargo.toml
Normal file
30
wfe-buildkit/Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "wfe-buildkit"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "BuildKit image builder executor for WFE"
|
||||
|
||||
[dependencies]
|
||||
wfe-core = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
wfe-buildkit-protos = { version = "1.8.0", path = "../wfe-buildkit-protos", registry = "sunbeam" }
|
||||
tonic = "0.14"
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
hyper-util = { version = "0.1", features = ["tokio"] }
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
tokio-stream = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
pretty_assertions = { workspace = true }
|
||||
tempfile = { workspace = true }
|
||||
tokio = { workspace = true, features = ["test-util"] }
|
||||
tokio-util = "0.7"
|
||||
95
wfe-buildkit/README.md
Normal file
95
wfe-buildkit/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# wfe-buildkit
|
||||
|
||||
BuildKit image builder executor for WFE.
|
||||
|
||||
## What it does
|
||||
|
||||
`wfe-buildkit` provides a `BuildkitStep` that implements the `StepBody` trait from `wfe-core`. It shells out to the `buildctl` CLI to build container images using BuildKit, capturing stdout/stderr and parsing image digests from the output.
|
||||
|
||||
## Quick start
|
||||
|
||||
Use it standalone:
|
||||
|
||||
```rust
|
||||
use wfe_buildkit::{BuildkitConfig, BuildkitStep};
|
||||
|
||||
let config = BuildkitConfig {
|
||||
dockerfile: "Dockerfile".to_string(),
|
||||
context: ".".to_string(),
|
||||
tags: vec!["myapp:latest".to_string()],
|
||||
push: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let step = BuildkitStep::new(config);
|
||||
|
||||
// Inspect the command that would be executed.
|
||||
let args = step.build_command();
|
||||
println!("{}", args.join(" "));
|
||||
```
|
||||
|
||||
Or use it through `wfe-yaml` with the `buildkit` feature:
|
||||
|
||||
```yaml
|
||||
workflow:
|
||||
id: build-image
|
||||
version: 1
|
||||
steps:
|
||||
- name: build
|
||||
type: buildkit
|
||||
config:
|
||||
dockerfile: Dockerfile
|
||||
context: .
|
||||
tags:
|
||||
- myapp:latest
|
||||
- myapp:v1.0
|
||||
push: true
|
||||
build_args:
|
||||
RUST_VERSION: "1.78"
|
||||
cache_from:
|
||||
- type=registry,ref=myapp:cache
|
||||
cache_to:
|
||||
- type=registry,ref=myapp:cache,mode=max
|
||||
timeout: 10m
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
| Field | Type | Required | Default | Description |
|
||||
|---|---|---|---|---|
|
||||
| `dockerfile` | String | Yes | - | Path to the Dockerfile |
|
||||
| `context` | String | Yes | - | Build context directory |
|
||||
| `target` | String | No | - | Multi-stage build target |
|
||||
| `tags` | Vec\<String\> | No | [] | Image tags |
|
||||
| `build_args` | Map\<String, String\> | No | {} | Build arguments |
|
||||
| `cache_from` | Vec\<String\> | No | [] | Cache import sources |
|
||||
| `cache_to` | Vec\<String\> | No | [] | Cache export destinations |
|
||||
| `push` | bool | No | false | Push image after build |
|
||||
| `output_type` | String | No | "image" | Output type: image, local, tar |
|
||||
| `buildkit_addr` | String | No | unix:///run/buildkit/buildkitd.sock | BuildKit daemon address |
|
||||
| `tls` | TlsConfig | No | - | TLS certificate paths |
|
||||
| `registry_auth` | Map\<String, RegistryAuth\> | No | {} | Registry credentials |
|
||||
| `timeout_ms` | u64 | No | - | Execution timeout in milliseconds |
|
||||
|
||||
## Output data
|
||||
|
||||
After execution, the step writes the following keys into `output_data`:
|
||||
|
||||
| Key | Description |
|
||||
|---|---|
|
||||
| `{step_name}.digest` | Image digest (sha256:...), if found in output |
|
||||
| `{step_name}.tags` | Array of tags applied to the image |
|
||||
| `{step_name}.stdout` | Full stdout from buildctl |
|
||||
| `{step_name}.stderr` | Full stderr from buildctl |
|
||||
|
||||
## Testing
|
||||
|
||||
```sh
|
||||
cargo test -p wfe-buildkit
|
||||
```
|
||||
|
||||
The `build_command()` method returns the full argument list without executing, making it possible to test command construction without a running BuildKit daemon.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
358
wfe-buildkit/src/config.rs
Normal file
358
wfe-buildkit/src/config.rs
Normal file
@@ -0,0 +1,358 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Configuration for a BuildKit image build step.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct BuildkitConfig {
|
||||
/// Path to the Dockerfile (or directory containing it).
|
||||
pub dockerfile: String,
|
||||
/// Build context directory.
|
||||
pub context: String,
|
||||
/// Multi-stage build target.
|
||||
pub target: Option<String>,
|
||||
/// Image tags to apply.
|
||||
#[serde(default)]
|
||||
pub tags: Vec<String>,
|
||||
/// Build arguments passed as `--opt build-arg:KEY=VALUE`.
|
||||
#[serde(default)]
|
||||
pub build_args: HashMap<String, String>,
|
||||
/// Cache import sources.
|
||||
#[serde(default)]
|
||||
pub cache_from: Vec<String>,
|
||||
/// Cache export destinations.
|
||||
#[serde(default)]
|
||||
pub cache_to: Vec<String>,
|
||||
/// Whether to push the built image.
|
||||
#[serde(default)]
|
||||
pub push: bool,
|
||||
/// Output type: "image", "local", "tar".
|
||||
pub output_type: Option<String>,
|
||||
/// BuildKit daemon address.
|
||||
#[serde(default = "default_buildkit_addr")]
|
||||
pub buildkit_addr: String,
|
||||
/// TLS configuration for the BuildKit connection.
|
||||
#[serde(default)]
|
||||
pub tls: TlsConfig,
|
||||
/// Registry authentication credentials keyed by registry host.
|
||||
#[serde(default)]
|
||||
pub registry_auth: HashMap<String, RegistryAuth>,
|
||||
/// Execution timeout in milliseconds.
|
||||
pub timeout_ms: Option<u64>,
|
||||
}
|
||||
|
||||
/// TLS certificate paths for securing the BuildKit connection.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||
pub struct TlsConfig {
|
||||
/// Path to the CA certificate.
|
||||
pub ca: Option<String>,
|
||||
/// Path to the client certificate.
|
||||
pub cert: Option<String>,
|
||||
/// Path to the client private key.
|
||||
pub key: Option<String>,
|
||||
}
|
||||
|
||||
/// Credentials for authenticating with a container registry.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RegistryAuth {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
fn default_buildkit_addr() -> String {
|
||||
"unix:///run/buildkit/buildkitd.sock".to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn serde_round_trip_full_config() {
|
||||
let mut build_args = HashMap::new();
|
||||
build_args.insert("RUST_VERSION".to_string(), "1.78".to_string());
|
||||
|
||||
let mut registry_auth = HashMap::new();
|
||||
registry_auth.insert(
|
||||
"ghcr.io".to_string(),
|
||||
RegistryAuth {
|
||||
username: "user".to_string(),
|
||||
password: "pass".to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
let config = BuildkitConfig {
|
||||
dockerfile: "./Dockerfile".to_string(),
|
||||
context: ".".to_string(),
|
||||
target: Some("runtime".to_string()),
|
||||
tags: vec!["myapp:latest".to_string(), "myapp:v1.0".to_string()],
|
||||
build_args,
|
||||
cache_from: vec!["type=registry,ref=myapp:cache".to_string()],
|
||||
cache_to: vec!["type=registry,ref=myapp:cache,mode=max".to_string()],
|
||||
push: true,
|
||||
output_type: Some("image".to_string()),
|
||||
buildkit_addr: "tcp://buildkitd:1234".to_string(),
|
||||
tls: TlsConfig {
|
||||
ca: Some("/certs/ca.pem".to_string()),
|
||||
cert: Some("/certs/cert.pem".to_string()),
|
||||
key: Some("/certs/key.pem".to_string()),
|
||||
},
|
||||
registry_auth,
|
||||
timeout_ms: Some(300_000),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&config).unwrap();
|
||||
let deserialized: BuildkitConfig = serde_json::from_str(&json).unwrap();
|
||||
|
||||
assert_eq!(config.dockerfile, deserialized.dockerfile);
|
||||
assert_eq!(config.context, deserialized.context);
|
||||
assert_eq!(config.target, deserialized.target);
|
||||
assert_eq!(config.tags, deserialized.tags);
|
||||
assert_eq!(config.build_args, deserialized.build_args);
|
||||
assert_eq!(config.cache_from, deserialized.cache_from);
|
||||
assert_eq!(config.cache_to, deserialized.cache_to);
|
||||
assert_eq!(config.push, deserialized.push);
|
||||
assert_eq!(config.output_type, deserialized.output_type);
|
||||
assert_eq!(config.buildkit_addr, deserialized.buildkit_addr);
|
||||
assert_eq!(config.tls.ca, deserialized.tls.ca);
|
||||
assert_eq!(config.tls.cert, deserialized.tls.cert);
|
||||
assert_eq!(config.tls.key, deserialized.tls.key);
|
||||
assert_eq!(config.timeout_ms, deserialized.timeout_ms);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_round_trip_minimal_config() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": "."
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
|
||||
assert_eq!(config.dockerfile, "Dockerfile");
|
||||
assert_eq!(config.context, ".");
|
||||
assert_eq!(config.target, None);
|
||||
assert!(config.tags.is_empty());
|
||||
assert!(config.build_args.is_empty());
|
||||
assert!(config.cache_from.is_empty());
|
||||
assert!(config.cache_to.is_empty());
|
||||
assert!(!config.push);
|
||||
assert_eq!(config.output_type, None);
|
||||
assert_eq!(config.buildkit_addr, "unix:///run/buildkit/buildkitd.sock");
|
||||
assert_eq!(config.timeout_ms, None);
|
||||
|
||||
// Round-trip
|
||||
let serialized = serde_json::to_string(&config).unwrap();
|
||||
let deserialized: BuildkitConfig = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(config.dockerfile, deserialized.dockerfile);
|
||||
assert_eq!(config.context, deserialized.context);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn default_buildkit_addr_value() {
|
||||
let addr = default_buildkit_addr();
|
||||
assert_eq!(addr, "unix:///run/buildkit/buildkitd.sock");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tls_config_defaults_to_none() {
|
||||
let tls = TlsConfig::default();
|
||||
assert_eq!(tls.ca, None);
|
||||
assert_eq!(tls.cert, None);
|
||||
assert_eq!(tls.key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn registry_auth_serde() {
|
||||
let auth = RegistryAuth {
|
||||
username: "admin".to_string(),
|
||||
password: "secret123".to_string(),
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&auth).unwrap();
|
||||
let deserialized: RegistryAuth = serde_json::from_str(&json).unwrap();
|
||||
|
||||
assert_eq!(auth.username, deserialized.username);
|
||||
assert_eq!(auth.password, deserialized.password);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_custom_addr() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"buildkit_addr": "tcp://remote:1234"
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.buildkit_addr, "tcp://remote:1234");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_timeout() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"timeout_ms": 60000
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.timeout_ms, Some(60000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_tags_and_push() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"tags": ["myapp:latest", "myapp:v1.0"],
|
||||
"push": true
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.tags, vec!["myapp:latest", "myapp:v1.0"]);
|
||||
assert!(config.push);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_build_args() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"build_args": {"VERSION": "1.0", "DEBUG": "false"}
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.build_args.len(), 2);
|
||||
assert_eq!(config.build_args["VERSION"], "1.0");
|
||||
assert_eq!(config.build_args["DEBUG"], "false");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_cache_config() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"cache_from": ["type=registry,ref=cache:latest"],
|
||||
"cache_to": ["type=registry,ref=cache:latest,mode=max"]
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.cache_from.len(), 1);
|
||||
assert_eq!(config.cache_to.len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_output_type() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"output_type": "tar"
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.output_type, Some("tar".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_registry_auth() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"registry_auth": {
|
||||
"ghcr.io": {"username": "bot", "password": "tok"},
|
||||
"docker.io": {"username": "u", "password": "p"}
|
||||
}
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.registry_auth.len(), 2);
|
||||
assert_eq!(config.registry_auth["ghcr.io"].username, "bot");
|
||||
assert_eq!(config.registry_auth["docker.io"].password, "p");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_with_tls() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"tls": {
|
||||
"ca": "/certs/ca.pem",
|
||||
"cert": "/certs/cert.pem",
|
||||
"key": "/certs/key.pem"
|
||||
}
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.tls.ca, Some("/certs/ca.pem".to_string()));
|
||||
assert_eq!(config.tls.cert, Some("/certs/cert.pem".to_string()));
|
||||
assert_eq!(config.tls.key, Some("/certs/key.pem".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_partial_tls() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"tls": {"ca": "/certs/ca.pem"}
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.tls.ca, Some("/certs/ca.pem".to_string()));
|
||||
assert_eq!(config.tls.cert, None);
|
||||
assert_eq!(config.tls.key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_empty_tls_object() {
|
||||
let json = r#"{
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": ".",
|
||||
"tls": {}
|
||||
}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
assert_eq!(config.tls.ca, None);
|
||||
assert_eq!(config.tls.cert, None);
|
||||
assert_eq!(config.tls.key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tls_config_clone() {
|
||||
let tls = TlsConfig {
|
||||
ca: Some("ca".to_string()),
|
||||
cert: Some("cert".to_string()),
|
||||
key: Some("key".to_string()),
|
||||
};
|
||||
let cloned = tls.clone();
|
||||
assert_eq!(tls.ca, cloned.ca);
|
||||
assert_eq!(tls.cert, cloned.cert);
|
||||
assert_eq!(tls.key, cloned.key);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tls_config_debug() {
|
||||
let tls = TlsConfig::default();
|
||||
let debug = format!("{:?}", tls);
|
||||
assert!(debug.contains("TlsConfig"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buildkit_config_debug() {
|
||||
let json = r#"{"dockerfile": "Dockerfile", "context": "."}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
let debug = format!("{:?}", config);
|
||||
assert!(debug.contains("BuildkitConfig"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn registry_auth_clone() {
|
||||
let auth = RegistryAuth {
|
||||
username: "u".to_string(),
|
||||
password: "p".to_string(),
|
||||
};
|
||||
let cloned = auth.clone();
|
||||
assert_eq!(auth.username, cloned.username);
|
||||
assert_eq!(auth.password, cloned.password);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn buildkit_config_clone() {
|
||||
let json = r#"{"dockerfile": "Dockerfile", "context": "."}"#;
|
||||
let config: BuildkitConfig = serde_json::from_str(json).unwrap();
|
||||
let cloned = config.clone();
|
||||
assert_eq!(config.dockerfile, cloned.dockerfile);
|
||||
assert_eq!(config.context, cloned.context);
|
||||
assert_eq!(config.buildkit_addr, cloned.buildkit_addr);
|
||||
}
|
||||
}
|
||||
5
wfe-buildkit/src/lib.rs
Normal file
5
wfe-buildkit/src/lib.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub mod config;
|
||||
pub mod step;
|
||||
|
||||
pub use config::{BuildkitConfig, RegistryAuth, TlsConfig};
|
||||
pub use step::{build_output_data, parse_digest, BuildkitStep};
|
||||
905
wfe-buildkit/src/step.rs
Normal file
905
wfe-buildkit/src/step.rs
Normal file
@@ -0,0 +1,905 @@
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use regex::Regex;
|
||||
use tokio_stream::StreamExt;
|
||||
use tonic::transport::{Channel, Endpoint, Uri};
|
||||
use wfe_buildkit_protos::moby::buildkit::v1::control_client::ControlClient;
|
||||
use wfe_buildkit_protos::moby::buildkit::v1::{
|
||||
CacheOptions, CacheOptionsEntry, Exporter, SolveRequest, StatusRequest,
|
||||
};
|
||||
use wfe_core::models::ExecutionResult;
|
||||
use wfe_core::traits::step::{StepBody, StepExecutionContext};
|
||||
use wfe_core::WfeError;
|
||||
|
||||
use crate::config::BuildkitConfig;
|
||||
|
||||
/// Result of a BuildKit solve operation.
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct BuildResult {
|
||||
/// Image digest produced by the build, if any.
|
||||
pub digest: Option<String>,
|
||||
/// Full exporter response metadata from the daemon.
|
||||
#[allow(dead_code)]
|
||||
pub metadata: HashMap<String, String>,
|
||||
}
|
||||
|
||||
/// A workflow step that builds container images via the BuildKit gRPC API.
|
||||
pub struct BuildkitStep {
|
||||
config: BuildkitConfig,
|
||||
}
|
||||
|
||||
impl BuildkitStep {
|
||||
/// Create a new BuildKit step from configuration.
|
||||
pub fn new(config: BuildkitConfig) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
/// Connect to the BuildKit daemon and return a raw `ControlClient`.
|
||||
///
|
||||
/// Supports Unix socket (`unix://`), TCP (`tcp://`), and HTTP (`http://`)
|
||||
/// endpoints.
|
||||
async fn connect(&self) -> Result<ControlClient<Channel>, WfeError> {
|
||||
let addr = &self.config.buildkit_addr;
|
||||
tracing::info!(addr = %addr, "connecting to BuildKit daemon");
|
||||
|
||||
let channel = if addr.starts_with("unix://") {
|
||||
let socket_path = addr
|
||||
.strip_prefix("unix://")
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
// Verify the socket exists before attempting connection.
|
||||
if !Path::new(&socket_path).exists() {
|
||||
return Err(WfeError::StepExecution(format!(
|
||||
"BuildKit socket not found: {socket_path}"
|
||||
)));
|
||||
}
|
||||
|
||||
// tonic requires a dummy URI for Unix sockets; the actual path
|
||||
// is provided via the connector.
|
||||
Endpoint::try_from("http://[::]:50051")
|
||||
.map_err(|e| {
|
||||
WfeError::StepExecution(format!("failed to create endpoint: {e}"))
|
||||
})?
|
||||
.connect_with_connector(tower::service_fn(move |_: Uri| {
|
||||
let path = socket_path.clone();
|
||||
async move {
|
||||
tokio::net::UnixStream::connect(path)
|
||||
.await
|
||||
.map(hyper_util::rt::TokioIo::new)
|
||||
}
|
||||
}))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
WfeError::StepExecution(format!(
|
||||
"failed to connect to buildkitd via Unix socket at {addr}: {e}"
|
||||
))
|
||||
})?
|
||||
} else {
|
||||
// TCP or HTTP endpoint.
|
||||
let connect_addr = if addr.starts_with("tcp://") {
|
||||
addr.replacen("tcp://", "http://", 1)
|
||||
} else {
|
||||
addr.clone()
|
||||
};
|
||||
|
||||
Endpoint::from_shared(connect_addr.clone())
|
||||
.map_err(|e| {
|
||||
WfeError::StepExecution(format!(
|
||||
"invalid BuildKit endpoint {connect_addr}: {e}"
|
||||
))
|
||||
})?
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.connect()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
WfeError::StepExecution(format!(
|
||||
"failed to connect to buildkitd at {connect_addr}: {e}"
|
||||
))
|
||||
})?
|
||||
};
|
||||
|
||||
Ok(ControlClient::new(channel))
|
||||
}
|
||||
|
||||
/// Build frontend attributes from the current configuration.
|
||||
///
|
||||
/// These attributes tell the BuildKit dockerfile frontend how to process
|
||||
/// the build: which file to use, which target stage, build arguments, etc.
|
||||
fn build_frontend_attrs(&self) -> HashMap<String, String> {
|
||||
let mut attrs = HashMap::new();
|
||||
|
||||
// Dockerfile filename (relative to context).
|
||||
if self.config.dockerfile != "Dockerfile" {
|
||||
attrs.insert("filename".to_string(), self.config.dockerfile.clone());
|
||||
}
|
||||
|
||||
// Target stage for multi-stage builds.
|
||||
if let Some(ref target) = self.config.target {
|
||||
attrs.insert("target".to_string(), target.clone());
|
||||
}
|
||||
|
||||
// Build arguments (sorted for determinism).
|
||||
let mut sorted_args: Vec<_> = self.config.build_args.iter().collect();
|
||||
sorted_args.sort_by_key(|(k, _)| (*k).clone());
|
||||
for (key, value) in &sorted_args {
|
||||
attrs.insert(format!("build-arg:{key}"), value.to_string());
|
||||
}
|
||||
|
||||
attrs
|
||||
}
|
||||
|
||||
/// Build exporter configuration for image output.
|
||||
fn build_exporters(&self) -> Vec<Exporter> {
|
||||
if self.config.tags.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
|
||||
let mut export_attrs = HashMap::new();
|
||||
export_attrs.insert("name".to_string(), self.config.tags.join(","));
|
||||
if self.config.push {
|
||||
export_attrs.insert("push".to_string(), "true".to_string());
|
||||
}
|
||||
|
||||
vec![Exporter {
|
||||
r#type: "image".to_string(),
|
||||
attrs: export_attrs,
|
||||
}]
|
||||
}
|
||||
|
||||
/// Build cache options from the configuration.
|
||||
fn build_cache_options(&self) -> Option<CacheOptions> {
|
||||
if self.config.cache_from.is_empty() && self.config.cache_to.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let imports = self
|
||||
.config
|
||||
.cache_from
|
||||
.iter()
|
||||
.map(|source| {
|
||||
let mut attrs = HashMap::new();
|
||||
attrs.insert("ref".to_string(), source.clone());
|
||||
CacheOptionsEntry {
|
||||
r#type: "registry".to_string(),
|
||||
attrs,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let exports = self
|
||||
.config
|
||||
.cache_to
|
||||
.iter()
|
||||
.map(|dest| {
|
||||
let mut attrs = HashMap::new();
|
||||
attrs.insert("ref".to_string(), dest.clone());
|
||||
attrs.insert("mode".to_string(), "max".to_string());
|
||||
CacheOptionsEntry {
|
||||
r#type: "registry".to_string(),
|
||||
attrs,
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(CacheOptions {
|
||||
export_ref_deprecated: String::new(),
|
||||
import_refs_deprecated: vec![],
|
||||
export_attrs_deprecated: HashMap::new(),
|
||||
exports,
|
||||
imports,
|
||||
})
|
||||
}
|
||||
|
||||
/// Execute the build against a connected BuildKit daemon.
|
||||
///
|
||||
/// Constructs a `SolveRequest` using the dockerfile.v0 frontend and
|
||||
/// sends it via the Control gRPC service. The build context must be
|
||||
/// accessible to the daemon on its local filesystem (shared mount or
|
||||
/// same machine).
|
||||
///
|
||||
/// # Session protocol
|
||||
///
|
||||
/// TODO: For remote daemons where the build context is not on the same
|
||||
/// filesystem, a full session protocol implementation is needed to
|
||||
/// transfer files. Currently we rely on the context directory being
|
||||
/// available to buildkitd (e.g., via a shared mount in Lima/colima).
|
||||
async fn execute_build(
|
||||
&self,
|
||||
control: &mut ControlClient<Channel>,
|
||||
) -> Result<BuildResult, WfeError> {
|
||||
let build_ref = format!("wfe-build-{}", uuid::Uuid::new_v4());
|
||||
let session_id = uuid::Uuid::new_v4().to_string();
|
||||
|
||||
// Resolve the absolute context path.
|
||||
let abs_context = std::fs::canonicalize(&self.config.context).map_err(|e| {
|
||||
WfeError::StepExecution(format!(
|
||||
"failed to resolve context path {}: {e}",
|
||||
self.config.context
|
||||
))
|
||||
})?;
|
||||
|
||||
// Build frontend attributes with local context references.
|
||||
let mut frontend_attrs = self.build_frontend_attrs();
|
||||
|
||||
// Point the frontend at the daemon-local context directory.
|
||||
// The "context" attr tells the dockerfile frontend where to find
|
||||
// the build context. For local builds we use the local source type
|
||||
// with a shared-key reference.
|
||||
let context_name = "context";
|
||||
let dockerfile_name = "dockerfile";
|
||||
|
||||
frontend_attrs.insert(
|
||||
"context".to_string(),
|
||||
format!("local://{context_name}"),
|
||||
);
|
||||
frontend_attrs.insert(
|
||||
format!("local-sessionid:{context_name}"),
|
||||
session_id.clone(),
|
||||
);
|
||||
|
||||
// Also provide the dockerfile source as a local reference.
|
||||
frontend_attrs.insert(
|
||||
"dockerfilekey".to_string(),
|
||||
format!("local://{dockerfile_name}"),
|
||||
);
|
||||
frontend_attrs.insert(
|
||||
format!("local-sessionid:{dockerfile_name}"),
|
||||
session_id.clone(),
|
||||
);
|
||||
|
||||
let request = SolveRequest {
|
||||
r#ref: build_ref.clone(),
|
||||
definition: None,
|
||||
exporter_deprecated: String::new(),
|
||||
exporter_attrs_deprecated: HashMap::new(),
|
||||
session: session_id.clone(),
|
||||
frontend: "dockerfile.v0".to_string(),
|
||||
frontend_attrs,
|
||||
cache: self.build_cache_options(),
|
||||
entitlements: vec![],
|
||||
frontend_inputs: HashMap::new(),
|
||||
internal: false,
|
||||
source_policy: None,
|
||||
exporters: self.build_exporters(),
|
||||
enable_session_exporter: false,
|
||||
source_policy_session: String::new(),
|
||||
};
|
||||
|
||||
// Attach session metadata headers so buildkitd knows which
|
||||
// session provides the local source content.
|
||||
let mut grpc_request = tonic::Request::new(request);
|
||||
let metadata = grpc_request.metadata_mut();
|
||||
|
||||
// The x-docker-expose-session-uuid header tells buildkitd which
|
||||
// session owns the local sources. The x-docker-expose-session-grpc-method
|
||||
// header lists the gRPC methods the session implements.
|
||||
if let Ok(key) =
|
||||
"x-docker-expose-session-uuid"
|
||||
.parse::<tonic::metadata::MetadataKey<tonic::metadata::Ascii>>()
|
||||
&& let Ok(val) = session_id
|
||||
.parse::<tonic::metadata::MetadataValue<tonic::metadata::Ascii>>()
|
||||
{
|
||||
metadata.insert(key, val);
|
||||
}
|
||||
|
||||
// Advertise the filesync method so the daemon knows it can request
|
||||
// local file content from our session.
|
||||
if let Ok(key) =
|
||||
"x-docker-expose-session-grpc-method"
|
||||
.parse::<tonic::metadata::MetadataKey<tonic::metadata::Ascii>>()
|
||||
{
|
||||
if let Ok(val) = "/moby.filesync.v1.FileSync/DiffCopy"
|
||||
.parse::<tonic::metadata::MetadataValue<tonic::metadata::Ascii>>()
|
||||
{
|
||||
metadata.append(key.clone(), val);
|
||||
}
|
||||
if let Ok(val) = "/moby.filesync.v1.Auth/Credentials"
|
||||
.parse::<tonic::metadata::MetadataValue<tonic::metadata::Ascii>>()
|
||||
{
|
||||
metadata.append(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
tracing::info!(
|
||||
context = %abs_context.display(),
|
||||
session_id = %session_id,
|
||||
"sending solve request to BuildKit"
|
||||
);
|
||||
|
||||
let response = control
|
||||
.solve(grpc_request)
|
||||
.await
|
||||
.map_err(|e| WfeError::StepExecution(format!("BuildKit solve failed: {e}")))?;
|
||||
let solve_response = response.into_inner();
|
||||
|
||||
// Monitor progress (non-blocking, best effort).
|
||||
let status_request = StatusRequest {
|
||||
r#ref: build_ref.clone(),
|
||||
};
|
||||
if let Ok(stream_resp) = control.status(status_request).await {
|
||||
let mut stream = stream_resp.into_inner();
|
||||
while let Some(Ok(status)) = stream.next().await {
|
||||
for vertex in &status.vertexes {
|
||||
if !vertex.name.is_empty() {
|
||||
tracing::debug!(vertex = %vertex.name, "build progress");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract digest.
|
||||
let digest = solve_response
|
||||
.exporter_response
|
||||
.get("containerimage.digest")
|
||||
.cloned();
|
||||
|
||||
tracing::info!(digest = ?digest, "build completed");
|
||||
|
||||
Ok(BuildResult {
|
||||
digest,
|
||||
metadata: solve_response.exporter_response,
|
||||
})
|
||||
}
|
||||
|
||||
/// Build environment variables for registry authentication.
|
||||
///
|
||||
/// This is still useful when the BuildKit daemon reads credentials from
|
||||
/// environment variables rather than session-based auth.
|
||||
pub fn build_registry_env(&self) -> HashMap<String, String> {
|
||||
let mut env = HashMap::new();
|
||||
for (host, auth) in &self.config.registry_auth {
|
||||
let sanitized_host = host.replace(['.', '-'], "_").to_uppercase();
|
||||
env.insert(
|
||||
format!("BUILDKIT_HOST_{sanitized_host}_USERNAME"),
|
||||
auth.username.clone(),
|
||||
);
|
||||
env.insert(
|
||||
format!("BUILDKIT_HOST_{sanitized_host}_PASSWORD"),
|
||||
auth.password.clone(),
|
||||
);
|
||||
}
|
||||
env
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse the image digest from buildctl or BuildKit progress output.
|
||||
///
|
||||
/// Looks for patterns like `exporting manifest sha256:<hex>` or
|
||||
/// `digest: sha256:<hex>` or the raw `containerimage.digest` value.
|
||||
pub fn parse_digest(output: &str) -> Option<String> {
|
||||
let re = Regex::new(r"(?:exporting manifest |digest: )sha256:([a-f0-9]{64})").unwrap();
|
||||
re.captures(output)
|
||||
.map(|caps| format!("sha256:{}", &caps[1]))
|
||||
}
|
||||
|
||||
/// Build the output data JSON object from step execution results.
|
||||
///
|
||||
/// Assembles a `serde_json::Value::Object` containing the step's stdout,
|
||||
/// stderr, digest (if found), and tags (if any).
|
||||
pub fn build_output_data(
|
||||
step_name: &str,
|
||||
stdout: &str,
|
||||
stderr: &str,
|
||||
digest: Option<&str>,
|
||||
tags: &[String],
|
||||
) -> serde_json::Value {
|
||||
let mut outputs = serde_json::Map::new();
|
||||
|
||||
if let Some(digest) = digest {
|
||||
outputs.insert(
|
||||
format!("{step_name}.digest"),
|
||||
serde_json::Value::String(digest.to_string()),
|
||||
);
|
||||
}
|
||||
|
||||
if !tags.is_empty() {
|
||||
outputs.insert(
|
||||
format!("{step_name}.tags"),
|
||||
serde_json::Value::Array(
|
||||
tags.iter()
|
||||
.map(|t| serde_json::Value::String(t.clone()))
|
||||
.collect(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
outputs.insert(
|
||||
format!("{step_name}.stdout"),
|
||||
serde_json::Value::String(stdout.to_string()),
|
||||
);
|
||||
outputs.insert(
|
||||
format!("{step_name}.stderr"),
|
||||
serde_json::Value::String(stderr.to_string()),
|
||||
);
|
||||
|
||||
serde_json::Value::Object(outputs)
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl StepBody for BuildkitStep {
|
||||
async fn run(
|
||||
&mut self,
|
||||
context: &StepExecutionContext<'_>,
|
||||
) -> wfe_core::Result<ExecutionResult> {
|
||||
let step_name = context.step.name.as_deref().unwrap_or("unknown");
|
||||
|
||||
// Connect to the BuildKit daemon.
|
||||
let mut control = self.connect().await?;
|
||||
|
||||
tracing::info!(step = step_name, "submitting build to BuildKit");
|
||||
|
||||
// Execute the build with optional timeout.
|
||||
let result = if let Some(timeout_ms) = self.config.timeout_ms {
|
||||
let duration = std::time::Duration::from_millis(timeout_ms);
|
||||
match tokio::time::timeout(duration, self.execute_build(&mut control)).await {
|
||||
Ok(Ok(result)) => result,
|
||||
Ok(Err(e)) => return Err(e),
|
||||
Err(_) => {
|
||||
return Err(WfeError::StepExecution(format!(
|
||||
"BuildKit build timed out after {timeout_ms}ms"
|
||||
)));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.execute_build(&mut control).await?
|
||||
};
|
||||
|
||||
// Extract digest from BuildResult.
|
||||
let digest = result.digest.clone();
|
||||
|
||||
tracing::info!(
|
||||
step = step_name,
|
||||
digest = ?digest,
|
||||
"build completed"
|
||||
);
|
||||
|
||||
let output_data = build_output_data(
|
||||
step_name,
|
||||
"", // gRPC builds don't produce traditional stdout
|
||||
"", // gRPC builds don't produce traditional stderr
|
||||
digest.as_deref(),
|
||||
&self.config.tags,
|
||||
);
|
||||
|
||||
Ok(ExecutionResult {
|
||||
proceed: true,
|
||||
output_data: Some(output_data),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::config::{BuildkitConfig, RegistryAuth, TlsConfig};
|
||||
|
||||
fn minimal_config() -> BuildkitConfig {
|
||||
BuildkitConfig {
|
||||
dockerfile: "Dockerfile".to_string(),
|
||||
context: ".".to_string(),
|
||||
target: None,
|
||||
tags: vec![],
|
||||
build_args: HashMap::new(),
|
||||
cache_from: vec![],
|
||||
cache_to: vec![],
|
||||
push: false,
|
||||
output_type: None,
|
||||
buildkit_addr: "unix:///run/buildkit/buildkitd.sock".to_string(),
|
||||
tls: TlsConfig::default(),
|
||||
registry_auth: HashMap::new(),
|
||||
timeout_ms: None,
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// build_registry_env tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn build_registry_env_with_auth() {
|
||||
let mut config = minimal_config();
|
||||
config.registry_auth.insert(
|
||||
"ghcr.io".to_string(),
|
||||
RegistryAuth {
|
||||
username: "user".to_string(),
|
||||
password: "token".to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
let step = BuildkitStep::new(config);
|
||||
let env = step.build_registry_env();
|
||||
|
||||
assert_eq!(
|
||||
env.get("BUILDKIT_HOST_GHCR_IO_USERNAME"),
|
||||
Some(&"user".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
env.get("BUILDKIT_HOST_GHCR_IO_PASSWORD"),
|
||||
Some(&"token".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_registry_env_sanitizes_host() {
|
||||
let mut config = minimal_config();
|
||||
config.registry_auth.insert(
|
||||
"my-registry.example.com".to_string(),
|
||||
RegistryAuth {
|
||||
username: "u".to_string(),
|
||||
password: "p".to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
let step = BuildkitStep::new(config);
|
||||
let env = step.build_registry_env();
|
||||
|
||||
assert!(env.contains_key("BUILDKIT_HOST_MY_REGISTRY_EXAMPLE_COM_USERNAME"));
|
||||
assert!(env.contains_key("BUILDKIT_HOST_MY_REGISTRY_EXAMPLE_COM_PASSWORD"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_registry_env_empty_when_no_auth() {
|
||||
let step = BuildkitStep::new(minimal_config());
|
||||
let env = step.build_registry_env();
|
||||
assert!(env.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_registry_env_multiple_registries() {
|
||||
let mut config = minimal_config();
|
||||
config.registry_auth.insert(
|
||||
"ghcr.io".to_string(),
|
||||
RegistryAuth {
|
||||
username: "gh_user".to_string(),
|
||||
password: "gh_pass".to_string(),
|
||||
},
|
||||
);
|
||||
config.registry_auth.insert(
|
||||
"docker.io".to_string(),
|
||||
RegistryAuth {
|
||||
username: "dh_user".to_string(),
|
||||
password: "dh_pass".to_string(),
|
||||
},
|
||||
);
|
||||
|
||||
let step = BuildkitStep::new(config);
|
||||
let env = step.build_registry_env();
|
||||
|
||||
assert_eq!(env.len(), 4);
|
||||
assert_eq!(env["BUILDKIT_HOST_GHCR_IO_USERNAME"], "gh_user");
|
||||
assert_eq!(env["BUILDKIT_HOST_GHCR_IO_PASSWORD"], "gh_pass");
|
||||
assert_eq!(env["BUILDKIT_HOST_DOCKER_IO_USERNAME"], "dh_user");
|
||||
assert_eq!(env["BUILDKIT_HOST_DOCKER_IO_PASSWORD"], "dh_pass");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// parse_digest tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn parse_digest_from_output() {
|
||||
let output = "some build output\nexporting manifest sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789\ndone";
|
||||
let digest = parse_digest(output);
|
||||
assert_eq!(
|
||||
digest,
|
||||
Some(
|
||||
"sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789"
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_with_digest_prefix() {
|
||||
let output = "digest: sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef\n";
|
||||
let digest = parse_digest(output);
|
||||
assert_eq!(
|
||||
digest,
|
||||
Some(
|
||||
"sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
||||
.to_string()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_missing_returns_none() {
|
||||
let output = "building image...\nall done!";
|
||||
let digest = parse_digest(output);
|
||||
assert_eq!(digest, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_partial_hash_returns_none() {
|
||||
let output = "exporting manifest sha256:abcdef";
|
||||
let digest = parse_digest(output);
|
||||
assert_eq!(digest, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_empty_input() {
|
||||
assert_eq!(parse_digest(""), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_wrong_prefix() {
|
||||
let output =
|
||||
"sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789";
|
||||
assert_eq!(parse_digest(output), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_uppercase_hex_returns_none() {
|
||||
let output = "exporting manifest sha256:ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789";
|
||||
assert_eq!(parse_digest(output), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_multiline_with_noise() {
|
||||
let output = r#"
|
||||
[+] Building 12.3s (8/8) FINISHED
|
||||
=> exporting to image
|
||||
=> exporting manifest sha256:aabbccdd0011223344556677aabbccdd0011223344556677aabbccdd00112233
|
||||
=> done
|
||||
"#;
|
||||
assert_eq!(
|
||||
parse_digest(output),
|
||||
Some("sha256:aabbccdd0011223344556677aabbccdd0011223344556677aabbccdd00112233".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_digest_first_match_wins() {
|
||||
let hash1 = "a".repeat(64);
|
||||
let hash2 = "b".repeat(64);
|
||||
let output = format!(
|
||||
"exporting manifest sha256:{hash1}\ndigest: sha256:{hash2}"
|
||||
);
|
||||
let digest = parse_digest(&output).unwrap();
|
||||
assert_eq!(digest, format!("sha256:{hash1}"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// build_output_data tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn build_output_data_with_digest_and_tags() {
|
||||
let digest = "sha256:abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789";
|
||||
let tags = vec!["myapp:latest".to_string(), "myapp:v1".to_string()];
|
||||
let result = build_output_data("build", "out", "err", Some(digest), &tags);
|
||||
|
||||
let obj = result.as_object().unwrap();
|
||||
assert_eq!(obj["build.digest"], digest);
|
||||
assert_eq!(
|
||||
obj["build.tags"],
|
||||
serde_json::json!(["myapp:latest", "myapp:v1"])
|
||||
);
|
||||
assert_eq!(obj["build.stdout"], "out");
|
||||
assert_eq!(obj["build.stderr"], "err");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_output_data_without_digest() {
|
||||
let result = build_output_data("step1", "hello", "", None, &[]);
|
||||
|
||||
let obj = result.as_object().unwrap();
|
||||
assert!(!obj.contains_key("step1.digest"));
|
||||
assert!(!obj.contains_key("step1.tags"));
|
||||
assert_eq!(obj["step1.stdout"], "hello");
|
||||
assert_eq!(obj["step1.stderr"], "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_output_data_with_digest_no_tags() {
|
||||
let digest = "sha256:0000000000000000000000000000000000000000000000000000000000000000";
|
||||
let result = build_output_data("img", "ok", "warn", Some(digest), &[]);
|
||||
|
||||
let obj = result.as_object().unwrap();
|
||||
assert_eq!(obj["img.digest"], digest);
|
||||
assert!(!obj.contains_key("img.tags"));
|
||||
assert_eq!(obj["img.stdout"], "ok");
|
||||
assert_eq!(obj["img.stderr"], "warn");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_output_data_no_digest_with_tags() {
|
||||
let tags = vec!["app:v2".to_string()];
|
||||
let result = build_output_data("s", "", "", None, &tags);
|
||||
|
||||
let obj = result.as_object().unwrap();
|
||||
assert!(!obj.contains_key("s.digest"));
|
||||
assert_eq!(obj["s.tags"], serde_json::json!(["app:v2"]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_output_data_empty_strings() {
|
||||
let result = build_output_data("x", "", "", None, &[]);
|
||||
let obj = result.as_object().unwrap();
|
||||
assert_eq!(obj["x.stdout"], "");
|
||||
assert_eq!(obj["x.stderr"], "");
|
||||
assert_eq!(obj.len(), 2);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// build_frontend_attrs tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn frontend_attrs_minimal() {
|
||||
let step = BuildkitStep::new(minimal_config());
|
||||
let attrs = step.build_frontend_attrs();
|
||||
// Default Dockerfile name is not included (only non-default).
|
||||
assert!(!attrs.contains_key("filename"));
|
||||
assert!(!attrs.contains_key("target"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frontend_attrs_with_target() {
|
||||
let mut config = minimal_config();
|
||||
config.target = Some("runtime".to_string());
|
||||
let step = BuildkitStep::new(config);
|
||||
let attrs = step.build_frontend_attrs();
|
||||
assert_eq!(attrs.get("target"), Some(&"runtime".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frontend_attrs_with_custom_dockerfile() {
|
||||
let mut config = minimal_config();
|
||||
config.dockerfile = "docker/Dockerfile.prod".to_string();
|
||||
let step = BuildkitStep::new(config);
|
||||
let attrs = step.build_frontend_attrs();
|
||||
assert_eq!(
|
||||
attrs.get("filename"),
|
||||
Some(&"docker/Dockerfile.prod".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frontend_attrs_with_build_args() {
|
||||
let mut config = minimal_config();
|
||||
config
|
||||
.build_args
|
||||
.insert("RUST_VERSION".to_string(), "1.78".to_string());
|
||||
config
|
||||
.build_args
|
||||
.insert("BUILD_MODE".to_string(), "release".to_string());
|
||||
let step = BuildkitStep::new(config);
|
||||
let attrs = step.build_frontend_attrs();
|
||||
assert_eq!(
|
||||
attrs.get("build-arg:BUILD_MODE"),
|
||||
Some(&"release".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
attrs.get("build-arg:RUST_VERSION"),
|
||||
Some(&"1.78".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// build_exporters tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn exporters_empty_when_no_tags() {
|
||||
let step = BuildkitStep::new(minimal_config());
|
||||
assert!(step.build_exporters().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exporters_with_tags_and_push() {
|
||||
let mut config = minimal_config();
|
||||
config.tags = vec!["myapp:latest".to_string(), "myapp:v1.0".to_string()];
|
||||
config.push = true;
|
||||
let step = BuildkitStep::new(config);
|
||||
let exporters = step.build_exporters();
|
||||
assert_eq!(exporters.len(), 1);
|
||||
assert_eq!(exporters[0].r#type, "image");
|
||||
assert_eq!(
|
||||
exporters[0].attrs.get("name"),
|
||||
Some(&"myapp:latest,myapp:v1.0".to_string())
|
||||
);
|
||||
assert_eq!(
|
||||
exporters[0].attrs.get("push"),
|
||||
Some(&"true".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exporters_with_tags_no_push() {
|
||||
let mut config = minimal_config();
|
||||
config.tags = vec!["myapp:latest".to_string()];
|
||||
config.push = false;
|
||||
let step = BuildkitStep::new(config);
|
||||
let exporters = step.build_exporters();
|
||||
assert_eq!(exporters.len(), 1);
|
||||
assert!(!exporters[0].attrs.contains_key("push"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// build_cache_options tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn cache_options_none_when_empty() {
|
||||
let step = BuildkitStep::new(minimal_config());
|
||||
assert!(step.build_cache_options().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cache_options_with_imports_and_exports() {
|
||||
let mut config = minimal_config();
|
||||
config.cache_from = vec!["type=registry,ref=myapp:cache".to_string()];
|
||||
config.cache_to = vec!["type=registry,ref=myapp:cache,mode=max".to_string()];
|
||||
let step = BuildkitStep::new(config);
|
||||
let opts = step.build_cache_options().unwrap();
|
||||
assert_eq!(opts.imports.len(), 1);
|
||||
assert_eq!(opts.exports.len(), 1);
|
||||
assert_eq!(opts.imports[0].r#type, "registry");
|
||||
assert_eq!(opts.exports[0].r#type, "registry");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// connect helper tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn tcp_addr_converted_to_http() {
|
||||
let mut config = minimal_config();
|
||||
config.buildkit_addr = "tcp://buildkitd:1234".to_string();
|
||||
let step = BuildkitStep::new(config);
|
||||
assert_eq!(step.config.buildkit_addr, "tcp://buildkitd:1234");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unix_addr_preserved() {
|
||||
let config = minimal_config();
|
||||
let step = BuildkitStep::new(config);
|
||||
assert!(step.config.buildkit_addr.starts_with("unix://"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn connect_to_missing_unix_socket_returns_error() {
|
||||
let mut config = minimal_config();
|
||||
config.buildkit_addr = "unix:///tmp/nonexistent-wfe-test.sock".to_string();
|
||||
let step = BuildkitStep::new(config);
|
||||
let err = step.connect().await.unwrap_err();
|
||||
let msg = format!("{err}");
|
||||
assert!(
|
||||
msg.contains("socket not found"),
|
||||
"expected 'socket not found' error, got: {msg}"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn connect_to_invalid_tcp_returns_error() {
|
||||
let mut config = minimal_config();
|
||||
config.buildkit_addr = "tcp://127.0.0.1:1".to_string();
|
||||
let step = BuildkitStep::new(config);
|
||||
let err = step.connect().await.unwrap_err();
|
||||
let msg = format!("{err}");
|
||||
assert!(
|
||||
msg.contains("failed to connect"),
|
||||
"expected connection error, got: {msg}"
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// BuildkitStep construction tests
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
#[test]
|
||||
fn new_step_stores_config() {
|
||||
let config = minimal_config();
|
||||
let step = BuildkitStep::new(config.clone());
|
||||
assert_eq!(step.config.dockerfile, "Dockerfile");
|
||||
assert_eq!(step.config.context, ".");
|
||||
}
|
||||
}
|
||||
237
wfe-buildkit/tests/integration_test.rs
Normal file
237
wfe-buildkit/tests/integration_test.rs
Normal file
@@ -0,0 +1,237 @@
|
||||
//! Integration tests for wfe-buildkit using a real BuildKit daemon.
|
||||
//!
|
||||
//! These tests require a running BuildKit daemon. The socket path is read
|
||||
//! from `WFE_BUILDKIT_ADDR`, falling back to
|
||||
//! `unix:///Users/sienna/.lima/wfe-test/sock/buildkitd.sock`.
|
||||
//!
|
||||
//! If the daemon is not available, the tests are skipped gracefully.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
use wfe_buildkit::config::{BuildkitConfig, TlsConfig};
|
||||
use wfe_buildkit::BuildkitStep;
|
||||
|
||||
use wfe_core::models::{ExecutionPointer, WorkflowInstance, WorkflowStep};
|
||||
use wfe_core::traits::step::{StepBody, StepExecutionContext};
|
||||
|
||||
/// Get the BuildKit daemon address from the environment or use the default.
|
||||
fn buildkit_addr() -> String {
|
||||
std::env::var("WFE_BUILDKIT_ADDR").unwrap_or_else(|_| {
|
||||
"unix:///Users/sienna/.lima/wfe-test/sock/buildkitd.sock".to_string()
|
||||
})
|
||||
}
|
||||
|
||||
/// Check whether the BuildKit daemon socket is reachable.
|
||||
fn buildkitd_available() -> bool {
|
||||
let addr = buildkit_addr();
|
||||
if let Some(path) = addr.strip_prefix("unix://") {
|
||||
Path::new(path).exists()
|
||||
} else {
|
||||
// For TCP endpoints, optimistically assume available.
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn make_test_context(
|
||||
step_name: &str,
|
||||
) -> (
|
||||
WorkflowStep,
|
||||
ExecutionPointer,
|
||||
WorkflowInstance,
|
||||
) {
|
||||
let mut step = WorkflowStep::new(0, "buildkit");
|
||||
step.name = Some(step_name.to_string());
|
||||
let pointer = ExecutionPointer::new(0);
|
||||
let instance = WorkflowInstance::new("test-wf", 1, serde_json::json!({}));
|
||||
(step, pointer, instance)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn build_simple_dockerfile_via_grpc() {
|
||||
if !buildkitd_available() {
|
||||
eprintln!(
|
||||
"SKIP: BuildKit daemon not available at {}",
|
||||
buildkit_addr()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a temp directory with a trivial Dockerfile.
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dockerfile = tmp.path().join("Dockerfile");
|
||||
std::fs::write(
|
||||
&dockerfile,
|
||||
"FROM alpine:latest\nRUN echo built\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let config = BuildkitConfig {
|
||||
dockerfile: "Dockerfile".to_string(),
|
||||
context: tmp.path().to_string_lossy().to_string(),
|
||||
target: None,
|
||||
tags: vec![],
|
||||
build_args: HashMap::new(),
|
||||
cache_from: vec![],
|
||||
cache_to: vec![],
|
||||
push: false,
|
||||
output_type: None,
|
||||
buildkit_addr: buildkit_addr(),
|
||||
tls: TlsConfig::default(),
|
||||
registry_auth: HashMap::new(),
|
||||
timeout_ms: Some(120_000), // 2 minutes
|
||||
};
|
||||
|
||||
let mut step = BuildkitStep::new(config);
|
||||
|
||||
let (ws, pointer, instance) = make_test_context("integration-build");
|
||||
let cancel = tokio_util::sync::CancellationToken::new();
|
||||
let ctx = StepExecutionContext {
|
||||
item: None,
|
||||
execution_pointer: &pointer,
|
||||
persistence_data: None,
|
||||
step: &ws,
|
||||
workflow: &instance,
|
||||
cancellation_token: cancel,
|
||||
host_context: None,
|
||||
log_sink: None,
|
||||
};
|
||||
|
||||
let result = step.run(&ctx).await.expect("build should succeed");
|
||||
|
||||
assert!(result.proceed);
|
||||
|
||||
let data = result.output_data.expect("should have output_data");
|
||||
let obj = data.as_object().expect("output_data should be an object");
|
||||
|
||||
// Without tags/push, BuildKit does not produce a digest in the exporter
|
||||
// response. The build succeeds but the digest is absent.
|
||||
assert!(
|
||||
obj.contains_key("integration-build.stdout"),
|
||||
"expected stdout key, got: {:?}",
|
||||
obj.keys().collect::<Vec<_>>()
|
||||
);
|
||||
assert!(
|
||||
obj.contains_key("integration-build.stderr"),
|
||||
"expected stderr key, got: {:?}",
|
||||
obj.keys().collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// If a digest IS present (e.g., newer buildkitd versions), validate its format.
|
||||
if let Some(digest_val) = obj.get("integration-build.digest") {
|
||||
let digest = digest_val.as_str().unwrap();
|
||||
assert!(
|
||||
digest.starts_with("sha256:"),
|
||||
"digest should start with sha256:, got: {digest}"
|
||||
);
|
||||
assert_eq!(
|
||||
digest.len(),
|
||||
7 + 64,
|
||||
"digest should be sha256:<64hex>, got: {digest}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn build_with_build_args() {
|
||||
if !buildkitd_available() {
|
||||
eprintln!(
|
||||
"SKIP: BuildKit daemon not available at {}",
|
||||
buildkit_addr()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let dockerfile = tmp.path().join("Dockerfile");
|
||||
std::fs::write(
|
||||
&dockerfile,
|
||||
"FROM alpine:latest\nARG MY_VAR=default\nRUN echo \"value=$MY_VAR\"\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut build_args = HashMap::new();
|
||||
build_args.insert("MY_VAR".to_string(), "custom_value".to_string());
|
||||
|
||||
let config = BuildkitConfig {
|
||||
dockerfile: "Dockerfile".to_string(),
|
||||
context: tmp.path().to_string_lossy().to_string(),
|
||||
target: None,
|
||||
tags: vec![],
|
||||
build_args,
|
||||
cache_from: vec![],
|
||||
cache_to: vec![],
|
||||
push: false,
|
||||
output_type: None,
|
||||
buildkit_addr: buildkit_addr(),
|
||||
tls: TlsConfig::default(),
|
||||
registry_auth: HashMap::new(),
|
||||
timeout_ms: Some(120_000),
|
||||
};
|
||||
|
||||
let mut step = BuildkitStep::new(config);
|
||||
|
||||
let (ws, pointer, instance) = make_test_context("build-args-test");
|
||||
let cancel = tokio_util::sync::CancellationToken::new();
|
||||
let ctx = StepExecutionContext {
|
||||
item: None,
|
||||
execution_pointer: &pointer,
|
||||
persistence_data: None,
|
||||
step: &ws,
|
||||
workflow: &instance,
|
||||
cancellation_token: cancel,
|
||||
host_context: None,
|
||||
log_sink: None,
|
||||
};
|
||||
|
||||
let result = step.run(&ctx).await.expect("build with args should succeed");
|
||||
assert!(result.proceed);
|
||||
|
||||
let data = result.output_data.expect("should have output_data");
|
||||
let obj = data.as_object().unwrap();
|
||||
|
||||
// Build should complete and produce output data entries.
|
||||
assert!(
|
||||
obj.contains_key("build-args-test.stdout"),
|
||||
"expected stdout key, got: {:?}",
|
||||
obj.keys().collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn connect_to_unavailable_daemon_returns_error() {
|
||||
// Use a deliberately wrong address to test error handling.
|
||||
let config = BuildkitConfig {
|
||||
dockerfile: "Dockerfile".to_string(),
|
||||
context: ".".to_string(),
|
||||
target: None,
|
||||
tags: vec![],
|
||||
build_args: HashMap::new(),
|
||||
cache_from: vec![],
|
||||
cache_to: vec![],
|
||||
push: false,
|
||||
output_type: None,
|
||||
buildkit_addr: "unix:///tmp/nonexistent-buildkitd.sock".to_string(),
|
||||
tls: TlsConfig::default(),
|
||||
registry_auth: HashMap::new(),
|
||||
timeout_ms: Some(5_000),
|
||||
};
|
||||
|
||||
let mut step = BuildkitStep::new(config);
|
||||
|
||||
let (ws, pointer, instance) = make_test_context("error-test");
|
||||
let cancel = tokio_util::sync::CancellationToken::new();
|
||||
let ctx = StepExecutionContext {
|
||||
item: None,
|
||||
execution_pointer: &pointer,
|
||||
persistence_data: None,
|
||||
step: &ws,
|
||||
workflow: &instance,
|
||||
cancellation_token: cancel,
|
||||
host_context: None,
|
||||
log_sink: None,
|
||||
};
|
||||
|
||||
let err = step.run(&ctx).await;
|
||||
assert!(err.is_err(), "should fail when daemon is unavailable");
|
||||
}
|
||||
19
wfe-containerd-protos/Cargo.toml
Normal file
19
wfe-containerd-protos/Cargo.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "wfe-containerd-protos"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
homepage.workspace = true
|
||||
description = "Generated gRPC stubs for the full containerd API"
|
||||
|
||||
[dependencies]
|
||||
tonic = "0.14"
|
||||
tonic-prost = "0.14"
|
||||
prost = "0.14"
|
||||
prost-types = "0.14"
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = "0.14"
|
||||
tonic-prost-build = "0.14"
|
||||
prost-build = "0.14"
|
||||
50
wfe-containerd-protos/build.rs
Normal file
50
wfe-containerd-protos/build.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let api_dir = PathBuf::from("proto/api");
|
||||
|
||||
// Collect all .proto files, excluding internal runtime shim protos
|
||||
let proto_files: Vec<PathBuf> = walkdir(&api_dir)?
|
||||
.into_iter()
|
||||
.filter(|p| {
|
||||
let s = p.to_string_lossy();
|
||||
!s.contains("/runtime/task/") && !s.contains("/runtime/sandbox/")
|
||||
})
|
||||
.collect();
|
||||
|
||||
println!(
|
||||
"cargo:warning=Compiling {} containerd proto files",
|
||||
proto_files.len()
|
||||
);
|
||||
|
||||
let _out_dir = PathBuf::from(std::env::var("OUT_DIR")?);
|
||||
|
||||
// Use tonic-prost-build (the tonic 0.14 way)
|
||||
let mut prost_config = prost_build::Config::new();
|
||||
prost_config.include_file("mod.rs");
|
||||
|
||||
tonic_prost_build::configure()
|
||||
.build_server(false)
|
||||
.compile_with_config(
|
||||
prost_config,
|
||||
&proto_files,
|
||||
&[api_dir, PathBuf::from("proto")],
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Recursively collect all .proto files under a directory.
|
||||
fn walkdir(dir: &PathBuf) -> Result<Vec<PathBuf>, Box<dyn std::error::Error>> {
|
||||
let mut protos = Vec::new();
|
||||
for entry in std::fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
protos.extend(walkdir(&path)?);
|
||||
} else if path.extension().is_some_and(|ext| ext == "proto") {
|
||||
protos.push(path);
|
||||
}
|
||||
}
|
||||
Ok(protos)
|
||||
}
|
||||
46
wfe-containerd-protos/proto/api/events/container.proto
Normal file
46
wfe-containerd-protos/proto/api/events/container.proto
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message ContainerCreate {
|
||||
string id = 1;
|
||||
string image = 2;
|
||||
message Runtime {
|
||||
string name = 1;
|
||||
google.protobuf.Any options = 2;
|
||||
}
|
||||
Runtime runtime = 3;
|
||||
}
|
||||
|
||||
message ContainerUpdate {
|
||||
string id = 1;
|
||||
string image = 2;
|
||||
map<string, string> labels = 3;
|
||||
string snapshot_key = 4;
|
||||
}
|
||||
|
||||
message ContainerDelete {
|
||||
string id = 1;
|
||||
}
|
||||
33
wfe-containerd-protos/proto/api/events/content.proto
Normal file
33
wfe-containerd-protos/proto/api/events/content.proto
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message ContentCreate {
|
||||
string digest = 1;
|
||||
int64 size = 2;
|
||||
}
|
||||
|
||||
message ContentDelete {
|
||||
string digest = 1;
|
||||
}
|
||||
38
wfe-containerd-protos/proto/api/events/image.proto
Normal file
38
wfe-containerd-protos/proto/api/events/image.proto
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.images.v1;
|
||||
|
||||
import "types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message ImageCreate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message ImageUpdate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message ImageDelete {
|
||||
string name = 1;
|
||||
}
|
||||
38
wfe-containerd-protos/proto/api/events/namespace.proto
Normal file
38
wfe-containerd-protos/proto/api/events/namespace.proto
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message NamespaceCreate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message NamespaceUpdate {
|
||||
string name = 1;
|
||||
map<string, string> labels = 2;
|
||||
}
|
||||
|
||||
message NamespaceDelete {
|
||||
string name = 1;
|
||||
}
|
||||
37
wfe-containerd-protos/proto/api/events/sandbox.proto
Normal file
37
wfe-containerd-protos/proto/api/events/sandbox.proto
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
|
||||
message SandboxCreate {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message SandboxStart {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message SandboxExit {
|
||||
string sandbox_id = 1;
|
||||
uint32 exit_status = 2;
|
||||
google.protobuf.Timestamp exited_at = 3;
|
||||
}
|
||||
41
wfe-containerd-protos/proto/api/events/snapshot.proto
Normal file
41
wfe-containerd-protos/proto/api/events/snapshot.proto
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "types/fieldpath.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message SnapshotPrepare {
|
||||
string key = 1;
|
||||
string parent = 2;
|
||||
string snapshotter = 5;
|
||||
}
|
||||
|
||||
message SnapshotCommit {
|
||||
string key = 1;
|
||||
string name = 2;
|
||||
string snapshotter = 5;
|
||||
}
|
||||
|
||||
message SnapshotRemove {
|
||||
string key = 1;
|
||||
string snapshotter = 5;
|
||||
}
|
||||
93
wfe-containerd-protos/proto/api/events/task.proto
Normal file
93
wfe-containerd-protos/proto/api/events/task.proto
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.events;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "types/fieldpath.proto";
|
||||
import "types/mount.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/events;events";
|
||||
option (containerd.types.fieldpath_all) = true;
|
||||
|
||||
message TaskCreate {
|
||||
string container_id = 1;
|
||||
string bundle = 2;
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
TaskIO io = 4;
|
||||
string checkpoint = 5;
|
||||
uint32 pid = 6;
|
||||
}
|
||||
|
||||
message TaskStart {
|
||||
string container_id = 1;
|
||||
uint32 pid = 2;
|
||||
}
|
||||
|
||||
message TaskDelete {
|
||||
string container_id = 1;
|
||||
uint32 pid = 2;
|
||||
uint32 exit_status = 3;
|
||||
google.protobuf.Timestamp exited_at = 4;
|
||||
// id is the specific exec. By default if omitted will be `""` thus matches
|
||||
// the init exec of the task matching `container_id`.
|
||||
string id = 5;
|
||||
}
|
||||
|
||||
message TaskIO {
|
||||
string stdin = 1;
|
||||
string stdout = 2;
|
||||
string stderr = 3;
|
||||
bool terminal = 4;
|
||||
}
|
||||
|
||||
message TaskExit {
|
||||
string container_id = 1;
|
||||
string id = 2;
|
||||
uint32 pid = 3;
|
||||
uint32 exit_status = 4;
|
||||
google.protobuf.Timestamp exited_at = 5;
|
||||
}
|
||||
|
||||
message TaskOOM {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message TaskExecAdded {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message TaskExecStarted {
|
||||
string container_id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 pid = 3;
|
||||
}
|
||||
|
||||
message TaskPaused {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message TaskResumed {
|
||||
string container_id = 1;
|
||||
}
|
||||
|
||||
message TaskCheckpointed {
|
||||
string container_id = 1;
|
||||
string checkpoint = 2;
|
||||
}
|
||||
149
wfe-containerd-protos/proto/api/runtime/sandbox/v1/sandbox.proto
Normal file
149
wfe-containerd-protos/proto/api/runtime/sandbox/v1/sandbox.proto
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.runtime.sandbox.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "types/metrics.proto";
|
||||
import "types/mount.proto";
|
||||
import "types/platform.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/runtime/sandbox/v1;sandbox";
|
||||
|
||||
// Sandbox is an optional interface that shim may implement to support sandboxes environments.
|
||||
// A typical example of sandbox is microVM or pause container - an entity that groups containers and/or
|
||||
// holds resources relevant for this group.
|
||||
service Sandbox {
|
||||
// CreateSandbox will be called right after sandbox shim instance launched.
|
||||
// It is a good place to initialize sandbox environment.
|
||||
rpc CreateSandbox(CreateSandboxRequest) returns (CreateSandboxResponse);
|
||||
|
||||
// StartSandbox will start a previously created sandbox.
|
||||
rpc StartSandbox(StartSandboxRequest) returns (StartSandboxResponse);
|
||||
|
||||
// Platform queries the platform the sandbox is going to run containers on.
|
||||
// containerd will use this to generate a proper OCI spec.
|
||||
rpc Platform(PlatformRequest) returns (PlatformResponse);
|
||||
|
||||
// StopSandbox will stop existing sandbox instance
|
||||
rpc StopSandbox(StopSandboxRequest) returns (StopSandboxResponse);
|
||||
|
||||
// WaitSandbox blocks until sandbox exits.
|
||||
rpc WaitSandbox(WaitSandboxRequest) returns (WaitSandboxResponse);
|
||||
|
||||
// SandboxStatus will return current status of the running sandbox instance
|
||||
rpc SandboxStatus(SandboxStatusRequest) returns (SandboxStatusResponse);
|
||||
|
||||
// PingSandbox is a lightweight API call to check whether sandbox alive.
|
||||
rpc PingSandbox(PingRequest) returns (PingResponse);
|
||||
|
||||
// ShutdownSandbox must shutdown shim instance.
|
||||
rpc ShutdownSandbox(ShutdownSandboxRequest) returns (ShutdownSandboxResponse);
|
||||
|
||||
// SandboxMetrics retrieves metrics about a sandbox instance.
|
||||
rpc SandboxMetrics(SandboxMetricsRequest) returns (SandboxMetricsResponse);
|
||||
}
|
||||
|
||||
message CreateSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
string bundle_path = 2;
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
google.protobuf.Any options = 4;
|
||||
string netns_path = 5;
|
||||
map<string, string> annotations = 6;
|
||||
}
|
||||
|
||||
message CreateSandboxResponse {}
|
||||
|
||||
message StartSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message StartSandboxResponse {
|
||||
uint32 pid = 1;
|
||||
google.protobuf.Timestamp created_at = 2;
|
||||
google.protobuf.Any spec = 3;
|
||||
}
|
||||
|
||||
message PlatformRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message PlatformResponse {
|
||||
containerd.types.Platform platform = 1;
|
||||
}
|
||||
|
||||
message StopSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
uint32 timeout_secs = 2;
|
||||
}
|
||||
|
||||
message StopSandboxResponse {}
|
||||
|
||||
message UpdateSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
google.protobuf.Any resources = 2;
|
||||
map<string, string> annotations = 3;
|
||||
}
|
||||
|
||||
message WaitSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message WaitSandboxResponse {
|
||||
uint32 exit_status = 1;
|
||||
google.protobuf.Timestamp exited_at = 2;
|
||||
}
|
||||
|
||||
message UpdateSandboxResponse {}
|
||||
|
||||
message SandboxStatusRequest {
|
||||
string sandbox_id = 1;
|
||||
bool verbose = 2;
|
||||
}
|
||||
|
||||
message SandboxStatusResponse {
|
||||
string sandbox_id = 1;
|
||||
uint32 pid = 2;
|
||||
string state = 3;
|
||||
map<string, string> info = 4;
|
||||
google.protobuf.Timestamp created_at = 5;
|
||||
google.protobuf.Timestamp exited_at = 6;
|
||||
google.protobuf.Any extra = 7;
|
||||
}
|
||||
|
||||
message PingRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message PingResponse {}
|
||||
|
||||
message ShutdownSandboxRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message ShutdownSandboxResponse {}
|
||||
|
||||
message SandboxMetricsRequest {
|
||||
string sandbox_id = 1;
|
||||
}
|
||||
|
||||
message SandboxMetricsResponse {
|
||||
containerd.types.Metric metrics = 1;
|
||||
}
|
||||
200
wfe-containerd-protos/proto/api/runtime/task/v2/shim.proto
Normal file
200
wfe-containerd-protos/proto/api/runtime/task/v2/shim.proto
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.task.v2;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "types/mount.proto";
|
||||
import "types/task/task.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/runtime/task/v2;task";
|
||||
|
||||
// Shim service is launched for each container and is responsible for owning the IO
|
||||
// for the container and its additional processes. The shim is also the parent of
|
||||
// each container and allows reattaching to the IO and receiving the exit status
|
||||
// for the container processes.
|
||||
service Task {
|
||||
rpc State(StateRequest) returns (StateResponse);
|
||||
rpc Create(CreateTaskRequest) returns (CreateTaskResponse);
|
||||
rpc Start(StartRequest) returns (StartResponse);
|
||||
rpc Delete(DeleteRequest) returns (DeleteResponse);
|
||||
rpc Pids(PidsRequest) returns (PidsResponse);
|
||||
rpc Pause(PauseRequest) returns (google.protobuf.Empty);
|
||||
rpc Resume(ResumeRequest) returns (google.protobuf.Empty);
|
||||
rpc Checkpoint(CheckpointTaskRequest) returns (google.protobuf.Empty);
|
||||
rpc Kill(KillRequest) returns (google.protobuf.Empty);
|
||||
rpc Exec(ExecProcessRequest) returns (google.protobuf.Empty);
|
||||
rpc ResizePty(ResizePtyRequest) returns (google.protobuf.Empty);
|
||||
rpc CloseIO(CloseIORequest) returns (google.protobuf.Empty);
|
||||
rpc Update(UpdateTaskRequest) returns (google.protobuf.Empty);
|
||||
rpc Wait(WaitRequest) returns (WaitResponse);
|
||||
rpc Stats(StatsRequest) returns (StatsResponse);
|
||||
rpc Connect(ConnectRequest) returns (ConnectResponse);
|
||||
rpc Shutdown(ShutdownRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message CreateTaskRequest {
|
||||
string id = 1;
|
||||
string bundle = 2;
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
bool terminal = 4;
|
||||
string stdin = 5;
|
||||
string stdout = 6;
|
||||
string stderr = 7;
|
||||
string checkpoint = 8;
|
||||
string parent_checkpoint = 9;
|
||||
google.protobuf.Any options = 10;
|
||||
}
|
||||
|
||||
message CreateTaskResponse {
|
||||
uint32 pid = 1;
|
||||
}
|
||||
|
||||
message DeleteRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
uint32 pid = 1;
|
||||
uint32 exit_status = 2;
|
||||
google.protobuf.Timestamp exited_at = 3;
|
||||
}
|
||||
|
||||
message ExecProcessRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
bool terminal = 3;
|
||||
string stdin = 4;
|
||||
string stdout = 5;
|
||||
string stderr = 6;
|
||||
google.protobuf.Any spec = 7;
|
||||
}
|
||||
|
||||
message ExecProcessResponse {}
|
||||
|
||||
message ResizePtyRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 width = 3;
|
||||
uint32 height = 4;
|
||||
}
|
||||
|
||||
message StateRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message StateResponse {
|
||||
string id = 1;
|
||||
string bundle = 2;
|
||||
uint32 pid = 3;
|
||||
containerd.v1.types.Status status = 4;
|
||||
string stdin = 5;
|
||||
string stdout = 6;
|
||||
string stderr = 7;
|
||||
bool terminal = 8;
|
||||
uint32 exit_status = 9;
|
||||
google.protobuf.Timestamp exited_at = 10;
|
||||
string exec_id = 11;
|
||||
}
|
||||
|
||||
message KillRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 signal = 3;
|
||||
bool all = 4;
|
||||
}
|
||||
|
||||
message CloseIORequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
bool stdin = 3;
|
||||
}
|
||||
|
||||
message PidsRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message PidsResponse {
|
||||
repeated containerd.v1.types.ProcessInfo processes = 1;
|
||||
}
|
||||
|
||||
message CheckpointTaskRequest {
|
||||
string id = 1;
|
||||
string path = 2;
|
||||
google.protobuf.Any options = 3;
|
||||
}
|
||||
|
||||
message UpdateTaskRequest {
|
||||
string id = 1;
|
||||
google.protobuf.Any resources = 2;
|
||||
map<string, string> annotations = 3;
|
||||
}
|
||||
|
||||
message StartRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message StartResponse {
|
||||
uint32 pid = 1;
|
||||
}
|
||||
|
||||
message WaitRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message WaitResponse {
|
||||
uint32 exit_status = 1;
|
||||
google.protobuf.Timestamp exited_at = 2;
|
||||
}
|
||||
|
||||
message StatsRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message StatsResponse {
|
||||
google.protobuf.Any stats = 1;
|
||||
}
|
||||
|
||||
message ConnectRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ConnectResponse {
|
||||
uint32 shim_pid = 1;
|
||||
uint32 task_pid = 2;
|
||||
string version = 3;
|
||||
}
|
||||
|
||||
message ShutdownRequest {
|
||||
string id = 1;
|
||||
bool now = 2;
|
||||
}
|
||||
|
||||
message PauseRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ResumeRequest {
|
||||
string id = 1;
|
||||
}
|
||||
200
wfe-containerd-protos/proto/api/runtime/task/v3/shim.proto
Normal file
200
wfe-containerd-protos/proto/api/runtime/task/v3/shim.proto
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.task.v3;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "types/mount.proto";
|
||||
import "types/task/task.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/runtime/task/v3;task";
|
||||
|
||||
// Shim service is launched for each container and is responsible for owning the IO
|
||||
// for the container and its additional processes. The shim is also the parent of
|
||||
// each container and allows reattaching to the IO and receiving the exit status
|
||||
// for the container processes.
|
||||
service Task {
|
||||
rpc State(StateRequest) returns (StateResponse);
|
||||
rpc Create(CreateTaskRequest) returns (CreateTaskResponse);
|
||||
rpc Start(StartRequest) returns (StartResponse);
|
||||
rpc Delete(DeleteRequest) returns (DeleteResponse);
|
||||
rpc Pids(PidsRequest) returns (PidsResponse);
|
||||
rpc Pause(PauseRequest) returns (google.protobuf.Empty);
|
||||
rpc Resume(ResumeRequest) returns (google.protobuf.Empty);
|
||||
rpc Checkpoint(CheckpointTaskRequest) returns (google.protobuf.Empty);
|
||||
rpc Kill(KillRequest) returns (google.protobuf.Empty);
|
||||
rpc Exec(ExecProcessRequest) returns (google.protobuf.Empty);
|
||||
rpc ResizePty(ResizePtyRequest) returns (google.protobuf.Empty);
|
||||
rpc CloseIO(CloseIORequest) returns (google.protobuf.Empty);
|
||||
rpc Update(UpdateTaskRequest) returns (google.protobuf.Empty);
|
||||
rpc Wait(WaitRequest) returns (WaitResponse);
|
||||
rpc Stats(StatsRequest) returns (StatsResponse);
|
||||
rpc Connect(ConnectRequest) returns (ConnectResponse);
|
||||
rpc Shutdown(ShutdownRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message CreateTaskRequest {
|
||||
string id = 1;
|
||||
string bundle = 2;
|
||||
repeated containerd.types.Mount rootfs = 3;
|
||||
bool terminal = 4;
|
||||
string stdin = 5;
|
||||
string stdout = 6;
|
||||
string stderr = 7;
|
||||
string checkpoint = 8;
|
||||
string parent_checkpoint = 9;
|
||||
google.protobuf.Any options = 10;
|
||||
}
|
||||
|
||||
message CreateTaskResponse {
|
||||
uint32 pid = 1;
|
||||
}
|
||||
|
||||
message DeleteRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message DeleteResponse {
|
||||
uint32 pid = 1;
|
||||
uint32 exit_status = 2;
|
||||
google.protobuf.Timestamp exited_at = 3;
|
||||
}
|
||||
|
||||
message ExecProcessRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
bool terminal = 3;
|
||||
string stdin = 4;
|
||||
string stdout = 5;
|
||||
string stderr = 6;
|
||||
google.protobuf.Any spec = 7;
|
||||
}
|
||||
|
||||
message ExecProcessResponse {}
|
||||
|
||||
message ResizePtyRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 width = 3;
|
||||
uint32 height = 4;
|
||||
}
|
||||
|
||||
message StateRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message StateResponse {
|
||||
string id = 1;
|
||||
string bundle = 2;
|
||||
uint32 pid = 3;
|
||||
containerd.v1.types.Status status = 4;
|
||||
string stdin = 5;
|
||||
string stdout = 6;
|
||||
string stderr = 7;
|
||||
bool terminal = 8;
|
||||
uint32 exit_status = 9;
|
||||
google.protobuf.Timestamp exited_at = 10;
|
||||
string exec_id = 11;
|
||||
}
|
||||
|
||||
message KillRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
uint32 signal = 3;
|
||||
bool all = 4;
|
||||
}
|
||||
|
||||
message CloseIORequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
bool stdin = 3;
|
||||
}
|
||||
|
||||
message PidsRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message PidsResponse {
|
||||
repeated containerd.v1.types.ProcessInfo processes = 1;
|
||||
}
|
||||
|
||||
message CheckpointTaskRequest {
|
||||
string id = 1;
|
||||
string path = 2;
|
||||
google.protobuf.Any options = 3;
|
||||
}
|
||||
|
||||
message UpdateTaskRequest {
|
||||
string id = 1;
|
||||
google.protobuf.Any resources = 2;
|
||||
map<string, string> annotations = 3;
|
||||
}
|
||||
|
||||
message StartRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message StartResponse {
|
||||
uint32 pid = 1;
|
||||
}
|
||||
|
||||
message WaitRequest {
|
||||
string id = 1;
|
||||
string exec_id = 2;
|
||||
}
|
||||
|
||||
message WaitResponse {
|
||||
uint32 exit_status = 1;
|
||||
google.protobuf.Timestamp exited_at = 2;
|
||||
}
|
||||
|
||||
message StatsRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message StatsResponse {
|
||||
google.protobuf.Any stats = 1;
|
||||
}
|
||||
|
||||
message ConnectRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ConnectResponse {
|
||||
uint32 shim_pid = 1;
|
||||
uint32 task_pid = 2;
|
||||
string version = 3;
|
||||
}
|
||||
|
||||
message ShutdownRequest {
|
||||
string id = 1;
|
||||
bool now = 2;
|
||||
}
|
||||
|
||||
message PauseRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ResumeRequest {
|
||||
string id = 1;
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.containers.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/containers/v1;containers";
|
||||
|
||||
// Containers provides metadata storage for containers used in the execution
|
||||
// service.
|
||||
//
|
||||
// The objects here provide an state-independent view of containers for use in
|
||||
// management and resource pinning. From that perspective, containers do not
|
||||
// have a "state" but rather this is the set of resources that will be
|
||||
// considered in use by the container.
|
||||
//
|
||||
// From the perspective of the execution service, these objects represent the
|
||||
// base parameters for creating a container process.
|
||||
//
|
||||
// In general, when looking to add fields for this type, first ask yourself
|
||||
// whether or not the function of the field has to do with runtime execution or
|
||||
// is invariant of the runtime state of the container. If it has to do with
|
||||
// runtime, or changes as the "container" is started and stops, it probably
|
||||
// doesn't belong on this object.
|
||||
service Containers {
|
||||
rpc Get(GetContainerRequest) returns (GetContainerResponse);
|
||||
rpc List(ListContainersRequest) returns (ListContainersResponse);
|
||||
rpc ListStream(ListContainersRequest) returns (stream ListContainerMessage);
|
||||
rpc Create(CreateContainerRequest) returns (CreateContainerResponse);
|
||||
rpc Update(UpdateContainerRequest) returns (UpdateContainerResponse);
|
||||
rpc Delete(DeleteContainerRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Container {
|
||||
// ID is the user-specified identifier.
|
||||
//
|
||||
// This field may not be updated.
|
||||
string id = 1;
|
||||
|
||||
// Labels provides an area to include arbitrary data on containers.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
//
|
||||
// Note that to add a new value to this field, read the existing set and
|
||||
// include the entire result in the update call.
|
||||
map<string, string> labels = 2;
|
||||
|
||||
// Image contains the reference of the image used to build the
|
||||
// specification and snapshots for running this container.
|
||||
//
|
||||
// If this field is updated, the spec and rootfs needed to updated, as well.
|
||||
string image = 3;
|
||||
|
||||
message Runtime {
|
||||
// Name is the name of the runtime.
|
||||
string name = 1;
|
||||
// Options specify additional runtime initialization options.
|
||||
google.protobuf.Any options = 2;
|
||||
}
|
||||
// Runtime specifies which runtime to use for executing this container.
|
||||
Runtime runtime = 4;
|
||||
|
||||
// Spec to be used when creating the container. This is runtime specific.
|
||||
google.protobuf.Any spec = 5;
|
||||
|
||||
// Snapshotter specifies the snapshotter name used for rootfs
|
||||
string snapshotter = 6;
|
||||
|
||||
// SnapshotKey specifies the snapshot key to use for the container's root
|
||||
// filesystem. When starting a task from this container, a caller should
|
||||
// look up the mounts from the snapshot service and include those on the
|
||||
// task create request.
|
||||
//
|
||||
// Snapshots referenced in this field will not be garbage collected.
|
||||
//
|
||||
// This field is set to empty when the rootfs is not a snapshot.
|
||||
//
|
||||
// This field may be updated.
|
||||
string snapshot_key = 7;
|
||||
|
||||
// CreatedAt is the time the container was first created.
|
||||
google.protobuf.Timestamp created_at = 8;
|
||||
|
||||
// UpdatedAt is the last time the container was mutated.
|
||||
google.protobuf.Timestamp updated_at = 9;
|
||||
|
||||
// Extensions allow clients to provide zero or more blobs that are directly
|
||||
// associated with the container. One may provide protobuf, json, or other
|
||||
// encoding formats. The primary use of this is to further decorate the
|
||||
// container object with fields that may be specific to a client integration.
|
||||
//
|
||||
// The key portion of this map should identify a "name" for the extension
|
||||
// that should be unique against other extensions. When updating extension
|
||||
// data, one should only update the specified extension using field paths
|
||||
// to select a specific map key.
|
||||
map<string, google.protobuf.Any> extensions = 10;
|
||||
|
||||
// Sandbox ID this container belongs to.
|
||||
string sandbox = 11;
|
||||
}
|
||||
|
||||
message GetContainerRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message GetContainerResponse {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
message ListContainersRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListContainersResponse {
|
||||
repeated Container containers = 1;
|
||||
}
|
||||
|
||||
message CreateContainerRequest {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
message CreateContainerResponse {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
// UpdateContainerRequest updates the metadata on one or more container.
|
||||
//
|
||||
// The operation should follow semantics described in
|
||||
// https://developers.google.com/protocol-buffers/docs/reference/csharp/class/google/protobuf/well-known-types/field-mask,
|
||||
// unless otherwise qualified.
|
||||
message UpdateContainerRequest {
|
||||
// Container provides the target values, as declared by the mask, for the update.
|
||||
//
|
||||
// The ID field must be set.
|
||||
Container container = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
}
|
||||
|
||||
message UpdateContainerResponse {
|
||||
Container container = 1;
|
||||
}
|
||||
|
||||
message DeleteContainerRequest {
|
||||
string id = 1;
|
||||
}
|
||||
|
||||
message ListContainerMessage {
|
||||
Container container = 1;
|
||||
}
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.content.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/content/v1;content";
|
||||
|
||||
// Content provides access to a content addressable storage system.
|
||||
service Content {
|
||||
// Info returns information about a committed object.
|
||||
//
|
||||
// This call can be used for getting the size of content and checking for
|
||||
// existence.
|
||||
rpc Info(InfoRequest) returns (InfoResponse);
|
||||
|
||||
// Update updates content metadata.
|
||||
//
|
||||
// This call can be used to manage the mutable content labels. The
|
||||
// immutable metadata such as digest, size, and committed at cannot
|
||||
// be updated.
|
||||
rpc Update(UpdateRequest) returns (UpdateResponse);
|
||||
|
||||
// List streams the entire set of content as Info objects and closes the
|
||||
// stream.
|
||||
//
|
||||
// Typically, this will yield a large response, chunked into messages.
|
||||
// Clients should make provisions to ensure they can handle the entire data
|
||||
// set.
|
||||
rpc List(ListContentRequest) returns (stream ListContentResponse);
|
||||
|
||||
// Delete will delete the referenced object.
|
||||
rpc Delete(DeleteContentRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Read allows one to read an object based on the offset into the content.
|
||||
//
|
||||
// The requested data may be returned in one or more messages.
|
||||
rpc Read(ReadContentRequest) returns (stream ReadContentResponse);
|
||||
|
||||
// Status returns the status for a single reference.
|
||||
rpc Status(StatusRequest) returns (StatusResponse);
|
||||
|
||||
// ListStatuses returns the status of ongoing object ingestions, started via
|
||||
// Write.
|
||||
//
|
||||
// Only those matching the regular expression will be provided in the
|
||||
// response. If the provided regular expression is empty, all ingestions
|
||||
// will be provided.
|
||||
rpc ListStatuses(ListStatusesRequest) returns (ListStatusesResponse);
|
||||
|
||||
// Write begins or resumes writes to a resource identified by a unique ref.
|
||||
// Only one active stream may exist at a time for each ref.
|
||||
//
|
||||
// Once a write stream has started, it may only write to a single ref, thus
|
||||
// once a stream is started, the ref may be omitted on subsequent writes.
|
||||
//
|
||||
// For any write transaction represented by a ref, only a single write may
|
||||
// be made to a given offset. If overlapping writes occur, it is an error.
|
||||
// Writes should be sequential and implementations may throw an error if
|
||||
// this is required.
|
||||
//
|
||||
// If expected_digest is set and already part of the content store, the
|
||||
// write will fail.
|
||||
//
|
||||
// When completed, the commit flag should be set to true. If expected size
|
||||
// or digest is set, the content will be validated against those values.
|
||||
rpc Write(stream WriteContentRequest) returns (stream WriteContentResponse);
|
||||
|
||||
// Abort cancels the ongoing write named in the request. Any resources
|
||||
// associated with the write will be collected.
|
||||
rpc Abort(AbortRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Info {
|
||||
// Digest is the hash identity of the blob.
|
||||
string digest = 1;
|
||||
|
||||
// Size is the total number of bytes in the blob.
|
||||
int64 size = 2;
|
||||
|
||||
// CreatedAt provides the time at which the blob was committed.
|
||||
google.protobuf.Timestamp created_at = 3;
|
||||
|
||||
// UpdatedAt provides the time the info was last updated.
|
||||
google.protobuf.Timestamp updated_at = 4;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 5;
|
||||
}
|
||||
|
||||
message InfoRequest {
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
message InfoResponse {
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message UpdateRequest {
|
||||
Info info = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
//
|
||||
// In info, Digest, Size, and CreatedAt are immutable,
|
||||
// other field may be updated using this mask.
|
||||
// If no mask is provided, all mutable field are updated.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
}
|
||||
|
||||
message UpdateResponse {
|
||||
Info info = 1;
|
||||
}
|
||||
|
||||
message ListContentRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, containers that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListContentResponse {
|
||||
repeated Info info = 1;
|
||||
}
|
||||
|
||||
message DeleteContentRequest {
|
||||
// Digest specifies which content to delete.
|
||||
string digest = 1;
|
||||
}
|
||||
|
||||
// ReadContentRequest defines the fields that make up a request to read a portion of
|
||||
// data from a stored object.
|
||||
message ReadContentRequest {
|
||||
// Digest is the hash identity to read.
|
||||
string digest = 1;
|
||||
|
||||
// Offset specifies the number of bytes from the start at which to begin
|
||||
// the read. If zero or less, the read will be from the start. This uses
|
||||
// standard zero-indexed semantics.
|
||||
int64 offset = 2;
|
||||
|
||||
// size is the total size of the read. If zero, the entire blob will be
|
||||
// returned by the service.
|
||||
int64 size = 3;
|
||||
}
|
||||
|
||||
// ReadContentResponse carries byte data for a read request.
|
||||
message ReadContentResponse {
|
||||
int64 offset = 1; // offset of the returned data
|
||||
bytes data = 2; // actual data
|
||||
}
|
||||
|
||||
message Status {
|
||||
google.protobuf.Timestamp started_at = 1;
|
||||
google.protobuf.Timestamp updated_at = 2;
|
||||
string ref = 3;
|
||||
int64 offset = 4;
|
||||
int64 total = 5;
|
||||
string expected = 6;
|
||||
}
|
||||
|
||||
message StatusRequest {
|
||||
string ref = 1;
|
||||
}
|
||||
|
||||
message StatusResponse {
|
||||
Status status = 1;
|
||||
}
|
||||
|
||||
message ListStatusesRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListStatusesResponse {
|
||||
repeated Status statuses = 1;
|
||||
}
|
||||
|
||||
// WriteAction defines the behavior of a WriteRequest.
|
||||
enum WriteAction {
|
||||
// WriteActionStat instructs the writer to return the current status while
|
||||
// holding the lock on the write.
|
||||
STAT = 0;
|
||||
|
||||
// WriteActionWrite sets the action for the write request to write data.
|
||||
//
|
||||
// Any data included will be written at the provided offset. The
|
||||
// transaction will be left open for further writes.
|
||||
//
|
||||
// This is the default.
|
||||
WRITE = 1;
|
||||
|
||||
// WriteActionCommit will write any outstanding data in the message and
|
||||
// commit the write, storing it under the digest.
|
||||
//
|
||||
// This can be used in a single message to send the data, verify it and
|
||||
// commit it.
|
||||
//
|
||||
// This action will always terminate the write.
|
||||
COMMIT = 2;
|
||||
}
|
||||
|
||||
// WriteContentRequest writes data to the request ref at offset.
|
||||
message WriteContentRequest {
|
||||
// Action sets the behavior of the write.
|
||||
//
|
||||
// When this is a write and the ref is not yet allocated, the ref will be
|
||||
// allocated and the data will be written at offset.
|
||||
//
|
||||
// If the action is write and the ref is allocated, it will accept data to
|
||||
// an offset that has not yet been written.
|
||||
//
|
||||
// If the action is write and there is no data, the current write status
|
||||
// will be returned. This works differently from status because the stream
|
||||
// holds a lock.
|
||||
WriteAction action = 1;
|
||||
|
||||
// Ref identifies the pre-commit object to write to.
|
||||
string ref = 2;
|
||||
|
||||
// Total can be set to have the service validate the total size of the
|
||||
// committed content.
|
||||
//
|
||||
// The latest value before or with the commit action message will be use to
|
||||
// validate the content. If the offset overflows total, the service may
|
||||
// report an error. It is only required on one message for the write.
|
||||
//
|
||||
// If the value is zero or less, no validation of the final content will be
|
||||
// performed.
|
||||
int64 total = 3;
|
||||
|
||||
// Expected can be set to have the service validate the final content against
|
||||
// the provided digest.
|
||||
//
|
||||
// If the digest is already present in the object store, an AlreadyExists
|
||||
// error will be returned.
|
||||
//
|
||||
// Only the latest version will be used to check the content against the
|
||||
// digest. It is only required to include it on a single message, before or
|
||||
// with the commit action message.
|
||||
string expected = 4;
|
||||
|
||||
// Offset specifies the number of bytes from the start at which to begin
|
||||
// the write. For most implementations, this means from the start of the
|
||||
// file. This uses standard, zero-indexed semantics.
|
||||
//
|
||||
// If the action is write, the remote may remove all previously written
|
||||
// data after the offset. Implementations may support arbitrary offsets but
|
||||
// MUST support reseting this value to zero with a write. If an
|
||||
// implementation does not support a write at a particular offset, an
|
||||
// OutOfRange error must be returned.
|
||||
int64 offset = 5;
|
||||
|
||||
// Data is the actual bytes to be written.
|
||||
//
|
||||
// If this is empty and the message is not a commit, a response will be
|
||||
// returned with the current write state.
|
||||
bytes data = 6;
|
||||
|
||||
// Labels are arbitrary data on snapshots.
|
||||
//
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 7;
|
||||
}
|
||||
|
||||
// WriteContentResponse is returned on the culmination of a write call.
|
||||
message WriteContentResponse {
|
||||
// Action contains the action for the final message of the stream. A writer
|
||||
// should confirm that they match the intended result.
|
||||
WriteAction action = 1;
|
||||
|
||||
// StartedAt provides the time at which the write began.
|
||||
//
|
||||
// This must be set for stat and commit write actions. All other write
|
||||
// actions may omit this.
|
||||
google.protobuf.Timestamp started_at = 2;
|
||||
|
||||
// UpdatedAt provides the last time of a successful write.
|
||||
//
|
||||
// This must be set for stat and commit write actions. All other write
|
||||
// actions may omit this.
|
||||
google.protobuf.Timestamp updated_at = 3;
|
||||
|
||||
// Offset is the current committed size for the write.
|
||||
int64 offset = 4;
|
||||
|
||||
// Total provides the current, expected total size of the write.
|
||||
//
|
||||
// We include this to provide consistency with the Status structure on the
|
||||
// client writer.
|
||||
//
|
||||
// This is only valid on the Stat and Commit response.
|
||||
int64 total = 5;
|
||||
|
||||
// Digest, if present, includes the digest up to the currently committed
|
||||
// bytes. If action is commit, this field will be set. It is implementation
|
||||
// defined if this is set for other actions.
|
||||
string digest = 6;
|
||||
}
|
||||
|
||||
message AbortRequest {
|
||||
string ref = 1;
|
||||
}
|
||||
90
wfe-containerd-protos/proto/api/services/diff/v1/diff.proto
Normal file
90
wfe-containerd-protos/proto/api/services/diff/v1/diff.proto
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.diff.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "types/descriptor.proto";
|
||||
import "types/mount.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/diff/v1;diff";
|
||||
|
||||
// Diff service creates and applies diffs
|
||||
service Diff {
|
||||
// Apply applies the content associated with the provided digests onto
|
||||
// the provided mounts. Archive content will be extracted and
|
||||
// decompressed if necessary.
|
||||
rpc Apply(ApplyRequest) returns (ApplyResponse);
|
||||
|
||||
// Diff creates a diff between the given mounts and uploads the result
|
||||
// to the content store.
|
||||
rpc Diff(DiffRequest) returns (DiffResponse);
|
||||
}
|
||||
|
||||
message ApplyRequest {
|
||||
// Diff is the descriptor of the diff to be extracted
|
||||
containerd.types.Descriptor diff = 1;
|
||||
|
||||
repeated containerd.types.Mount mounts = 2;
|
||||
|
||||
map<string, google.protobuf.Any> payloads = 3;
|
||||
// SyncFs is to synchronize the underlying filesystem containing files.
|
||||
bool sync_fs = 4;
|
||||
}
|
||||
|
||||
message ApplyResponse {
|
||||
// Applied is the descriptor for the object which was applied.
|
||||
// If the input was a compressed blob then the result will be
|
||||
// the descriptor for the uncompressed blob.
|
||||
containerd.types.Descriptor applied = 1;
|
||||
}
|
||||
|
||||
message DiffRequest {
|
||||
// Left are the mounts which represent the older copy
|
||||
// in which is the base of the computed changes.
|
||||
repeated containerd.types.Mount left = 1;
|
||||
|
||||
// Right are the mounts which represents the newer copy
|
||||
// in which changes from the left were made into.
|
||||
repeated containerd.types.Mount right = 2;
|
||||
|
||||
// MediaType is the media type descriptor for the created diff
|
||||
// object
|
||||
string media_type = 3;
|
||||
|
||||
// Ref identifies the pre-commit content store object. This
|
||||
// reference can be used to get the status from the content store.
|
||||
string ref = 4;
|
||||
|
||||
// Labels are the labels to apply to the generated content
|
||||
// on content store commit.
|
||||
map<string, string> labels = 5;
|
||||
|
||||
// SourceDateEpoch specifies the timestamp used to provide control for reproducibility.
|
||||
// See also https://reproducible-builds.org/docs/source-date-epoch/ .
|
||||
//
|
||||
// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01),
|
||||
// not to the source date epoch.
|
||||
google.protobuf.Timestamp source_date_epoch = 6;
|
||||
}
|
||||
|
||||
message DiffResponse {
|
||||
// Diff is the descriptor of the diff which can be applied
|
||||
containerd.types.Descriptor diff = 3;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.events.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "types/event.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/events/v1;events";
|
||||
|
||||
service Events {
|
||||
// Publish an event to a topic.
|
||||
//
|
||||
// The event will be packed into a timestamp envelope with the namespace
|
||||
// introspected from the context. The envelope will then be dispatched.
|
||||
rpc Publish(PublishRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Forward sends an event that has already been packaged into an envelope
|
||||
// with a timestamp and namespace.
|
||||
//
|
||||
// This is useful if earlier timestamping is required or when forwarding on
|
||||
// behalf of another component, namespace or publisher.
|
||||
rpc Forward(ForwardRequest) returns (google.protobuf.Empty);
|
||||
|
||||
// Subscribe to a stream of events, possibly returning only that match any
|
||||
// of the provided filters.
|
||||
//
|
||||
// Unlike many other methods in containerd, subscribers will get messages
|
||||
// from all namespaces unless otherwise specified. If this is not desired,
|
||||
// a filter can be provided in the format 'namespace==<namespace>' to
|
||||
// restrict the received events.
|
||||
rpc Subscribe(SubscribeRequest) returns (stream containerd.types.Envelope);
|
||||
}
|
||||
|
||||
message PublishRequest {
|
||||
string topic = 1;
|
||||
google.protobuf.Any event = 2;
|
||||
}
|
||||
|
||||
message ForwardRequest {
|
||||
containerd.types.Envelope envelope = 1;
|
||||
}
|
||||
|
||||
message SubscribeRequest {
|
||||
repeated string filters = 1;
|
||||
}
|
||||
149
wfe-containerd-protos/proto/api/services/images/v1/images.proto
Normal file
149
wfe-containerd-protos/proto/api/services/images/v1/images.proto
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package containerd.services.images.v1;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/field_mask.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "types/descriptor.proto";
|
||||
|
||||
option go_package = "github.com/containerd/containerd/api/services/images/v1;images";
|
||||
|
||||
// Images is a service that allows one to register images with containerd.
|
||||
//
|
||||
// In containerd, an image is merely the mapping of a name to a content root,
|
||||
// described by a descriptor. The behavior and state of image is purely
|
||||
// dictated by the type of the descriptor.
|
||||
//
|
||||
// From the perspective of this service, these references are mostly shallow,
|
||||
// in that the existence of the required content won't be validated until
|
||||
// required by consuming services.
|
||||
//
|
||||
// As such, this can really be considered a "metadata service".
|
||||
service Images {
|
||||
// Get returns an image by name.
|
||||
rpc Get(GetImageRequest) returns (GetImageResponse);
|
||||
|
||||
// List returns a list of all images known to containerd.
|
||||
rpc List(ListImagesRequest) returns (ListImagesResponse);
|
||||
|
||||
// Create an image record in the metadata store.
|
||||
//
|
||||
// The name of the image must be unique.
|
||||
rpc Create(CreateImageRequest) returns (CreateImageResponse);
|
||||
|
||||
// Update assigns the name to a given target image based on the provided
|
||||
// image.
|
||||
rpc Update(UpdateImageRequest) returns (UpdateImageResponse);
|
||||
|
||||
// Delete deletes the image by name.
|
||||
rpc Delete(DeleteImageRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
message Image {
|
||||
// Name provides a unique name for the image.
|
||||
//
|
||||
// Containerd treats this as the primary identifier.
|
||||
string name = 1;
|
||||
|
||||
// Labels provides free form labels for the image. These are runtime only
|
||||
// and do not get inherited into the package image in any way.
|
||||
//
|
||||
// Labels may be updated using the field mask.
|
||||
// The combined size of a key/value pair cannot exceed 4096 bytes.
|
||||
map<string, string> labels = 2;
|
||||
|
||||
// Target describes the content entry point of the image.
|
||||
containerd.types.Descriptor target = 3;
|
||||
|
||||
// CreatedAt is the time the image was first created.
|
||||
google.protobuf.Timestamp created_at = 7;
|
||||
|
||||
// UpdatedAt is the last time the image was mutated.
|
||||
google.protobuf.Timestamp updated_at = 8;
|
||||
}
|
||||
|
||||
message GetImageRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message GetImageResponse {
|
||||
Image image = 1;
|
||||
}
|
||||
|
||||
message CreateImageRequest {
|
||||
Image image = 1;
|
||||
|
||||
google.protobuf.Timestamp source_date_epoch = 2;
|
||||
}
|
||||
|
||||
message CreateImageResponse {
|
||||
Image image = 1;
|
||||
}
|
||||
|
||||
message UpdateImageRequest {
|
||||
// Image provides a full or partial image for update.
|
||||
//
|
||||
// The name field must be set or an error will be returned.
|
||||
Image image = 1;
|
||||
|
||||
// UpdateMask specifies which fields to perform the update on. If empty,
|
||||
// the operation applies to all fields.
|
||||
google.protobuf.FieldMask update_mask = 2;
|
||||
|
||||
google.protobuf.Timestamp source_date_epoch = 3;
|
||||
}
|
||||
|
||||
message UpdateImageResponse {
|
||||
Image image = 1;
|
||||
}
|
||||
|
||||
message ListImagesRequest {
|
||||
// Filters contains one or more filters using the syntax defined in the
|
||||
// containerd filter package.
|
||||
//
|
||||
// The returned result will be those that match any of the provided
|
||||
// filters. Expanded, images that match the following will be
|
||||
// returned:
|
||||
//
|
||||
// filters[0] or filters[1] or ... or filters[n-1] or filters[n]
|
||||
//
|
||||
// If filters is zero-length or nil, all items will be returned.
|
||||
repeated string filters = 1;
|
||||
}
|
||||
|
||||
message ListImagesResponse {
|
||||
repeated Image images = 1;
|
||||
}
|
||||
|
||||
message DeleteImageRequest {
|
||||
string name = 1;
|
||||
|
||||
// Sync indicates that the delete and cleanup should be done
|
||||
// synchronously before returning to the caller
|
||||
//
|
||||
// Default is false
|
||||
bool sync = 2;
|
||||
|
||||
// Target value for image to be deleted
|
||||
//
|
||||
// If image descriptor does not match the same digest,
|
||||
// the delete operation will return "not found" error.
|
||||
optional containerd.types.Descriptor target = 3;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user