176 lines
5.2 KiB
TypeScript
176 lines
5.2 KiB
TypeScript
|
|
// 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,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|