Skip to content

Latest commit

 

History

History
168 lines (122 loc) · 7.43 KB

developing.md

File metadata and controls

168 lines (122 loc) · 7.43 KB

Developing Image Factory

Running with Docker Compose

docker-compose-{up|down} make targets are available for running Image Factory.

To run:

# Generate signing key
openssl ecparam -name prime256v1 -genkey -noout -out _out/cache-signing-key.key

# Build and run
make docker-compose-up

# Build and run (enterprise)
make docker-compose-up WITH_ENTERPRISE=true

# Build and run with debug symbols, serving UI assets from internal/frontend/http/ without rebuilding
make docker-compose-up WITH_DEBUG=true

To stop:

make docker-compose-down

Local overrides

If hack/dev/compose.override.yaml exists, make docker-compose-{up|down} passes it to Compose after hack/dev/compose.yaml. This file is git-ignored. Use it for local changes that should not be committed, such as extra environment variables, a different config file or a different port.

Configuration keys can be set with an IF_-prefixed environment variable (for example, registry.debug becomes IF_REGISTRY_DEBUG). The config file is loaded after the environment, so this only works for keys that hack/dev/config.yaml does not already set; to change those, replace the config file as shown below.

services:
  image-factory:
    environment:
      - IF_REGISTRY_DEBUG=true

To replace the whole configuration file instead:

configs:
  if_config:
    file: ./config.local.yaml # relative to hack/dev/

See the Compose merge rules for how the two files are combined.

Local development enables authentication by default and uses the htpasswd provider. The Compose configuration mounts hack/dev/htpasswd at the configured /etc/image-factory/htpasswd path.

When running make docker-compose-up or the integration tests, the extra extension catalog and an extra extension image and their signatures are automatically pushed to the local registry. You can push the extra images manually with push-extra-extensions (requires crane), optionally setting the EXTRA_EXTENSIONS_REGISTRY. The extra images are located under internal/integration/testdata/extra-extensions/.

Running Image Factory Manually

In order to run the Image Factory, generate a ECDSA key pair:

openssl ecparam -name prime256v1 -genkey -noout -out cache-signing-key.key

Run the Image Factory using the following config:

artifacts:
  # registry mirror for ghcr.io
  core:
    registry: 127.0.0.1:5004

  # private registry repository for schematics
  #
  # resolves to 127.0.0.1:5005/image-factory/schematic
  schematic:
    registry: 127.0.0.1:5005
    namespace: image-factory
    repository: schematic

  installer:
    # internal registry namespace to push installer images to
    internal:
      registry: 127.0.0.1:5005
      namespace: siderolabs

    # external registry namespace to redirect users to pull installer
    external:
      registry: 127.0.0.1:5005
      namespace: siderolabs

cache:
  oci:
    # private registry repository for cached assets
    registry: 127.0.0.1:5005
    namespace: image-factory
    repository: cache

  # path to the ECDSA private key (to sign cached assets)
  signingKeyPath: ./cache-signing-key.key

http:
  # external URL the Image Factory is available at
  externalURL: https://example.com/

Styling the UI

The UI uses the Talos design system. Templates use its color roles (bg-surface-card), type roles (type-body) and spacing steps (p-compact) instead of raw palette values, so both themes come from the same classes. The theme choice is stored in the browser and applied by js/theme.js before first paint.

make tailwind rebuilds internal/frontend/http/css/output.css and copies the Inter and JetBrains Mono files next to it, so the fonts are served by Image Factory and work in air-gapped installs. Both are committed, so rerun it after changing template classes or bumping the design system.

HTTP identity and operation ownership

Authentication publishes the authoritative typed authn.Principal to the request context. Request middleware does not keep a separate authentication identity or capture a username through an authentication callback. After request execution, audit projects the username from that principal into audit.Record.Username. This audit-time projection is intentional: removing legacy middleware-local username capture does not mean removing authenticated identity from audit records. The post-authentication request context is used, not the earlier context created before authentication. Requests rejected before authentication do not acquire an identity; public requests retain their existing audit bypass. Audit sink failures are logged and do not change the response.

TestRequestMiddlewareOrderingAndTypedAudit protects these rules alongside contract-before-auth ordering, streaming responses, and authenticated no-store.

Operation ownership checks compare runtime descriptors with the OpenAPI document, not an expected set inferred from those descriptors. Community and Enterprise assemblies are checked with browser capability both disabled and enabled. Every enabled operation must have exactly one owner; disabled and unknown operations must have none. Enterprise contract annotations describe product availability: the token UI shell remains registered in Community, and browser routes are registered only when the provider exposes browser capability. These exceptions are explicit in the configuration tests. Counterexamples exercise missing dispatched owners, duplicates, unknown operations, and disabled capabilities.

Running Integration Tests

Integration tests can be run with specific targets:

  • integration-direct
  • integration-s3
  • integration-cdn
  • integration-proxy-installer
  • integration-enterprise

Example running direct integration tests with registry mirrors (127.0.0.1:5004 is a registry mirror for ghcr.io, 127.0.0.1:5100 is an ephemeral local registry brought up by make automatically, and 127.0.0.1:5005 is a local registry for pushing images):

make integration-direct TEST_FLAGS="-test.image-registry=127.0.0.1:5004 -test.schematic-service-repository=127.0.0.1:5100/image-factory/schematic -test.installer-external-repository=127.0.0.1:5100/test -test.installer-internal-repository=127.0.0.1:5100/test -test.cache-repository=127.0.0.1:5100/image-factory/cache -test.signing-cache-repository=127.0.0.1:5100/image-factory/signing-cache -test.extra-extensions-manifest=127.0.0.1:5100/extension-testing/extensions" REGISTRY=127.0.0.1:5005

A test focus can be set with:

...  RUN_TESTS_DIRECT='TestIntegration/Schematic'

For Enterprise tests, use the following command:

make integration-enterprise TEST_FLAGS="-test.image-registry=127.0.0.1:5004 -test.schematic-service-repository=127.0.0.1:5100/image-factory/schematic -test.installer-external-repository=127.0.0.1:5100/test -test.installer-internal-repository=127.0.0.1:5100/test -test.cache-repository=127.0.0.1:5100/image-factory/cache -test.signing-cache-repository=127.0.0.1:5100/image-factory/signing-cache -test.extra-extensions-manifest=127.0.0.1:5100/extension-testing/extensions" REGISTRY=127.0.0.1:5005

(The only change is s/integration-direct/integration-enterprise/ in the target name, and the test focus variable will be RUN_TESTS_ENTERPRISE instead of RUN_TESTS_DIRECT.)