236 lines
5.5 KiB
TypeScript
236 lines
5.5 KiB
TypeScript
import * as command from '@pulumi/command';
|
|
import * as digitalocean from '@pulumi/digitalocean';
|
|
import * as hcloud from '@pulumi/hcloud';
|
|
import * as pulumi from '@pulumi/pulumi';
|
|
import * as tls from '@pulumi/tls';
|
|
import * as fs from 'fs';
|
|
|
|
const config = new pulumi.Config();
|
|
const hcloudToken = config.getSecret('hcloudToken');
|
|
|
|
if (hcloudToken === undefined) {
|
|
throw new Error('Hetzner Cloud token was not set');
|
|
}
|
|
|
|
const provider = new hcloud.Provider('provider', {
|
|
token: hcloudToken,
|
|
});
|
|
|
|
const sshKey = new tls.PrivateKey('sshKey', {
|
|
algorithm: 'ED25519',
|
|
});
|
|
|
|
export const privateKey = sshKey.privateKeyOpenssh;
|
|
|
|
privateKey.apply((privKey) =>
|
|
fs.writeFileSync('././local/private_key', privKey, { mode: '0600' })
|
|
);
|
|
|
|
const hetznerSshKey = new hcloud.SshKey(
|
|
'iac_default',
|
|
{
|
|
publicKey: sshKey.publicKeyOpenssh,
|
|
},
|
|
{ provider }
|
|
);
|
|
|
|
export const swarmMaster = await createSwarmCluster(1);
|
|
|
|
async function createSwarmCluster(nodeCount: number) {
|
|
const dockerImage = await hcloud.getImage(
|
|
{
|
|
name: 'docker-ce',
|
|
withArchitecture: 'x86',
|
|
},
|
|
{ provider }
|
|
);
|
|
|
|
const swarmNet = new hcloud.Network(
|
|
'swarm-net',
|
|
{
|
|
ipRange: '172.16.0.0/16',
|
|
},
|
|
{ provider }
|
|
);
|
|
|
|
const swarmSubNet = new hcloud.NetworkSubnet(
|
|
'swarm-subnet-dev',
|
|
{
|
|
networkId: swarmNet.id.apply((id) => +id),
|
|
type: 'cloud',
|
|
networkZone: 'eu-central',
|
|
ipRange: '172.16.1.0/24',
|
|
},
|
|
{ provider }
|
|
);
|
|
|
|
const vm = new hcloud.Server(
|
|
`node-1`,
|
|
{
|
|
sshKeys: [hetznerSshKey.id],
|
|
serverType: 'ccx23',
|
|
location: 'fsn1',
|
|
image: `${dockerImage.id}`,
|
|
labels: { nodeType: 'dockerSwarmNode' },
|
|
},
|
|
{ provider }
|
|
);
|
|
const srvNet = new hcloud.ServerNetwork(
|
|
'node_1-net',
|
|
{
|
|
serverId: vm.id.apply((id) => +id),
|
|
networkId: swarmNet.id.apply((id) => +id),
|
|
ip: '172.16.1.1',
|
|
},
|
|
{ provider }
|
|
);
|
|
const swarmInit = vm.id.apply((id) => {
|
|
return new command.remote.Command(
|
|
`dockerSwarmInit-${id}`,
|
|
{
|
|
connection: {
|
|
host: vm.ipv4Address,
|
|
user: 'root',
|
|
privateKey: privateKey,
|
|
},
|
|
create: [
|
|
'docker swarm init --advertise-addr 172.16.1.1',
|
|
'echo "Manager Token: $(docker swarm join-token -q manager)"',
|
|
'echo "Worker Token: $(docker swarm join-token -q worker)"',
|
|
].join('&&'),
|
|
},
|
|
{ dependsOn: [vm] }
|
|
);
|
|
});
|
|
|
|
const swarmTokens = {
|
|
worker: '',
|
|
manager: '',
|
|
};
|
|
|
|
swarmInit.stdout.apply((output) => {
|
|
const managerToken = output.match(/Manager Token: (\S+)/)?.[1];
|
|
const workerToken = output.match(/Worker Token: (\S+)/)?.[1];
|
|
|
|
if (managerToken && workerToken) {
|
|
swarmTokens.manager = managerToken;
|
|
swarmTokens.worker = workerToken;
|
|
}
|
|
});
|
|
|
|
// for (let i = 1; i < nodeCount; i++) {
|
|
// const node = new hcloud.Server(
|
|
// `node-${i + 1}`,
|
|
// {
|
|
// sshKeys: [hetznerSshKey.id],
|
|
// serverType: 'cx21',
|
|
// location: 'fsn1',
|
|
// image: `${dockerImage.id}`,
|
|
// labels: { nodeType: 'dockerSwarmNode' },
|
|
// userData: cloudConfig.then((cc) => cc.rendered),
|
|
// },
|
|
// { provider, dependsOn: [swarmInit] }
|
|
// );
|
|
|
|
// const srvNet = new hcloud.ServerNetwork(
|
|
// `node_${i + 1}-net`,
|
|
// {
|
|
// serverId: node.id.apply((id) => +id),
|
|
// networkId: swarmNet.id.apply((id) => +id),
|
|
// ip: `172.16.1.${i + 1}`,
|
|
// },
|
|
// { provider }
|
|
// );
|
|
|
|
// const swarmJoin = node.id.apply((id) => {
|
|
// return new command.remote.Command(
|
|
// `dockerSwarmInit-${id}`,
|
|
// {
|
|
// connection: {
|
|
// host: node.ipv4Address,
|
|
// user: 'root',
|
|
// privateKey: privateKey,
|
|
// },
|
|
// create: vm.ipv4Address.apply(
|
|
// (ip) =>
|
|
// `docker swarm join --token ${swarmTokens.worker} 172.16.1.1:2377`
|
|
// ),
|
|
// },
|
|
// { dependsOn: [node] }
|
|
// );
|
|
// });
|
|
// }
|
|
return vm;
|
|
}
|
|
|
|
const geniusceo = digitalocean.Domain.get(
|
|
'geniusceo',
|
|
'genius.ceo',
|
|
);
|
|
|
|
const wwwSubDomain = geniusceo.id.apply(
|
|
(id) =>
|
|
new digitalocean.DnsRecord('www', {
|
|
domain: id,
|
|
type: 'A',
|
|
value: swarmMaster.ipv4Address,
|
|
name: 'www',
|
|
})
|
|
);
|
|
|
|
const noSubDomain = geniusceo.id.apply(
|
|
(id) =>
|
|
new digitalocean.DnsRecord('noSub', {
|
|
domain: id,
|
|
type: 'A',
|
|
value: swarmMaster.ipv4Address,
|
|
name: '@',
|
|
})
|
|
);
|
|
|
|
const wildcardSubDomain = geniusceo.id.apply(
|
|
(id) =>
|
|
new digitalocean.DnsRecord('*', {
|
|
domain: id,
|
|
type: 'A',
|
|
value: swarmMaster.ipv4Address,
|
|
name: '*',
|
|
})
|
|
);
|
|
|
|
const installAnsibleDepsCmd = new command.remote.Command(
|
|
'installAnsibleDepsCmd',
|
|
{
|
|
connection: {
|
|
host: swarmMaster.ipv4Address,
|
|
user: 'root',
|
|
privateKey: privateKey,
|
|
},
|
|
create: `apt-get update && apt-get install -y python3-pip python3-jsondiff`,
|
|
}
|
|
);
|
|
|
|
const deployDockerStackCmd = new command.local.Command(
|
|
'deployDockerStackCmd',
|
|
{
|
|
create: pulumi.interpolate`ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u root -i "${swarmMaster.ipv4Address}," --private-key ./private_key ansible/playbook.yml`,
|
|
},
|
|
{
|
|
dependsOn: [installAnsibleDepsCmd],
|
|
}
|
|
);
|
|
|
|
const restartCmd = new command.remote.Command(
|
|
'restartCmd',
|
|
{
|
|
connection: {
|
|
host: swarmMaster.ipv4Address,
|
|
user: 'root',
|
|
privateKey: privateKey,
|
|
},
|
|
create: `shutdown -r 0`,
|
|
},
|
|
{
|
|
dependsOn: [deployDockerStackCmd],
|
|
}
|
|
); |