empeira 0.1.0.pre.alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +661 -0
- data/README.md +150 -0
- data/bin/empeira +18 -0
- data/config/defaults.yaml +229 -0
- data/docs/addons.md +331 -0
- data/docs/architecture.md +277 -0
- data/docs/configuration.md +1204 -0
- data/docs/development.md +472 -0
- data/docs/hiera-and-eyaml.md +361 -0
- data/docs/installation.md +280 -0
- data/docs/networking.md +362 -0
- data/docs/nodes.md +642 -0
- data/docs/proxy.md +136 -0
- data/docs/troubleshooting.md +361 -0
- data/lib/empeira/addons/environment.rb +82 -0
- data/lib/empeira/addons/error.rb +14 -0
- data/lib/empeira/addons/installation.rb +119 -0
- data/lib/empeira/addons/manifest.rb +112 -0
- data/lib/empeira/addons/service.rb +50 -0
- data/lib/empeira/addons/storage.rb +94 -0
- data/lib/empeira/agent/acquisition.rb +120 -0
- data/lib/empeira/agent/artifact.rb +41 -0
- data/lib/empeira/agent/authentication.rb +122 -0
- data/lib/empeira/agent/cache.rb +122 -0
- data/lib/empeira/agent/cache_storage.rb +82 -0
- data/lib/empeira/agent/download.rb +84 -0
- data/lib/empeira/agent/native_commands.rb +84 -0
- data/lib/empeira/agent/release_sources.rb +64 -0
- data/lib/empeira/agent/target.rb +66 -0
- data/lib/empeira/agent/versions.rb +29 -0
- data/lib/empeira/application.rb +86 -0
- data/lib/empeira/build.json +5 -0
- data/lib/empeira/build_info.rb +46 -0
- data/lib/empeira/cli/addons.rb +45 -0
- data/lib/empeira/cli/base.rb +73 -0
- data/lib/empeira/cli/completion.rb +42 -0
- data/lib/empeira/cli/config.rb +22 -0
- data/lib/empeira/cli/main.rb +114 -0
- data/lib/empeira/cli/node.rb +87 -0
- data/lib/empeira/cli/progress.rb +169 -0
- data/lib/empeira/cli/proxy.rb +36 -0
- data/lib/empeira/cli/update.rb +23 -0
- data/lib/empeira/completion/addons.rb +93 -0
- data/lib/empeira/completion/bash.rb +62 -0
- data/lib/empeira/completion/catalog.rb +170 -0
- data/lib/empeira/configuration/additional_services.rb +74 -0
- data/lib/empeira/configuration/addons.rb +85 -0
- data/lib/empeira/configuration/agent_schema.rb +163 -0
- data/lib/empeira/configuration/agent_values.rb +54 -0
- data/lib/empeira/configuration/bootstrap_guests.rb +42 -0
- data/lib/empeira/configuration/command_mocks.rb +65 -0
- data/lib/empeira/configuration/display.rb +20 -0
- data/lib/empeira/configuration/dns_rewrites.rb +58 -0
- data/lib/empeira/configuration/document.rb +67 -0
- data/lib/empeira/configuration/eyaml.rb +46 -0
- data/lib/empeira/configuration/hiera_modulepath.rb +40 -0
- data/lib/empeira/configuration/hiera_mount_schema.rb +62 -0
- data/lib/empeira/configuration/hiera_mounts.rb +83 -0
- data/lib/empeira/configuration/image_schema.rb +68 -0
- data/lib/empeira/configuration/loader.rb +70 -0
- data/lib/empeira/configuration/merge.rb +48 -0
- data/lib/empeira/configuration/network_redirects.rb +73 -0
- data/lib/empeira/configuration/node_images.rb +64 -0
- data/lib/empeira/configuration/schema.rb +215 -0
- data/lib/empeira/configuration/server_mounts.rb +106 -0
- data/lib/empeira/configuration/service_configuration.rb +40 -0
- data/lib/empeira/configuration/ssh_preferences.rb +83 -0
- data/lib/empeira/configuration/user.rb +46 -0
- data/lib/empeira/configuration/vm_interfaces.rb +147 -0
- data/lib/empeira/control_plane/additional_configurations.rb +106 -0
- data/lib/empeira/control_plane/browser.rb +73 -0
- data/lib/empeira/control_plane/controller.rb +763 -0
- data/lib/empeira/control_plane/discovery.rb +69 -0
- data/lib/empeira/control_plane/environment.rb +101 -0
- data/lib/empeira/control_plane/files.rb +263 -0
- data/lib/empeira/control_plane/health.rb +104 -0
- data/lib/empeira/control_plane/plan.rb +356 -0
- data/lib/empeira/control_plane/storage.rb +48 -0
- data/lib/empeira/errors.rb +9 -0
- data/lib/empeira/execution/console.rb +45 -0
- data/lib/empeira/execution/diagnostics.rb +210 -0
- data/lib/empeira/execution/launch_error.rb +14 -0
- data/lib/empeira/execution/result.rb +11 -0
- data/lib/empeira/execution/runner.rb +235 -0
- data/lib/empeira/execution/terminal.rb +35 -0
- data/lib/empeira/hostname_pattern.rb +14 -0
- data/lib/empeira/images/configuration.rb +44 -0
- data/lib/empeira/images/identity.rb +30 -0
- data/lib/empeira/images/recipe.rb +22 -0
- data/lib/empeira/images/reference.rb +43 -0
- data/lib/empeira/images/source.rb +19 -0
- data/lib/empeira/immutable.rb +19 -0
- data/lib/empeira/infrastructure/cleanup.rb +328 -0
- data/lib/empeira/infrastructure/definition.rb +59 -0
- data/lib/empeira/infrastructure/owned_files.rb +63 -0
- data/lib/empeira/infrastructure/recovery_inventory.rb +53 -0
- data/lib/empeira/infrastructure/service.rb +237 -0
- data/lib/empeira/infrastructure/status.rb +73 -0
- data/lib/empeira/infrastructure/store.rb +274 -0
- data/lib/empeira/modules/events.rb +67 -0
- data/lib/empeira/modules/git_safety.rb +60 -0
- data/lib/empeira/modules/host_git.rb +91 -0
- data/lib/empeira/modules/image.rb +27 -0
- data/lib/empeira/modules/installer.rb +67 -0
- data/lib/empeira/modules/request.rb +68 -0
- data/lib/empeira/modules/state.rb +87 -0
- data/lib/empeira/modules/storage.rb +35 -0
- data/lib/empeira/network/bootstrap_proxy.rb +157 -0
- data/lib/empeira/network/definition.rb +61 -0
- data/lib/empeira/network/direct_egress.rb +133 -0
- data/lib/empeira/network/egress.rb +27 -0
- data/lib/empeira/network/gateway.rb +79 -0
- data/lib/empeira/network/host_policy.rb +53 -0
- data/lib/empeira/network/naming.rb +28 -0
- data/lib/empeira/network/peer/adapter_image.rb +32 -0
- data/lib/empeira/network/peer/allocation.rb +45 -0
- data/lib/empeira/network/peer/attachment.rb +27 -0
- data/lib/empeira/network/peer/backend.rb +108 -0
- data/lib/empeira/network/peer/channel.rb +133 -0
- data/lib/empeira/network/peer/channel_server.rb +71 -0
- data/lib/empeira/network/peer/docker_adapter.rb +165 -0
- data/lib/empeira/network/peer/helper_security.rb +40 -0
- data/lib/empeira/network/peer/layout.rb +55 -0
- data/lib/empeira/network/peer/linux_podman.rb +114 -0
- data/lib/empeira/network/peer/podman_machine.rb +112 -0
- data/lib/empeira/network/policy.rb +39 -0
- data/lib/empeira/network/proxy_bindings.rb +52 -0
- data/lib/empeira/network/proxy_policy.rb +64 -0
- data/lib/empeira/network/redirects.rb +89 -0
- data/lib/empeira/network/resource.rb +50 -0
- data/lib/empeira/node/agent_installer.rb +31 -0
- data/lib/empeira/node/agent_package.rb +125 -0
- data/lib/empeira/node/agent_repository.rb +160 -0
- data/lib/empeira/node/apt_configuration.rb +85 -0
- data/lib/empeira/node/bootstrap.rb +17 -0
- data/lib/empeira/node/certificates.rb +98 -0
- data/lib/empeira/node/command_mock.rb +38 -0
- data/lib/empeira/node/command_mocks.rb +114 -0
- data/lib/empeira/node/container.rb +134 -0
- data/lib/empeira/node/container_agent_bootstrap.rb +43 -0
- data/lib/empeira/node/container_bootstrap.rb +52 -0
- data/lib/empeira/node/container_guest.rb +42 -0
- data/lib/empeira/node/container_lifecycle.rb +145 -0
- data/lib/empeira/node/container_preparation.rb +144 -0
- data/lib/empeira/node/container_state.rb +129 -0
- data/lib/empeira/node/definition.rb +20 -0
- data/lib/empeira/node/diagnostic_command.rb +19 -0
- data/lib/empeira/node/dnf_agent_repository.rb +202 -0
- data/lib/empeira/node/external_fact.rb +21 -0
- data/lib/empeira/node/image.rb +38 -0
- data/lib/empeira/node/interactive_tools.rb +33 -0
- data/lib/empeira/node/interface.rb +18 -0
- data/lib/empeira/node/inventory.rb +143 -0
- data/lib/empeira/node/package_bootstrap.rb +129 -0
- data/lib/empeira/node/package_proxy.rb +102 -0
- data/lib/empeira/node/package_sources.rb +19 -0
- data/lib/empeira/node/puppet_command.rb +12 -0
- data/lib/empeira/node/rpm_configuration.rb +62 -0
- data/lib/empeira/node/run_request.rb +52 -0
- data/lib/empeira/node/runtime_proxy.rb +86 -0
- data/lib/empeira/node/service.rb +72 -0
- data/lib/empeira/node/ssh_client.rb +25 -0
- data/lib/empeira/node/ssh_credentials.rb +78 -0
- data/lib/empeira/node/ssh_endpoint.rb +58 -0
- data/lib/empeira/node/ssh_identity.rb +37 -0
- data/lib/empeira/node/user_ssh.rb +60 -0
- data/lib/empeira/node/vm.rb +89 -0
- data/lib/empeira/node/vm_bootstrap.rb +53 -0
- data/lib/empeira/node/vm_lifecycle.rb +212 -0
- data/lib/empeira/node/vm_preflight.rb +37 -0
- data/lib/empeira/node/vm_preparation.rb +161 -0
- data/lib/empeira/node/vm_state.rb +161 -0
- data/lib/empeira/platform/facts.rb +66 -0
- data/lib/empeira/platform/kvm.rb +91 -0
- data/lib/empeira/platform/locations.rb +51 -0
- data/lib/empeira/platform/resolvers.rb +85 -0
- data/lib/empeira/platform/routes.rb +50 -0
- data/lib/empeira/progress.rb +70 -0
- data/lib/empeira/project_root.rb +47 -0
- data/lib/empeira/providers/lifecycle.rb +96 -0
- data/lib/empeira/providers/registry.rb +21 -0
- data/lib/empeira/providers/resource.rb +32 -0
- data/lib/empeira/providers.rb +55 -0
- data/lib/empeira/runtime/agent_helper.rb +34 -0
- data/lib/empeira/runtime/container.rb +184 -0
- data/lib/empeira/runtime/diagnostic_execution.rb +52 -0
- data/lib/empeira/runtime/docker.rb +87 -0
- data/lib/empeira/runtime/image_metadata.rb +83 -0
- data/lib/empeira/runtime/interface.rb +8 -0
- data/lib/empeira/runtime/mount_probe.rb +57 -0
- data/lib/empeira/runtime/podman.rb +122 -0
- data/lib/empeira/runtime/recipe_build.rb +103 -0
- data/lib/empeira/runtime/registry_diagnostics.rb +23 -0
- data/lib/empeira/runtime/service_arguments.rb +55 -0
- data/lib/empeira/runtime/service_images.rb +118 -0
- data/lib/empeira/runtime/service_inspection.rb +159 -0
- data/lib/empeira/runtime/services.rb +120 -0
- data/lib/empeira/runtime/update_helper.rb +97 -0
- data/lib/empeira/runtime/workspace_network.rb +69 -0
- data/lib/empeira/server/environment_configuration.rb +53 -0
- data/lib/empeira/server/http.rb +38 -0
- data/lib/empeira/server/puppetdb_runtime.rb +74 -0
- data/lib/empeira/server/relay_certificate.rb +76 -0
- data/lib/empeira/server/runtime.rb +90 -0
- data/lib/empeira/services/definition.rb +42 -0
- data/lib/empeira/updates/images.rb +104 -0
- data/lib/empeira/updates/modules.rb +45 -0
- data/lib/empeira/updates/service.rb +45 -0
- data/lib/empeira/version_requirement.rb +23 -0
- data/lib/empeira/vm/agent.rb +66 -0
- data/lib/empeira/vm/bootstrap_requirements.rb +69 -0
- data/lib/empeira/vm/certificate_runtime.rb +30 -0
- data/lib/empeira/vm/cloud_init.rb +171 -0
- data/lib/empeira/vm/disk.rb +136 -0
- data/lib/empeira/vm/guest.rb +123 -0
- data/lib/empeira/vm/guest_channel.rb +110 -0
- data/lib/empeira/vm/guest_network.rb +94 -0
- data/lib/empeira/vm/guest_output.rb +52 -0
- data/lib/empeira/vm/guest_shell.rb +79 -0
- data/lib/empeira/vm/guest_upload.rb +43 -0
- data/lib/empeira/vm/image_cache.rb +77 -0
- data/lib/empeira/vm/image_source.rb +91 -0
- data/lib/empeira/vm/interface.rb +8 -0
- data/lib/empeira/vm/interface_ownership.rb +124 -0
- data/lib/empeira/vm/interface_routes.rb +101 -0
- data/lib/empeira/vm/interfaces.rb +240 -0
- data/lib/empeira/vm/management.rb +73 -0
- data/lib/empeira/vm/prerequisites.rb +42 -0
- data/lib/empeira/vm/qemu.rb +83 -0
- data/lib/empeira/vm/qemu_runtime.rb +404 -0
- data/lib/empeira/vm/removal.rb +30 -0
- data/lib/empeira/vm/root_disk.rb +92 -0
- data/lib/empeira/vm/session_lock.rb +56 -0
- data/lib/empeira/vm/system_ssh.rb +29 -0
- data/lib/empeira/workspace.rb +42 -0
- data/lib/empeira.rb +209 -0
- data/resources/browser/relay.rb +22 -0
- data/resources/gateway/Containerfile +8 -0
- data/resources/gateway/bridge.rb +66 -0
- data/resources/gateway/configure.rb +323 -0
- data/resources/modules/Containerfile +15 -0
- data/resources/modules/Gemfile +5 -0
- data/resources/modules/Gemfile.lock +105 -0
- data/resources/modules/worker.rb +161 -0
- data/resources/network/adapter/Containerfile +13 -0
- data/resources/network/adapter/bridge_linux.go +51 -0
- data/resources/network/adapter/framing.go +45 -0
- data/resources/network/adapter/framing_test.go +53 -0
- data/resources/network/adapter/go.mod +3 -0
- data/resources/network/adapter/main_linux.go +273 -0
- data/resources/network/channel.rb +18 -0
- data/resources/network/ssh_connect.rb +32 -0
- data/resources/nodes/apt_sources.rb +66 -0
- data/resources/nodes/debian/Containerfile +10 -0
- data/resources/nodes/diagnostic_exec.rb +109 -0
- data/resources/nodes/interactive_tools.rb +139 -0
- data/resources/nodes/managed_file.rb +91 -0
- data/resources/nodes/management/guest_agent.py +415 -0
- data/resources/nodes/management/setup.sh +20 -0
- data/resources/nodes/management/shell_rc.sh +12 -0
- data/resources/nodes/management/system_account.sh +24 -0
- data/resources/nodes/management/system_home.sh +15 -0
- data/resources/nodes/rpm/Containerfile +10 -0
- data/resources/nodes/runtime_proxy.rb +244 -0
- data/resources/nodes/ssh/proxy.rb +16 -0
- data/resources/nodes/ssh/sshd_config +15 -0
- data/resources/nodes/ssh/start +6 -0
- data/resources/proxy/Containerfile +10 -0
- data/resources/relay/Containerfile +5 -0
- data/resources/relay/puppetdb.rb +81 -0
- data/resources/relay/server_environment.rb +10 -0
- data/resources/relay/server_start.sh +41 -0
- metadata +326 -0
data/docs/development.md
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
## Environment and quality checks
|
|
4
|
+
|
|
5
|
+
Install Git, Ruby 3.4, Bundler and the platform prerequisites in
|
|
6
|
+
[installation](installation.md). The gem requires Ruby 3.4+; Ruby 3.2 and 3.3 are
|
|
7
|
+
unsupported. Normal Ubuntu CI runs deterministic RSpec on Ruby 3.4 and 4.0, with
|
|
8
|
+
RuboCop and both dependency audits only on Ruby 3.4. Release builds use Ruby 3.4.
|
|
9
|
+
Use synthetic control repositories and disposable credentials.
|
|
10
|
+
|
|
11
|
+
```console
|
|
12
|
+
bundle install
|
|
13
|
+
bundle exec rspec
|
|
14
|
+
bundle exec rubocop
|
|
15
|
+
bundle exec bundler-audit check --update
|
|
16
|
+
bundle exec bundler-audit check --gemfile-lock resources/modules/Gemfile.lock
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
`bundle exec rake` also runs RSpec. Normal tests use isolated temporary projects,
|
|
20
|
+
local child processes and loopback fixtures. Explicit integration gates are pending
|
|
21
|
+
unless enabled; a pending test is not a successful runtime check. Security auditing
|
|
22
|
+
covers known Ruby advisories in both resolutions, not all container OS packages.
|
|
23
|
+
To reproduce either CI test job, activate the corresponding Ruby, install the locked
|
|
24
|
+
bundle and run `bundle exec rspec --exclude-pattern 'spec/integration/**/*_spec.rb'`.
|
|
25
|
+
Runtime and VM compatibility remain separate manual gates.
|
|
26
|
+
|
|
27
|
+
Addon tests (`spec/addon_*_spec.rb`) use the existing loopback Git fixture,
|
|
28
|
+
concurrent CLI subprocesses, a real PTY and the generated Bash completion. They
|
|
29
|
+
exercise branches, tags and commit refs without external Git services or container
|
|
30
|
+
startup. The complete `spec/fixtures/addon` is also the documented minimal addon.
|
|
31
|
+
When extending configuration, review `Schema::ADDON_PRIVATE_PATHS`: secret fields
|
|
32
|
+
and opaque content require explicit exclusion from the addon environment API.
|
|
33
|
+
|
|
34
|
+
Runtime proxy regression coverage runs real guest helpers against isolated fake
|
|
35
|
+
guest roots, checks foreign APT/DNF ownership, and exercises privileged VM command
|
|
36
|
+
environment separately from bootstrap. Never execute these helpers against the
|
|
37
|
+
developer's `/etc` in unit tests.
|
|
38
|
+
|
|
39
|
+
`spec/interactive_tools_spec.rb` executes native Bash against synthetic startup
|
|
40
|
+
files, covering login/non-login behavior, PATH preservation, duplicate prevention
|
|
41
|
+
and ownership failures. The manual runtime management gate also checks installed
|
|
42
|
+
agent commands on retained guests after restart.
|
|
43
|
+
|
|
44
|
+
The manual runtime management gate checks real VirtIO execution while Puppet sets
|
|
45
|
+
root shadow to `!`, replaces sudoers, removes the regular `empeira` account and
|
|
46
|
+
changes, restarts and disables system SSH. It verifies subsequent `node puppet`,
|
|
47
|
+
retry after exits 4/6, user SSH without the management endpoint, verified upload
|
|
48
|
+
cleanup, stop/start, interface facts and normal proxy reconciliation. The gate
|
|
49
|
+
combines a thin disk, first-catalog dummy/VLAN facts and normal proxy package
|
|
50
|
+
installation. `spec/vm_guest_spec.rb` covers streaming, full output, native status,
|
|
51
|
+
interruption, binary upload and operation identity against isolated Unix peers.
|
|
52
|
+
`spec/vm_guest_agent_spec.rb` runs the guest adapter against a synthetic private
|
|
53
|
+
transport and temporary files; its simulated numeric-UID boundary is not a real
|
|
54
|
+
root-lock test. `spec/vm_runtime_spec.rb` verifies ownership and QEMU endpoints.
|
|
55
|
+
`spec/vm_system_account_spec.rb` checks one-time regular account preparation with
|
|
56
|
+
synthetic passwd/shadow data. Run real gates with available runtime and acceleration:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
EMPEIRA_RUNTIME_MANAGEMENT_INTEGRATION=1 EMPEIRA_VM_RUNTIME=docker \
|
|
60
|
+
EMPEIRA_RUNTIME_MANAGEMENT_PROVIDERS=vm \
|
|
61
|
+
bundle exec rspec spec/integration/node_runtime_management_spec.rb
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Add `--example 'after Puppet locks root'` for the dedicated account-independent
|
|
65
|
+
management and user SSH acceptance scenario. The fixture uses persistent guest
|
|
66
|
+
files, disables the automatic Puppet service through ordinary Puppet resources,
|
|
67
|
+
and waits for completed user sessions to disappear before deleting their account.
|
|
68
|
+
The CLI agent runs remain real and include native exits 4/6 and retry.
|
|
69
|
+
|
|
70
|
+
Select `container` and `EMPEIRA_VM_RUNTIME=podman` for the corresponding rootless
|
|
71
|
+
Podman package/PATH/reconciliation gate. These remain manual, capability-dependent
|
|
72
|
+
tests rather than additions to the automatic heavy CI matrix.
|
|
73
|
+
For available Rocky Linux images, `EMPEIRA_DNF_RUNTIME_INTEGRATION=1` enables
|
|
74
|
+
`spec/integration/node_dnf_proxy_spec.rb` for containers and accelerated VMs. It
|
|
75
|
+
installs through a Puppet-owned additional signed repository while retaining the
|
|
76
|
+
original sources, then verifies restart and proxy disable/enable reconciliation.
|
|
77
|
+
The gate defaults to Rocky 9; set `EMPEIRA_DNF_GUEST_VERSION=8` to exercise Rocky 8.
|
|
78
|
+
|
|
79
|
+
Network regression gates exercise both node providers through their production
|
|
80
|
+
transports. The DNS gate checks live rewrite reloads without replacing nodes or
|
|
81
|
+
DNS. The redirect gate checks payload preservation, flow revocation and refusal
|
|
82
|
+
of external fallback under both runtimes. Run them on a capable local host:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
EMPEIRA_DNS_NODE_INTEGRATION=1 EMPEIRA_VM_RUNTIME=docker \
|
|
86
|
+
bundle exec rspec spec/integration/dns_rewrites_nodes_spec.rb
|
|
87
|
+
EMPEIRA_INTEGRATION=direct-egress EMPEIRA_REDIRECT_VM=1 \
|
|
88
|
+
EMPEIRA_REQUIRED_RUNTIMES=docker,podman \
|
|
89
|
+
bundle exec rspec spec/integration/network_redirects_spec.rb
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
For workflow changes, parse `.github/workflows/*.yml` and run `actionlint` when
|
|
93
|
+
available. Review action pins, triggers and permissions as well as YAML syntax.
|
|
94
|
+
See [contributing](../CONTRIBUTING.md) for review, commit and label conventions.
|
|
95
|
+
|
|
96
|
+
### Ruby 4.0 compatibility
|
|
97
|
+
|
|
98
|
+
Ruby 3.4 and 4.0 are supported. The deterministic suite passed locally on Linux
|
|
99
|
+
x86_64 with Ruby 3.4.7 and 4.0.7. Ruby 4.0 validation used an official Ruby container;
|
|
100
|
+
it does not establish macOS, container-engine or accelerated VM integration results.
|
|
101
|
+
|
|
102
|
+
Source development uses Bundler 4.0.22 from `Gemfile.lock`, matching the existing
|
|
103
|
+
module-helper tooling. With Ruby 4.0.7, the previous Bundler 2.4.19 redefined
|
|
104
|
+
`Gem::Platform` constants and emitted warnings in child processes. This failed 14
|
|
105
|
+
strict stderr, streaming, Bash completion and Puppetfile installer tests. Updating
|
|
106
|
+
Bundler preserves those output assertions; no application output filtering or
|
|
107
|
+
warning suppression is used. The dependency gem versions are unchanged.
|
|
108
|
+
|
|
109
|
+
The test checkout must be writable: the QEMU monitor-directory cleanup fixture
|
|
110
|
+
uses the checkout as a synthetic home. A read-only container bind mount caused one
|
|
111
|
+
additional filesystem failure; the compatibility run uses a writable disposable
|
|
112
|
+
copy. This fixture does not launch QEMU or establish real VM compatibility.
|
|
113
|
+
|
|
114
|
+
## Real runtime tests
|
|
115
|
+
|
|
116
|
+
Docker needs a reachable Linux engine 28+ with isolated bridge and helper support.
|
|
117
|
+
Podman needs rootless Netavark; cgroup v2 is required for enforced limits and systemd
|
|
118
|
+
nodes. Bind mounts must be visible at canonical host paths. Runtime tests pull public
|
|
119
|
+
images and need sufficient memory, disk space and registry/package access. Chromium
|
|
120
|
+
requires substantially more storage than the standard OpenVox smoke.
|
|
121
|
+
|
|
122
|
+
Run one explicit scope and runtime through the existing test driver:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
EMPEIRA_TEST_SCOPE=containers EMPEIRA_REQUIRED_RUNTIMES=docker \
|
|
126
|
+
bundle exec ruby script/integration.rb
|
|
127
|
+
EMPEIRA_TEST_SCOPE=services EMPEIRA_REQUIRED_RUNTIMES=podman \
|
|
128
|
+
bundle exec ruby script/integration.rb
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
| Scope | Existing suites / behavior |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| `containers` | Runtime contracts and real Ubuntu/RPM node lifecycle |
|
|
134
|
+
| `services` | Control plane, exported resources, proxy policy, OpenVox View and generated service YAML |
|
|
135
|
+
| `nodes` | Default OpenVox lifecycle and signed DNF installation |
|
|
136
|
+
| `network` | Gateway allow/deny/revocation and transparent TCP redirects from a managed container and Puppet server; Docker also exercises DNS resolvers/rewrites |
|
|
137
|
+
| `images` | Native metadata, immutable pins, reconciliation and synthetic registry authentication |
|
|
138
|
+
| `lifecycle` | Isolated runtime smoke, Hiera/EYAML, SSH, ownership and cleanup |
|
|
139
|
+
| `mounts` | Read-only/writable server mounts and selective reconciliation |
|
|
140
|
+
| `development` | Environment caching, live code and package bootstrap |
|
|
141
|
+
| `node-tools` | Diagnostic tools and agent-free node recipes |
|
|
142
|
+
| `modules` | Synthetic Git/r10k synchronization, live mounts and offline reuse |
|
|
143
|
+
| `update-plane` | Disposable helpers, artifact refresh and public Forge acquisition without infrastructure |
|
|
144
|
+
| `browser` | Real Chromium UI, internal reachability and isolation |
|
|
145
|
+
| `vm` | Accelerated VM lifecycle, proxy policy and dummy/VLAN interface reconciliation |
|
|
146
|
+
| `redirect-nodes` | TCP redirects from existing container/accelerated VM nodes and Puppet server; preserved HTTP bytes, target recreation, connection revocation and external canary |
|
|
147
|
+
| `dns-nodes` | DNS rewrite reload/removal with real container and accelerated VM nodes |
|
|
148
|
+
| `shared-network` | Production container/VM TCP/UDP peer lifecycle |
|
|
149
|
+
| `full` | All listed container scopes; excludes VM/dns-nodes/redirect-nodes/shared-network |
|
|
150
|
+
|
|
151
|
+
The `Manual runtime integration` workflow exposes these scopes through
|
|
152
|
+
`workflow_dispatch`. It selects one engine and has no automatic or scheduled heavy
|
|
153
|
+
run. A required unavailable runtime fails instead of becoming a successful skip.
|
|
154
|
+
Public-source outages and registry rate limits remain real validation failures.
|
|
155
|
+
|
|
156
|
+
The focused Squid regression uses a synthetic HTTP/HTTPS server on an isolated
|
|
157
|
+
private RFC 1918 subnet. Allowed and denied domains resolve to the same address;
|
|
158
|
+
the test checks domain allowlists, hostname rules, proxy reconciliation and blocked
|
|
159
|
+
direct egress for both engines:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
EMPEIRA_INTEGRATION=1 EMPEIRA_REQUIRED_RUNTIMES=docker,podman \
|
|
163
|
+
bundle exec rspec spec/integration/control_plane_spec.rb --example 'allows selected'
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The automatic PR workflow runs the existing Ubuntu default node lifecycle test:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
EMPEIRA_INTEGRATION=1 EMPEIRA_REQUIRED_RUNTIMES=docker \
|
|
170
|
+
bundle exec rspec spec/integration/node_spec.rb \
|
|
171
|
+
--example 'docker runs the default OpenVox node' --format documentation
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
It creates a temporary Git control repository with an empty `.empeira.yaml`, applies
|
|
175
|
+
a real Hiera-backed file resource, verifies default agent installation and CA
|
|
176
|
+
signing, checks a second run returns zero changes, and waits for the actual catalog
|
|
177
|
+
and changed/unchanged reports in PuppetDB. It also exercises state retention, live
|
|
178
|
+
edits, certificate cleanup/reuse and CA recreation. Failure diagnostics are bounded
|
|
179
|
+
and sanitized. Cleanup runs after failures and verifies that workspace-labeled
|
|
180
|
+
containers, networks and volumes are absent. No global prune is used.
|
|
181
|
+
The workflow reads all software pins from `config/defaults.yaml`; it needs no
|
|
182
|
+
repository secrets and uses public artifacts only.
|
|
183
|
+
|
|
184
|
+
Before the PR smoke, its disposable hosted Docker daemon uses Google's public
|
|
185
|
+
[Docker Hub cache](https://docs.cloud.google.com/artifact-registry/docs/pull-cached-dockerhub-images)
|
|
186
|
+
at `mirror.gcr.io`. Setup preserves existing daemon settings and verifies the active
|
|
187
|
+
mirror after restart. This also covers Docker Hub base images used by local builds;
|
|
188
|
+
GHCR images keep their original source. Image references, configured digest pins,
|
|
189
|
+
TLS verification and the complete smoke assertions remain unchanged. Cache hits
|
|
190
|
+
avoid the shared runner's anonymous Docker Hub pull quota. Cache misses still use
|
|
191
|
+
Docker Hub, and acquisition failures remain failures. The public-only smoke uses a
|
|
192
|
+
private, empty `DOCKER_CONFIG` directory instead of inheriting runner registry
|
|
193
|
+
credentials. Failures include bounded, sanitized Docker daemon diagnostics so a
|
|
194
|
+
failed mirror and canonical-registry fallback remain visible. Local engines and
|
|
195
|
+
workspace DNS, gateway and isolation policy are unaffected by this CI-only setup.
|
|
196
|
+
|
|
197
|
+
The APT authentication regression uses a local HTTPS repository with synthetic Basic
|
|
198
|
+
credentials and an ephemeral GPG signing key. It checks the helper's effective
|
|
199
|
+
`auth.conf.d` configuration, private file mode and exact credential bytes, then
|
|
200
|
+
verifies metadata returns 401 before one interactive login and 200 after the retry.
|
|
201
|
+
The selected package download must reuse that login and pass its SHA-256 check.
|
|
202
|
+
It requires host `gpg`/`gpgconf` and a locally reachable container engine; helper and
|
|
203
|
+
host TLS verification remain enabled. Run it explicitly for either engine:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
EMPEIRA_INTEGRATION=agent-auth EMPEIRA_REQUIRED_RUNTIMES=docker \
|
|
207
|
+
bundle exec rspec spec/integration/agent_repository_auth_spec.rb --example docker
|
|
208
|
+
EMPEIRA_INTEGRATION=agent-auth EMPEIRA_REQUIRED_RUNTIMES=podman \
|
|
209
|
+
bundle exec rspec spec/integration/agent_repository_auth_spec.rb --example podman
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Lightweight CI runs deterministic RSpec excluding `spec/integration`, RuboCop and
|
|
213
|
+
both dependency audits. Both quality and PR smoke support `main` and `initial`
|
|
214
|
+
during the transition; no branch migration is performed by a workflow.
|
|
215
|
+
|
|
216
|
+
## VM and shared-network prerequisites
|
|
217
|
+
|
|
218
|
+
Use real KVM on Linux/WSL2 or HVF on macOS, QEMU, `qemu-img`, `xorriso`, OpenSSH and
|
|
219
|
+
any required firmware. Preflight runs before image/cache or runtime mutation.
|
|
220
|
+
Rootless Podman also needs writable TUN/KVM inside its namespace. See
|
|
221
|
+
[VM installation](installation.md#vm-prerequisites) and
|
|
222
|
+
[networking](networking.md#runtime-attachment-and-privilege-boundary).
|
|
223
|
+
|
|
224
|
+
The VM scope also includes `spec/integration/vm_interfaces_spec.rb`. It observes real
|
|
225
|
+
Linux dummy/VLAN types, VLAN IDs, addresses and activation, checks Facter JSON, and
|
|
226
|
+
reads a file written by the first catalog from the ordinary network bindings. It
|
|
227
|
+
creates the VM with both a 32 GiB disk and interface rules, verifies the thin overlay,
|
|
228
|
+
unchanged base checksum and root filesystem growth, and checks package installation.
|
|
229
|
+
Later interface edits and removal use `vm.disk: 48` while retaining the original
|
|
230
|
+
32 GiB capacity through reconciliation and restart. The deterministic VM provider
|
|
231
|
+
regressions verify root growth precedes packages and interfaces, and that failed
|
|
232
|
+
growth blocks both features, enrollment and Puppet.
|
|
233
|
+
The real gate also tests idempotent `up`, stop/start restoration, address/VLAN edits and removal,
|
|
234
|
+
with managed SSH, DNS, proxy, gateway redirects and Puppet TLS checks. This gate
|
|
235
|
+
requires the same capable disposable host; deterministic guest models do not prove
|
|
236
|
+
real kernel or Facter compatibility.
|
|
237
|
+
|
|
238
|
+
The real VM lifecycle regression verifies the default managed SSH login and explicit
|
|
239
|
+
overrides, then exercises retained disk and console recovery. A second case injects
|
|
240
|
+
a permanent guest error at the final APT backup removal: the restored archive must
|
|
241
|
+
remain verifiable, Puppet must stay blocked, and SSH/console access must release the
|
|
242
|
+
workspace lock while preventing concurrent stop of that instance. The injected error
|
|
243
|
+
does not reproduce an unexplained historical SSH disconnect.
|
|
244
|
+
The lifecycle case also verifies a 32 GiB thin overlay, unchanged base checksum,
|
|
245
|
+
grown root partition/filesystem, package installation and `df -h /`. After changing
|
|
246
|
+
`vm.disk` to 48 GiB, workspace reconciliation and restart must retain the 32 GiB disk.
|
|
247
|
+
The VM lifecycle and container `lifecycle` smoke also load personal SSH defaults
|
|
248
|
+
before creating nodes. They exercise hostname rules, `~/` identity expansion,
|
|
249
|
+
independent CLI overrides and the unchanged internal bootstrap/Puppet transports.
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
EMPEIRA_VM_INTEGRATION=1 EMPEIRA_VM_RUNTIME=docker \
|
|
253
|
+
bundle exec rspec spec/integration/vm_spec.rb --format documentation
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
EMPEIRA_TEST_SCOPE=vm EMPEIRA_REQUIRED_RUNTIMES=docker \
|
|
258
|
+
bundle exec ruby script/integration.rb
|
|
259
|
+
EMPEIRA_TEST_SCOPE=shared-network EMPEIRA_REQUIRED_RUNTIMES=podman \
|
|
260
|
+
bundle exec ruby script/integration.rb
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
GitHub VM scopes require a dedicated disposable self-hosted Linux/AMD64 runner
|
|
264
|
+
labeled `empeira-vm`, with the selected runtime and acceleration already configured.
|
|
265
|
+
Ordinary GitHub-hosted runners are not assumed to have KVM/HVF. Use only trusted
|
|
266
|
+
manual revisions on that runner; do not expose it to fork PR code. A macOS/HVF
|
|
267
|
+
host runs the same local gates separately. Report Linux/WSL2, macOS, amd64 and
|
|
268
|
+
arm64 execution independently.
|
|
269
|
+
|
|
270
|
+
The lower-level regression proofs remain opt-in:
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
EMPEIRA_SHARED_NETWORK=1 bundle exec rspec spec/integration/shared_network_spec.rb
|
|
274
|
+
EMPEIRA_MACOS_NETWORK=podman bundle exec rspec spec/integration/macos_shared_network_spec.rb
|
|
275
|
+
EMPEIRA_MACOS_NETWORK=docker bundle exec rspec spec/integration/macos_shared_network_spec.rb
|
|
276
|
+
EMPEIRA_SHARED_GUEST_CHECK=1 bundle exec rspec spec/integration/shared_guest_artifact_spec.rb
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The last command is an explicit TCG test-artifact diagnostic, not evidence of
|
|
280
|
+
accelerated product VM support. These proofs do not substitute for the production
|
|
281
|
+
peer lifecycle gate. Test arbitrary TCP/UDP between providers, internal browser
|
|
282
|
+
reachability, DNS, egress revocation, unchanged node identities and owned cleanup.
|
|
283
|
+
|
|
284
|
+
The network scope includes real transparent redirect tests for both runtimes.
|
|
285
|
+
The accelerated scope adds a managed QEMU VM to the same traffic assertions:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
EMPEIRA_TEST_SCOPE=redirect-nodes EMPEIRA_REQUIRED_RUNTIMES=docker bundle exec ruby script/integration.rb
|
|
289
|
+
EMPEIRA_TEST_SCOPE=redirect-nodes EMPEIRA_REQUIRED_RUNTIMES=podman bundle exec ruby script/integration.rb
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
It verifies DELETE/path/Host/custom header/body and a complete 64 KiB response,
|
|
293
|
+
same-service hairpin connections, changed source/target ports, multiple sources,
|
|
294
|
+
owned target recreation at a different IP, unchanged node/service identities,
|
|
295
|
+
preserved connections on identical `up`, revoked established connections on removal,
|
|
296
|
+
and zero requests to an external canary even with an overlapping egress grant.
|
|
297
|
+
This manual scope requires KVM/HVF preflight and is excluded from `full` and normal CI.
|
|
298
|
+
|
|
299
|
+
The Docker network scope includes real CoreDNS tests for exact DNS rewrites:
|
|
300
|
+
|
|
301
|
+
```sh
|
|
302
|
+
EMPEIRA_INTEGRATION=1 EMPEIRA_REQUIRED_RUNTIMES=docker \
|
|
303
|
+
bundle exec rspec spec/integration/dns_rewrites_spec.rb
|
|
304
|
+
EMPEIRA_TEST_SCOPE=dns-nodes EMPEIRA_REQUIRED_RUNTIMES=docker \
|
|
305
|
+
bundle exec ruby script/integration.rb
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
The first gate uses isolated CoreDNS and DNS-client containers to check A/AAAA/CNAME
|
|
309
|
+
answers, dynamic service addresses, exact matching, reload/removal and no external
|
|
310
|
+
fallback. The manual `dns-nodes` scope additionally requires accelerated QEMU and
|
|
311
|
+
tests both real container and VM nodes across repeated `up` without restarting
|
|
312
|
+
them. It is deliberately separate from ordinary CI and container-only `full`.
|
|
313
|
+
|
|
314
|
+
## Build information and releases
|
|
315
|
+
|
|
316
|
+
GitHub tags are the released-version authority. `BuildInfo` embeds version, revision
|
|
317
|
+
and UTC build time without requiring Git at runtime. Source checkouts report
|
|
318
|
+
`development`; the gem packaging fallback is `0.0.0.development`.
|
|
319
|
+
|
|
320
|
+
The manual release workflow accepts `tag`, `channel` (`alpha`, `beta`, `rc`, `stable`)
|
|
321
|
+
and `dry_run` (default true). Dispatch it from `main`; a prerelease tag must match
|
|
322
|
+
its channel, for example `v0.1.0-alpha.1`. Other branches and existing tags/releases
|
|
323
|
+
are rejected. Quality and real Docker/OpenVox gates must pass before the build.
|
|
324
|
+
|
|
325
|
+
The build uses the existing `rake build_info` task in a temporary source staging
|
|
326
|
+
directory, builds an installable gem, and checks its contents, license, normalized
|
|
327
|
+
Gem version and exact embedded metadata. RubyGems normalizes a tag such as
|
|
328
|
+
`v0.1.0-alpha.1` to gem version `0.1.0.pre.alpha.1`; CLI BuildInfo retains
|
|
329
|
+
`0.1.0-alpha.1`. No source version file or generated commit is maintained.
|
|
330
|
+
|
|
331
|
+
Test the build locally without creating tags or contacting GitHub:
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
EMPEIRA_BUILD_VERSION=v0.1.0-alpha.1 \
|
|
335
|
+
EMPEIRA_RELEASE_CHANNEL=alpha \
|
|
336
|
+
EMPEIRA_BUILD_REVISION=0123456789abcdef0123456789abcdef01234567 \
|
|
337
|
+
EMPEIRA_BUILD_TIME=2026-01-01T00:00:00Z \
|
|
338
|
+
bundle exec ruby script/release.rb build
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
The result is in ignored `pkg/`. Source `lib/empeira/build.json` is untouched.
|
|
342
|
+
The lower-level task also supports `rake 'build_info[OUTPUT_PATH]'`; without that
|
|
343
|
+
argument it writes the ignored source metadata. Remove source metadata to return
|
|
344
|
+
that checkout to development mode.
|
|
345
|
+
|
|
346
|
+
For publishing, only the final job gets `contents: write`. It downloads the exact
|
|
347
|
+
built gem, checks its checksum and metadata, confirms the selected revision is still
|
|
348
|
+
`main`, creates the tag atomically and prepares a draft release with its asset and
|
|
349
|
+
[GitHub native release notes](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes).
|
|
350
|
+
It verifies the draft's tag revision, release channel and sole uploaded gem's name,
|
|
351
|
+
size and SHA-256 before publishing. A final API read verifies the published state
|
|
352
|
+
and the same tag/asset; missing assets, a retained draft or an API error fail the run.
|
|
353
|
+
Alpha/beta/rc are prereleases and do not become latest stable.
|
|
354
|
+
Dry-run performs all quality/build gates but skips the entire publishing job.
|
|
355
|
+
|
|
356
|
+
### Release failure and recovery
|
|
357
|
+
|
|
358
|
+
Tag creation and GitHub release publication are separate operations. A failed run
|
|
359
|
+
can leave a tag with no visible release, an incomplete draft, or an already published
|
|
360
|
+
release when the final verification failed. None of these states is treated as a
|
|
361
|
+
successful workflow run. Validation reports an existing draft/published **GitHub
|
|
362
|
+
release** first; an existing **tag** without a visible release gets a separate
|
|
363
|
+
diagnostic. A read token may not see a retained draft, so maintainers must inspect
|
|
364
|
+
both the release list and the failed run with write access.
|
|
365
|
+
|
|
366
|
+
1. Inspect the failed publishing step, the tag's commit, draft/published state and
|
|
367
|
+
attached assets. Compare the tag with the tested revision and the gem with the
|
|
368
|
+
build job's checksum and embedded BuildInfo. Workflow artifacts are retained for
|
|
369
|
+
seven days; do not substitute an unverified rebuild.
|
|
370
|
+
2. For a tag without a release or an incomplete draft, a maintainer may manually
|
|
371
|
+
complete the original publication at that exact tested revision using the verified
|
|
372
|
+
artifact and native release notes. Verify all assets before publishing the draft.
|
|
373
|
+
If the original artifact or validation evidence is unavailable, choose a new version.
|
|
374
|
+
3. If publication already happened, inspect and verify the remote release instead
|
|
375
|
+
of retrying publication. An incorrect or incomplete published release requires a
|
|
376
|
+
corrected release under a new version. A failed verification does not prove that
|
|
377
|
+
publication was rolled back.
|
|
378
|
+
|
|
379
|
+
The workflow never resumes an existing tag/release, deletes tags, moves tags or
|
|
380
|
+
reuses published version names. Rerunning it with the same retained tag is rejected;
|
|
381
|
+
another workflow run requires a new unused version. Manual recovery does not turn
|
|
382
|
+
the original failed run green.
|
|
383
|
+
|
|
384
|
+
With [GitHub Immutable Releases](https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases)
|
|
385
|
+
enabled, published assets cannot be added, replaced or deleted, and the associated
|
|
386
|
+
tag cannot be moved or deleted while the release exists. Even deleting that release
|
|
387
|
+
does not permit reuse of its tag name. Drafts remain editable until publication;
|
|
388
|
+
the workflow therefore uploads and verifies the entire asset set before publishing.
|
|
389
|
+
Title and release-note edits do not repair incorrect immutable assets.
|
|
390
|
+
|
|
391
|
+
Release notes use merged PR labels from `.github/release.yml`, independently of
|
|
392
|
+
Conventional Commit types. See [label conventions](../CONTRIBUTING.md#release-note-labels).
|
|
393
|
+
The first distribution is a GitHub-attached Ruby gem; RubyGems.org publication,
|
|
394
|
+
standalone Linux/macOS binaries and automatic self-update are not implemented.
|
|
395
|
+
|
|
396
|
+
## Dependency and image provenance
|
|
397
|
+
|
|
398
|
+
Thor is the sole application runtime gem. Development tools and the isolated r10k
|
|
399
|
+
installer are separate dependency resolutions. Dependencies are not vendored into
|
|
400
|
+
the release gem. Check upstream licensing and advisories before upgrades:
|
|
401
|
+
|
|
402
|
+
- [Thor](https://rubygems.org/gems/thor), [RSpec](https://rubygems.org/gems/rspec),
|
|
403
|
+
[RuboCop](https://rubygems.org/gems/rubocop), [Rake](https://rubygems.org/gems/rake)
|
|
404
|
+
and [Bundler](https://rubygems.org/gems/bundler): MIT.
|
|
405
|
+
- [bundler-audit](https://github.com/rubysec/bundler-audit): GPL-3.0-or-later development tool.
|
|
406
|
+
- [r10k](https://github.com/puppetlabs/r10k) and
|
|
407
|
+
[puppet_forge](https://github.com/puppetlabs/forge-ruby): Apache-2.0; reviewed versions
|
|
408
|
+
and checksums are in `resources/modules/Gemfile.lock`. Log4r's packaged
|
|
409
|
+
`doc/content/license.html` supplies permissive Ruby-style terms.
|
|
410
|
+
- The official [Go builder](https://github.com/docker-library/golang) uses BSD-style
|
|
411
|
+
Go licensing; its notice is retained in the adapter image. The adapter uses only
|
|
412
|
+
the standard library. Go is not a host prerequisite and no compiled adapter is bundled.
|
|
413
|
+
- GitHub-owned checkout/upload/download actions and ruby/setup-ruby are pinned by
|
|
414
|
+
commit; their MIT notices stay upstream. No action code is copied into the project.
|
|
415
|
+
|
|
416
|
+
Preserve package/image notices in locally built helpers. Registry pins establish
|
|
417
|
+
artifact integrity, not a universal signature or vulnerability guarantee.
|
|
418
|
+
See [image provenance](configuration.md#control-plane-images-and-provenance) and
|
|
419
|
+
[node image provenance](nodes.md#node-images-and-fidelity) for component sources.
|
|
420
|
+
|
|
421
|
+
The private adapter uses Python 3 already supplied by the reviewed cloud images;
|
|
422
|
+
it introduces no Python packages or guest-agent package bootstrap dependency.
|
|
423
|
+
QEMU Guest Agent was evaluated: its `guest-exec-status` returns captured output
|
|
424
|
+
only after exit, may report truncation and offers no command cancellation API.
|
|
425
|
+
The owned VirtIO adapter provides immediate streaming and process-group cleanup.
|
|
426
|
+
See the [QGA protocol reference](https://www.qemu.org/docs/master/interop/qemu-ga-ref.html).
|
|
427
|
+
|
|
428
|
+
Run `EMPEIRA_INTEGRATION=server-environment bundle exec rspec spec/integration/server_environment_spec.rb`
|
|
429
|
+
to check native timeout 0, live edits, CA retention, PuppetDB and idempotent up
|
|
430
|
+
under Docker/rootless Podman with the default server and a custom entrypoint
|
|
431
|
+
that ignores timeout environment mapping.
|
|
432
|
+
The same gate verifies startup and idempotent `up` with an explicit
|
|
433
|
+
`environment.conf` timeout override, preserving the file and distinguishing its
|
|
434
|
+
effective value from the native server setting.
|
|
435
|
+
|
|
436
|
+
Run the isolated diagnostics/recovery gate with each native runtime:
|
|
437
|
+
|
|
438
|
+
```sh
|
|
439
|
+
EMPEIRA_DIAGNOSTIC_INTEGRATION=1 EMPEIRA_DIAGNOSTIC_RUNTIME=docker bundle exec rspec spec/integration/node_diagnostics_spec.rb
|
|
440
|
+
EMPEIRA_DIAGNOSTIC_INTEGRATION=1 EMPEIRA_DIAGNOSTIC_RUNTIME=podman bundle exec rspec spec/integration/node_diagnostics_spec.rb
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Both runs include container and QEMU/KVM nodes; select either with
|
|
444
|
+
`EMPEIRA_DIAGNOSTIC_PROVIDERS=container` or `vm` when the other is unavailable.
|
|
445
|
+
The VM gate requires acceleration and exercises root locked by Puppet, disabled
|
|
446
|
+
SSHD, separated exec streams, exact exits, timeouts, concurrent VirtIO sessions,
|
|
447
|
+
real PTY resize/job control/fullscreen output and terminal restoration, restart,
|
|
448
|
+
serial console without the guest service, and cleanup after removal of the server
|
|
449
|
+
and control repository with an incompatible inventory. Projects and resources
|
|
450
|
+
are disposable and isolated; production infrastructure is never used.
|
|
451
|
+
|
|
452
|
+
## DNS endpoint, node identity and Hiera selection gates
|
|
453
|
+
|
|
454
|
+
These opt-in gates use disposable synthetic control repositories and owned helpers.
|
|
455
|
+
The DNS upstream is synthetic; no production DNS server is needed. The identity
|
|
456
|
+
gate requires working KVM/HVF and checks Ubuntu containers and VMs, multi-component
|
|
457
|
+
FQDNs, native Facter values, certnames, restart, legacy fact upgrades and an actual
|
|
458
|
+
first catalog using shared/provider Hiera data. Physical host files are checked for
|
|
459
|
+
changes. Run both container engines where available:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
EMPEIRA_HIERA_SELECTION_INTEGRATION=1 EMPEIRA_HIERA_SELECTION_RUNTIME=docker bundle exec rspec spec/integration/hiera_selection_spec.rb
|
|
463
|
+
EMPEIRA_DNS_REDIRECT_INTEGRATION=1 EMPEIRA_DNS_REDIRECT_RUNTIME=docker bundle exec rspec spec/integration/dns_redirects_spec.rb
|
|
464
|
+
EMPEIRA_NODE_IDENTITY_INTEGRATION=1 EMPEIRA_NODE_IDENTITY_RUNTIME=docker bundle exec rspec spec/integration/node_identity_spec.rb
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Repeat with `podman`. Hiera selection uses the configured server image, including
|
|
468
|
+
priority/merge lookups and a negative production-node fixture with no Empeira fact.
|
|
469
|
+
The DNS gate checks UDP/TCP, internal/external names, NXDOMAIN, large-answer fallback,
|
|
470
|
+
unavailable/recreated CoreDNS, a second workspace with a different subnet and
|
|
471
|
+
CoreDNS address, rule removal and idempotent reconciliation. Node identity also
|
|
472
|
+
checks both virtual DNS transports before and after node stop/start.
|