How-to guide / Adopt existing resources
Import an existing service with kix.mkImport
This guide assumes the Service already exists and its name, namespace, and port are stable. Use an import when another system owns that Service and Kix packages need its connection details.
Declare the import
Section titled “Declare the import”Add an instance whose package is created with kix.mkImport:
27 package = kix.mkImport {28 kind = "Service";29 apiVersion = "v1";30 out = {31 name = "legacy-api";32 fqdn = "legacy-api.legacy.svc.${config.clusterDomain}";33 port = 8080;34 };35 };36 aliases = [ "legacyApi" ];Set kind and apiVersion to describe the existing resource. The out
attributes form the interface that consuming packages receive. They must
match the Service in the target cluster.
Kix verifies the imported object’s kind, API version, name, and namespace
before deployment. It does not verify the fqdn or port outputs. Those
values pass through unchanged, so an incorrect port can deploy successfully
and fail only at runtime.
The legacyApi alias lets a package request this import with a build argument
of the same name. Choose an alias that describes the dependency’s role rather
than its location. If the import provides one of Kix’s registered
infrastructure roles, such as dns, declare it with roles = [ "dns" ]
instead. The role name also acts as the dependency key. An imported role is a
weak provider, so a managed instance that claims the same role takes
precedence.
Use the imported outputs
Section titled “Use the imported outputs”Accept the alias as a package build argument and read the values you need:
19 clientConfig = scope.mkResource {20 apiVersion = "v1";21 kind = "ConfigMap";22 name = "legacy-api-client";23 data.endpoint = "http://${legacyApi.out.fqdn}:${toString legacyApi.out.port}";24 };25
26 root = self.clientConfig;This example writes the imported endpoint into a client ConfigMap. A workload could use the same values in environment variables or generated configuration.
Check the cluster
Section titled “Check the cluster”Evaluate the cluster before deploying it:
❱ kix check how-to-adoption
TOOL RESULT DETAILS
eval pass 21 manifests evaluated
scorecard pass 0 errors, 14 warnings, 2 info Confirm that Kix classifies the instance as an import:
❱ kix list packages --cluster how-to-adoption
NAME VERSION STATUS
client 1.0.0 installed [apps]
helm-web 1.0.0 installed [apps]
legacy-api - import [legacy]
legacy-api-contract 1.0.0 installed [apps]
legacy-web 1.0.0 installed [apps]
platform-dns - import [kube-system]
platform-storage - import [kube-system] Render the manifests to verify the value received by the client:
❱ kix build how-to-adoption --output json
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"name": "legacy-api-client",
"namespace": "apps"
},
"data": {
"endpoint": "http://legacy-api.legacy.svc.cluster.local:8080"
}
} Kix renders a PackageInstance marker for legacy-api, but it does not render
or update the Service itself. Keep the Service in the lifecycle of the system
that already owns it.
Import an outside service with a login
Section titled “Import an outside service with a login”Dependency contracts that carry a login put it in out.credentials. In a
cluster module that takes { ref, ... }:, kix.mkImport can point a field in
out at a secret or secret-ref instance with ref.<namespace>.<instance>.
Kix replaces the ref with that secret instance (so the consumer can call
dep.out.credentials.out.keyRef "password" with no package changes) and orders
the import marker after the secret.
Because a pod reads Secrets only from its own namespace, and Kix refuses a
Secret from another namespace at build time, place the import and its secret in
the consumer’s namespace with scope = "namespace":
1{ ref, packages, kix, ... }:2{3 instances.app.rds-login = {4 package = packages.secret;5 config.source = ./secrets/rds-login.sops.yaml;6 config.keys = [ "username" "password" ];7 };8 instances.app.database.package = kix.mkImport {9 scope = "namespace";10 out = {11 host = "app.abc123.eu-west-1.rds.amazonaws.com";12 port = "5432";13 database = "app";14 tls = true;15 credentials = ref.app.rds-login;16 };17 };18}This satisfies the database contract (kix.contracts.postgresDatabase) for
an outside PostgreSQL server such as RDS or Cloud SQL. The same pattern works
for an outside Redis cache (kix.contracts.redis, see Use a Redis server outside the cluster),
an authenticated mail server (kix.contracts.smtp),
or a single-issuer external OIDC provider (kix.contracts.oidc).
See Connect external databases, caches, mail, and single sign-on
for complete examples of each contract.