# 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

Add an instance whose package is created with `kix.mkImport`:

<Snippet {...importExistingService} />

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.

:::caution[Generated network policy needs the other form]
An `out.fqdn` written as a string literal carries no information about the
Service behind it. A workload that uses the address gets a dependency edge,
but Kix cannot derive an egress rule. On a cluster with
[generated network policy](/docs/v0.1/how-to/platform-capabilities/enable-generated-network-policy/)
the call is dropped at runtime while `kix check` stays green.

Describe the Service instead of asserting its address, and let Kix derive the
address from the description:

```nix title="cluster.nix"
package = kix.mkImport {
  kind = "Service";
  apiVersion = "v1";
  from =
    { scope, ... }:
    {
      build =
        { self, ... }:
        {
          service = scope.mkResource {
            apiVersion = "v1";
            kind = "Service";
            name = "legacy-api";
            spec = {
              selector."app.kubernetes.io/name" = "legacy-api";
              ports = [
                {
                  port = 8080;
                  protocol = "TCP";
                }
              ];
            };
          };

          root = self.service;
        };
    };
};
```

Kix still does not render the Service. It uses this description to derive
`out.fqdn` and identify the pods reached through that address. The policy
generator needs both pieces of information. Make sure the selector matches
the live Service.
:::

## Use the imported outputs

Accept the alias as a package build argument and read the values you need:

<Snippet {...consumeImportedService} />

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

Evaluate the cluster before deploying it:

<Command {...check} />

Confirm that Kix classifies the instance as an import:

<Command {...listPackages} />

Render the manifests to verify the value received by the client:

<Command {...clientConfig} />

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.

:::note[Background]
See [Imports and existing cluster resources](/docs/v0.1/tutorials/13-imports-and-existing-cluster-resources/)
for a guided introduction, and [Imports vs managed packages](/docs/v0.1/explanation/imports-vs-managed-packages/)
for the ownership model.
:::