foundation/packages/pulumi-docker/index.ts

176 lines
5.2 KiB
TypeScript
Raw Normal View History

// index.ts
import * as pulumi from "@pulumi/pulumi";
import { Output } from "@pulumi/pulumi";
import * as docker from "@pulumi/docker";
export type DockerDeploymentsContainerArgs = {
name: string;
providerName: string;
image: string;
ports?: {
internal: number;
external: number;
protocol?: "tcp" | "udp";
ip?: string;
// hostname?: string;
}[];
volumes?: {
source: string;
target: string;
readOnly?: boolean;
type?: "bind" | "volume" | "tmpfs";
}[];
networks?: {
network: string;
aliases?: string[];
}[];
envs?: (string | Output<string>)[];
config: Partial<docker.ContainerArgs>;
providerConfig?: Partial<pulumi.CustomResourceOptions>;
};
interface DockerDeploymentsArgs {
provider: Record<
string,
{
host: pulumi.Input<string>;
sshPrivateKeyPath?: string;
networks?: Record<string, docker.NetworkArgs>;
} & Partial<docker.ProviderArgs>
>;
containers: DockerDeploymentsContainerArgs[];
}
export class DockerDeployments extends pulumi.ComponentResource {
private providers: Record<string, docker.Provider>;
public containers: {
container: docker.Container;
image: Output<docker.GetRegistryImageResult>;
volumes?: docker.Volume[];
}[];
private networks: Record<string, docker.Network>;
constructor(
name: string,
args: DockerDeploymentsArgs,
opts?: pulumi.ComponentResourceOptions,
) {
super("custom:resource:DockerDeployments", name, {}, opts);
this.providers = Object.entries(args.provider).reduce(
(acc, [providerName, providerConfig]) => {
acc[providerName] = new docker.Provider(
`${name}-${providerName}`,
{
host: providerConfig.host,
sshOpts: providerConfig.sshPrivateKeyPath
? [
"-o",
"StrictHostKeyChecking=no",
"-o",
"UserKnownHostsFile=/dev/null",
"-i",
providerConfig.sshPrivateKeyPath,
]
: undefined,
registryAuth: providerConfig.registryAuth,
},
{
parent: this,
},
);
return acc;
},
{} as Record<string, docker.Provider>,
);
this.networks = {};
Object.entries(args.provider).forEach(([providerName, providerConfig]) => {
if (providerConfig.networks) {
Object.entries(providerConfig.networks).forEach(
([name, networkConfig]) => {
this.networks[`${providerName}-${name}`] = new docker.Network(
`${providerName}-${name}`,
{
name: name,
attachable: true,
driver: "bridge",
internal: false,
...networkConfig,
},
{
parent: this,
provider: this.providers[providerName],
deleteBeforeReplace: true,
},
);
},
);
}
});
this.containers = [];
for (const containerConfig of args.containers) {
const provider = this.providers[containerConfig.providerName];
const containerImage = pulumi.output(
docker.getRegistryImage(
{
name: containerConfig.image,
},
{
parent: this,
provider: provider,
},
),
);
const container = new docker.Container(
`${containerConfig.providerName}-${containerConfig.name}`,
{
image: containerImage.apply((image) => image.name),
name: containerConfig.name,
hostname: containerConfig.name,
ports: containerConfig.ports?.map((port) => ({
internal: port.internal,
external: port.external,
protocol: port.protocol || "tcp",
ip: port.ip,
})),
mounts: containerConfig.volumes?.map((volume) => ({
source: volume.source,
target: volume.target,
readOnly: volume.readOnly || false,
type: volume.type || "volume",
})),
networksAdvanced: containerConfig.networks?.map((network) => ({
name: network.network,
aliases: network.aliases || [containerConfig.name],
})),
envs: containerConfig.envs
? [
...containerConfig.envs,
pulumi.interpolate`IMAGE_ID=${containerImage.apply((image) => image.id)}`,
]
: [
pulumi.interpolate`IMAGE_ID=${containerImage.apply((image) => image.id)}`,
],
...containerConfig.config,
},
{
parent: this,
provider: provider,
...containerConfig.providerConfig,
ignoreChanges: containerConfig.providerConfig?.ignoreChanges
? [...containerConfig.providerConfig.ignoreChanges, "image"]
: ["image"],
deleteBeforeReplace: true,
dependsOn:
containerConfig.networks && containerConfig.networks[0].network
? [this.networks[containerConfig.networks[0].network]]
: [],
},
);
this.containers.push({
image: containerImage,
container: container,
});
}
}
}