setup infrastructure as code project
This commit is contained in:
parent
455813ecbb
commit
9b2e286300
|
|
@ -0,0 +1,3 @@
|
||||||
|
/bin/
|
||||||
|
/node_modules/
|
||||||
|
.local/
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
config:
|
||||||
|
avicenna-infrastructure:hcloudToken:
|
||||||
|
secure: AAABAGlVe2bD1Y+vof1zy87jQIQLePGssfw4X7nuV6+afxSOPhhb7qVH/BkM9fS3ab5qqlCx8O1uCpZozfPAkMgL8Hx3Ib3eAgU6guj10wTCgV/vwhXiaE+bf7ZQgQgc
|
||||||
|
digitalocean:token:
|
||||||
|
secure: AAABAGies+t4YrcwhurOvELetL2jEoOhC2ejMHrGyvdgkmVgRlkR0idmT6EmgzpP09lmwtZRnxa7EjpAH92yUthZ1iuydorqo+meoXI91rrBdtd7jqJIC6qGbOyLWekUyXfRqxVeNA==
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
name: avicenna-infrastructure
|
||||||
|
description: Infrastructure Management to run the plattform and service applications of avicenna
|
||||||
|
runtime:
|
||||||
|
name: nodejs
|
||||||
|
options:
|
||||||
|
nodeargs: "--loader ts-node/esm --no-warnings --experimental-specifier-resolution=node"
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
tasks:
|
||||||
|
- import_role:
|
||||||
|
name: traefik
|
||||||
|
- import_role:
|
||||||
|
name: portainer
|
||||||
|
- import_role:
|
||||||
|
name: kestra
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
networks:
|
||||||
|
internal:
|
||||||
|
traefik_public:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
volumes:
|
||||||
|
- /srv/kestra/db:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: kestra
|
||||||
|
POSTGRES_USER: kestra
|
||||||
|
POSTGRES_PASSWORD: k3str4
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 10
|
||||||
|
networks:
|
||||||
|
- internal
|
||||||
|
|
||||||
|
kestra:
|
||||||
|
image: kestra/kestra:latest-full
|
||||||
|
entrypoint: /bin/bash
|
||||||
|
# Note that this is meant for development only. Refer to the documentation for production deployments of Kestra which runs without a root user.
|
||||||
|
user: "root"
|
||||||
|
command:
|
||||||
|
- -c
|
||||||
|
- /app/kestra server standalone --worker-thread=128
|
||||||
|
volumes:
|
||||||
|
- /srv/kestra/data:/app/storage
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /tmp/kestra-wd:/tmp/kestra-wd
|
||||||
|
environment:
|
||||||
|
KESTRA_CONFIGURATION: |
|
||||||
|
datasources:
|
||||||
|
postgres:
|
||||||
|
url: jdbc:postgresql://postgres:5432/kestra
|
||||||
|
driverClassName: org.postgresql.Driver
|
||||||
|
username: kestra
|
||||||
|
password: k3str4
|
||||||
|
kestra:
|
||||||
|
server:
|
||||||
|
basic-auth:
|
||||||
|
enabled: false
|
||||||
|
username: admin
|
||||||
|
password: kestra
|
||||||
|
repository:
|
||||||
|
type: postgres
|
||||||
|
storage:
|
||||||
|
type: local
|
||||||
|
local:
|
||||||
|
base-path: "/app/storage"
|
||||||
|
queue:
|
||||||
|
type: postgres
|
||||||
|
tasks:
|
||||||
|
tmp-dir:
|
||||||
|
path: /tmp/kestra-wd/tmp
|
||||||
|
url: http://localhost:8080/
|
||||||
|
networks:
|
||||||
|
- traefik_public
|
||||||
|
- internal
|
||||||
|
deploy:
|
||||||
|
labels:
|
||||||
|
- "traefik.docker.network=traefik_public"
|
||||||
|
- "traefik.http.routers.kestra.rule=Host(`kestra.genius.ceo`)"
|
||||||
|
- "traefik.http.routers.kestra.entrypoints=https"
|
||||||
|
- "traefik.http.routers.kestra.tls=true"
|
||||||
|
- "traefik.http.routers.kestra.tls.certresolver=main"
|
||||||
|
- "traefik.http.services.kestra.loadbalancer.server.port=8080"
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
version: '3.2'
|
||||||
|
|
||||||
|
services:
|
||||||
|
agent:
|
||||||
|
image: portainer/agent:2.16.1
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- /var/lib/docker/volumes:/var/lib/docker/volumes
|
||||||
|
networks:
|
||||||
|
- traefik_public
|
||||||
|
deploy:
|
||||||
|
mode: global
|
||||||
|
placement:
|
||||||
|
constraints: [node.platform.os == linux]
|
||||||
|
|
||||||
|
portainer:
|
||||||
|
image: portainer/portainer-ce:2.16.1
|
||||||
|
command: -H tcp://tasks.agent:9001 --tlsskipverify
|
||||||
|
ports:
|
||||||
|
- "9443:9443"
|
||||||
|
- "9000:9000"
|
||||||
|
- "8000:8000"
|
||||||
|
volumes:
|
||||||
|
- /srv/portainer/data:/data
|
||||||
|
networks:
|
||||||
|
- traefik_public
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
labels:
|
||||||
|
- "traefik.docker.network=traefik_public"
|
||||||
|
- "traefik.http.routers.portainer.rule=Host(`portainer.genius.ceo`)"
|
||||||
|
- "traefik.http.routers.portainer.entrypoints=https"
|
||||||
|
- "traefik.http.routers.portainer.tls=true"
|
||||||
|
- "traefik.http.routers.portainer.tls.certresolver=main"
|
||||||
|
- "traefik.http.services.portainer.loadbalancer.server.port=9000"
|
||||||
|
placement:
|
||||||
|
constraints: [node.role == manager]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik_public:
|
||||||
|
external: true
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
[global]
|
||||||
|
checkNewVersion = true
|
||||||
|
|
||||||
|
[accessLog]
|
||||||
|
filePath = "/access.log"
|
||||||
|
# Enable the Dashboard
|
||||||
|
[api]
|
||||||
|
dashboard = true
|
||||||
|
|
||||||
|
# Write out Traefik logs
|
||||||
|
[log]
|
||||||
|
level = "DEBUG"
|
||||||
|
filePath = "/traefik.log"
|
||||||
|
|
||||||
|
[entryPoints]
|
||||||
|
[entryPoints.http]
|
||||||
|
address = ":80"
|
||||||
|
[entryPoints.http.http.redirections.entryPoint]
|
||||||
|
to = "https"
|
||||||
|
scheme = "https"
|
||||||
|
|
||||||
|
[entryPoints.https]
|
||||||
|
address = ":443"
|
||||||
|
# [entryPoints.https.http.tls]
|
||||||
|
# certResolver = "main"
|
||||||
|
|
||||||
|
# Let's Encrypt
|
||||||
|
[certificatesResolvers.main.acme]
|
||||||
|
email = "ma@coachhamburg.com"
|
||||||
|
storage = "acme.json"
|
||||||
|
# uncomment to use staging CA for testing
|
||||||
|
# caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
# [certificatesResolvers.main.acme.tlsChallenge]
|
||||||
|
[certificatesResolvers.main.acme.dnsChallenge]
|
||||||
|
provider = "digitalocean"
|
||||||
|
# Uncomment to use HTTP validation, like a caveman!
|
||||||
|
# [certificatesResolvers.main.acme.httpChallenge]
|
||||||
|
# entryPoint = "http"
|
||||||
|
|
||||||
|
# Docker Traefik provider
|
||||||
|
[providers.docker]
|
||||||
|
endpoint = "unix:///var/run/docker.sock"
|
||||||
|
swarmMode = true
|
||||||
|
watch = true
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
version: "3.2"
|
||||||
|
|
||||||
|
# What is this?
|
||||||
|
#
|
||||||
|
# This stack exists solely to deploy the traefik_public overlay network, so that
|
||||||
|
# other stacks (including traefik-app) can attach to it
|
||||||
|
|
||||||
|
services:
|
||||||
|
scratch:
|
||||||
|
image: scratch
|
||||||
|
deploy:
|
||||||
|
replicas: 0
|
||||||
|
networks:
|
||||||
|
- public
|
||||||
|
|
||||||
|
networks:
|
||||||
|
public:
|
||||||
|
driver: overlay
|
||||||
|
attachable: true
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 172.16.200.0/24
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
DO_AUTH_TOKEN=dop_v1_34e88e03c46ded3af8e11389e80abbdc61d89e001058d1fbbb719422f64d91fc
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
version: "3.2"
|
||||||
|
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
image: traefik:v2.9.1
|
||||||
|
env_file: traefik.env
|
||||||
|
# Note below that we use host mode to avoid source nat being applied to our ingress HTTP/HTTPS sessions
|
||||||
|
# Without host mode, all inbound sessions would have the source IP of the swarm nodes, rather than the
|
||||||
|
# original source IP, which would impact logging. If you don't care about this, you can expose ports the
|
||||||
|
# "minimal" way instead
|
||||||
|
ports:
|
||||||
|
- target: 80
|
||||||
|
published: 80
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
- target: 443
|
||||||
|
published: 443
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
- target: 8080
|
||||||
|
published: 8080
|
||||||
|
protocol: tcp
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
- /srv/traefik/config:/etc/traefik
|
||||||
|
- /srv/traefik/data/traefik.log:/traefik.log
|
||||||
|
- /srv/traefik/data/access.log:/access.log
|
||||||
|
- /srv/traefik/data/acme.json:/acme.json
|
||||||
|
networks:
|
||||||
|
- traefik_public
|
||||||
|
# Global mode makes an instance of traefik listen on _every_ node, so that regardless of which
|
||||||
|
# node the request arrives on, it'll be forwarded to the correct backend service.
|
||||||
|
deploy:
|
||||||
|
mode: global
|
||||||
|
labels:
|
||||||
|
- "traefik.docker.network=traefik_public"
|
||||||
|
- "traefik.http.routers.api.rule=Host(`traefik.genius.ceo`)"
|
||||||
|
- "traefik.http.routers.api.entrypoints=https"
|
||||||
|
- "traefik.http.routers.api.tls.domains[0].main=genius.ceo"
|
||||||
|
- "traefik.http.routers.api.tls.domains[0].sans=*.genius.ceo"
|
||||||
|
- "traefik.http.routers.api.tls=true"
|
||||||
|
- "traefik.http.routers.api.tls.certresolver=main"
|
||||||
|
- "traefik.http.routers.api.service=api@internal"
|
||||||
|
- "traefik.http.services.dummy.loadbalancer.server.port=9999"
|
||||||
|
|
||||||
|
# uncomment this to enable forward authentication on the traefik api/dashboard
|
||||||
|
#- "traefik.http.routers.api.middlewares=forward-auth"
|
||||||
|
placement:
|
||||||
|
constraints: [node.role == manager]
|
||||||
|
|
||||||
|
networks:
|
||||||
|
traefik_public:
|
||||||
|
external: true
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Copy Stack Files
|
||||||
|
copy:
|
||||||
|
directory_mode: true
|
||||||
|
src: /Users/d3r0/dev/repositories/active/avicenna/infrastructure/ansible/resources/kestra
|
||||||
|
dest: /srv
|
||||||
|
- name: Deploy Kestra stack
|
||||||
|
community.docker.docker_stack:
|
||||||
|
state: present
|
||||||
|
name: kestra
|
||||||
|
compose:
|
||||||
|
- /srv/kestra/kestra.yml
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Copy Stack Files
|
||||||
|
copy:
|
||||||
|
directory_mode: true
|
||||||
|
src: /Users/d3r0/dev/repositories/active/avicenna/infrastructure/ansible/resources/portainer
|
||||||
|
dest: /srv
|
||||||
|
- name: Deploy Portainer stack
|
||||||
|
community.docker.docker_stack:
|
||||||
|
state: present
|
||||||
|
name: portainer
|
||||||
|
compose:
|
||||||
|
- /srv/portainer/portainer.yml
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
- name: Copy Stack Files
|
||||||
|
copy:
|
||||||
|
directory_mode: true
|
||||||
|
src: /Users/d3r0/dev/repositories/active/avicenna/infrastructure/ansible/resources/traefik
|
||||||
|
dest: /srv
|
||||||
|
- name: Deploy Traefik network stack
|
||||||
|
community.docker.docker_stack:
|
||||||
|
state: present
|
||||||
|
name: traefik
|
||||||
|
compose:
|
||||||
|
- /srv/traefik/network.yml
|
||||||
|
- name: Deploy Traefik app stack
|
||||||
|
community.docker.docker_stack:
|
||||||
|
state: present
|
||||||
|
name: traefik-app
|
||||||
|
compose:
|
||||||
|
- /srv/traefik/traefik.yml
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
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],
|
||||||
|
}
|
||||||
|
);
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "avicenna-infrastructure",
|
||||||
|
"main": "index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18",
|
||||||
|
"ts-node": "^10.9.2",
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@pulumi/cloudinit": "^1.3.0",
|
||||||
|
"@pulumi/command": "^0.9.1",
|
||||||
|
"@pulumi/digitalocean": "^4.23.0",
|
||||||
|
"@pulumi/docker": "^4.4.3",
|
||||||
|
"@pulumi/hcloud": "^1.16.1",
|
||||||
|
"@pulumi/kubernetes": "^3.24.2",
|
||||||
|
"@pulumi/pulumi": "^3.113.0",
|
||||||
|
"@pulumi/tls": "^4.11.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"strict": true,
|
||||||
|
"outDir": "bin",
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"stripInternal": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"pretty": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"forceConsistentCasingInFileNames": true
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.ts"
|
||||||
|
],
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue