caddy.ts 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import * as k8s from '@pulumi/kubernetes'
  2. import * as pulumi from '@pulumi/pulumi'
  3. import * as dns from 'dns'
  4. /**
  5. * ServiceDeployment is an example abstraction that uses a class to fold together the common pattern of a
  6. * Kubernetes Deployment and its associated Service object.
  7. */
  8. export class CaddyServiceDeployment extends pulumi.ComponentResource {
  9. public readonly deployment: k8s.apps.v1.Deployment
  10. public readonly service: k8s.core.v1.Service
  11. public readonly hostname?: pulumi.Output<string>
  12. public readonly primaryEndpoint?: pulumi.Output<string>
  13. public readonly secondaryEndpoint?: pulumi.Output<string>
  14. constructor(name: string, args: ServiceDeploymentArgs, opts?: pulumi.ComponentResourceOptions) {
  15. super('k8sjs:service:ServiceDeployment', name, {}, opts)
  16. const labels = { app: name }
  17. let volumes: pulumi.Input<pulumi.Input<k8s.types.input.core.v1.Volume>[]> = []
  18. let caddyVolumeMounts: pulumi.Input<pulumi.Input<k8s.types.input.core.v1.VolumeMount>[]> = []
  19. async function lookupPromise(url: string): Promise<dns.LookupAddress[]> {
  20. return new Promise((resolve, reject) => {
  21. dns.lookup(url, { all: true }, (err: any, addresses: dns.LookupAddress[]) => {
  22. if (err) reject(err)
  23. resolve(addresses)
  24. })
  25. })
  26. }
  27. this.service = new k8s.core.v1.Service(
  28. name,
  29. {
  30. metadata: {
  31. name: name,
  32. namespace: args.namespaceName,
  33. labels: labels,
  34. },
  35. spec: {
  36. type: args.isMinikube ? 'NodePort' : 'LoadBalancer',
  37. ports: [
  38. { name: 'http', port: 80 },
  39. { name: 'https', port: 443 },
  40. ],
  41. selector: labels,
  42. },
  43. },
  44. { parent: this }
  45. )
  46. this.hostname = this.service.status.loadBalancer.ingress[0].hostname
  47. if (args.lbReady) {
  48. let caddyConfig: pulumi.Output<string>
  49. const lbIps: pulumi.Output<dns.LookupAddress[]> = this.hostname.apply((dnsName) => {
  50. return lookupPromise(dnsName)
  51. })
  52. function getProxyString(ipAddress: pulumi.Output<string>) {
  53. return pulumi.interpolate`${ipAddress}.nip.io/ws-rpc {
  54. reverse_proxy node-network:9944
  55. }
  56. ${ipAddress}.nip.io/http-rpc {
  57. reverse_proxy node-network:9933
  58. }
  59. `
  60. }
  61. caddyConfig = pulumi.interpolate`${getProxyString(lbIps[0].address)}
  62. ${getProxyString(lbIps[1].address)}`
  63. this.primaryEndpoint = pulumi.interpolate`${lbIps[0].address}.nip.io`
  64. this.secondaryEndpoint = pulumi.interpolate`${lbIps[1].address}.nip.io`
  65. const keyConfig = new k8s.core.v1.ConfigMap(
  66. name,
  67. {
  68. metadata: { namespace: args.namespaceName, labels: labels },
  69. data: { 'fileData': caddyConfig },
  70. },
  71. { parent: this }
  72. )
  73. const keyConfigName = keyConfig.metadata.apply((m) => m.name)
  74. caddyVolumeMounts.push({
  75. mountPath: '/etc/caddy/Caddyfile',
  76. name: 'caddy-volume',
  77. subPath: 'fileData',
  78. })
  79. volumes.push({
  80. name: 'caddy-volume',
  81. configMap: {
  82. name: keyConfigName,
  83. },
  84. })
  85. }
  86. this.deployment = new k8s.apps.v1.Deployment(
  87. name,
  88. {
  89. metadata: { namespace: args.namespaceName, labels: labels },
  90. spec: {
  91. selector: { matchLabels: labels },
  92. replicas: 1,
  93. template: {
  94. metadata: { labels: labels },
  95. spec: {
  96. containers: [
  97. {
  98. name: 'caddy',
  99. image: 'caddy',
  100. ports: [
  101. { name: 'caddy-http', containerPort: 80 },
  102. { name: 'caddy-https', containerPort: 443 },
  103. ],
  104. volumeMounts: caddyVolumeMounts,
  105. },
  106. ],
  107. volumes,
  108. },
  109. },
  110. },
  111. },
  112. { parent: this }
  113. )
  114. }
  115. }
  116. export interface ServiceDeploymentArgs {
  117. namespaceName: pulumi.Output<string>
  118. lbReady?: boolean
  119. isMinikube?: boolean
  120. }