diff --git a/manifests/environment.yaml b/manifests/environment.yaml index f56be43..08dca25 100644 --- a/manifests/environment.yaml +++ b/manifests/environment.yaml @@ -9,4 +9,6 @@ metadata: name: dev namespace: dev spec: - domain: dev.mortenolsen.pro \ No newline at end of file + domain: one.dev.olsen.cloud + tls: + issuer: letsencrypt-prod \ No newline at end of file diff --git a/src/custom-resouces/authentik-server/authentik-server.controller.ts b/src/custom-resouces/authentik-server/authentik-server.controller.ts index 1d42b90..47b2c2a 100644 --- a/src/custom-resouces/authentik-server/authentik-server.controller.ts +++ b/src/custom-resouces/authentik-server/authentik-server.controller.ts @@ -16,6 +16,8 @@ import { API_VERSION } from '../../utils/consts.ts'; import { getWithNamespace } from '../../utils/naming.ts'; import { decodeSecret, encodeSecret } from '../../utils/secrets.ts'; import type { environmentSpecSchema } from '../environment/environment.schemas.ts'; +import { HttpServiceInstance } from '../../instances/http-service.ts'; +import type { redisServerSpecSchema } from '../redis-server/redis-server.schemas.ts'; import { authentikServerInitSecretSchema, type authentikServerSpecSchema } from './authentik-server.schemas.ts'; @@ -25,6 +27,8 @@ class AuthentikServerController extends CustomResource; + #httpService: HttpServiceInstance; + #redisServer: ResourceReference>; constructor(options: CustomResourceOptions) { super(options); @@ -62,12 +66,24 @@ class AuthentikServerController extends CustomResource { @@ -126,6 +142,9 @@ class AuthentikServerController extends CustomResource #storageClass: StorageClassInstance; #postgresCluster: PostgresClusterInstance; #authentikServer: AuthentikServerInstance; + #redisServer: RedisServerInstance; constructor(options: CustomResourceOptions) { super(options); const resourceService = this.services.get(ResourceService); + const namespaceService = this.services.get(NamespaceService); this.#namespace = resourceService.getInstance( { apiVersion: 'v1', @@ -48,8 +52,8 @@ class EnvironmentController extends CustomResource { apiVersion: 'cert-manager.io/v1', kind: 'Certificate', - name: this.name, - namespace: this.namespace, + name: `${this.name}-tls`, + namespace: namespaceService.homelab.name, }, CertificateInstance, ); @@ -96,6 +100,15 @@ class EnvironmentController extends CustomResource }, AuthentikServerInstance, ); + this.#redisServer = resourceService.getInstance( + { + apiVersion: API_VERSION, + kind: 'RedisServer', + name: `${this.name}-redis-server`, + namespace: this.namespace, + }, + RedisServerInstance, + ); this.#gatewayCrd.on('changed', this.queueReconcile); this.#gateway.on('changed', this.queueReconcile); this.#certificateCrd.on('changed', this.queueReconcile); @@ -104,6 +117,7 @@ class EnvironmentController extends CustomResource this.#postgresCluster.on('changed', this.queueReconcile); this.#authentikServer.on('changed', this.queueReconcile); this.#storageClass.on('changed', this.queueReconcile); + this.#redisServer.on('changed', this.queueReconcile); } public reconcile = async () => { @@ -120,13 +134,10 @@ class EnvironmentController extends CustomResource }); if (this.#certificateCrd.ready) { await this.#certificate.ensure({ - metadata: { - ownerReferences: [this.ref], - }, spec: { secretName: `${this.name}-tls`, issuerRef: { - name: 'cluster-issuer', + name: this.spec.tls.issuer, kind: 'ClusterIssuer', }, dnsNames: [`*.${this.spec.domain}`], @@ -143,7 +154,7 @@ class EnvironmentController extends CustomResource }, spec: { selector: { - istio: 'gateway', + istio: 'homelab-istio-gateway', }, servers: [ { @@ -197,8 +208,15 @@ class EnvironmentController extends CustomResource environment: `${this.namespace}/${this.name}`, subdomain: 'authentik', postgresCluster: `${this.name}-postgres-cluster`, + redisServer: `${this.name}-redis-server`, }, }); + await this.#redisServer.ensure({ + metadata: { + ownerReferences: [this.ref], + }, + spec: {}, + }); } }; } diff --git a/src/custom-resouces/environment/environment.schemas.ts b/src/custom-resouces/environment/environment.schemas.ts index b885003..3eca658 100644 --- a/src/custom-resouces/environment/environment.schemas.ts +++ b/src/custom-resouces/environment/environment.schemas.ts @@ -2,6 +2,9 @@ import { z } from 'zod'; const environmentSpecSchema = z.object({ domain: z.string(), + tls: z.object({ + issuer: z.string(), + }), storage: z .object({ location: z.string().optional(), diff --git a/src/custom-resouces/http-service/http-service.controller.ts b/src/custom-resouces/http-service/http-service.controller.ts index 45a3fcd..2392eea 100644 --- a/src/custom-resouces/http-service/http-service.controller.ts +++ b/src/custom-resouces/http-service/http-service.controller.ts @@ -66,7 +66,7 @@ class HttpServiceController extends CustomResource }, spec: { hosts: [`${this.spec.subdomain}.${environment.spec?.domain}`], - gateways: [`${this.#environment.current.namespace}/gateway`], + gateways: [`${this.#environment.current.namespace}/${this.#environment.current.name}`], http: [ { route: [ diff --git a/src/custom-resouces/redis-server/redis-server.controller.ts b/src/custom-resouces/redis-server/redis-server.controller.ts new file mode 100644 index 0000000..4016213 --- /dev/null +++ b/src/custom-resouces/redis-server/redis-server.controller.ts @@ -0,0 +1,82 @@ +import { DeploymentInstance } from '../../instances/deployment.ts'; +import { ServiceInstance } from '../../instances/service.ts'; +import { CustomResource } from '../../services/custom-resources/custom-resources.custom-resource.ts'; +import type { CustomResourceOptions } from '../../services/custom-resources/custom-resources.custom-resource.ts'; +import { ResourceService } from '../../services/resources/resources.ts'; + +import type { redisServerSpecSchema } from './redis-server.schemas.ts'; + +class RedisServerController extends CustomResource { + #deployment: DeploymentInstance; + #service: ServiceInstance; + + constructor(options: CustomResourceOptions) { + super(options); + const resourceService = this.services.get(ResourceService); + this.#deployment = resourceService.getInstance( + { + apiVersion: 'apps/v1', + kind: 'Deployment', + name: this.name, + namespace: this.namespace, + }, + DeploymentInstance, + ); + this.#service = resourceService.getInstance( + { + apiVersion: 'v1', + kind: 'Service', + name: this.name, + namespace: this.namespace, + }, + ServiceInstance, + ); + this.#deployment.on('changed', this.queueReconcile); + this.#service.on('changed', this.queueReconcile); + } + + public reconcile = async () => { + await this.#deployment.ensure({ + metadata: { + ownerReferences: [this.ref], + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: this.name, + }, + }, + template: { + metadata: { + labels: { + app: this.name, + }, + }, + spec: { + containers: [ + { + name: this.name, + image: 'redis:latest', + ports: [{ containerPort: 6379 }], + }, + ], + }, + }, + }, + }); + await this.#service.ensure({ + metadata: { + ownerReferences: [this.ref], + }, + spec: { + selector: { + app: this.name, + }, + ports: [{ port: 6379, targetPort: 6379 }], + }, + }); + }; +} + +export { RedisServerController }; diff --git a/src/custom-resouces/redis-server/redis-server.schemas.ts b/src/custom-resouces/redis-server/redis-server.schemas.ts new file mode 100644 index 0000000..cbd36f2 --- /dev/null +++ b/src/custom-resouces/redis-server/redis-server.schemas.ts @@ -0,0 +1,5 @@ +import { z } from 'zod'; + +const redisServerSpecSchema = z.object({}); + +export { redisServerSpecSchema }; diff --git a/src/custom-resouces/redis-server/redis-server.ts b/src/custom-resouces/redis-server/redis-server.ts new file mode 100644 index 0000000..861c12b --- /dev/null +++ b/src/custom-resouces/redis-server/redis-server.ts @@ -0,0 +1,19 @@ +import { createCustomResourceDefinition } from '../../services/custom-resources/custom-resources.ts'; +import { GROUP } from '../../utils/consts.ts'; + +import { RedisServerController } from './redis-server.controller.ts'; +import { redisServerSpecSchema } from './redis-server.schemas.ts'; + +const redisServerDefinition = createCustomResourceDefinition({ + group: GROUP, + version: 'v1', + kind: 'RedisServer', + names: { + plural: 'redis-servers', + singular: 'redis-server', + }, + spec: redisServerSpecSchema, + create: (options) => new RedisServerController(options), +}); + +export { redisServerDefinition }; diff --git a/src/instances/http-service.ts b/src/instances/http-service.ts new file mode 100644 index 0000000..9d2cddf --- /dev/null +++ b/src/instances/http-service.ts @@ -0,0 +1,7 @@ +import type { httpServiceSpecSchema } from '../custom-resouces/http-service/http-service.schemas.ts'; +import type { CustomResourceObject } from '../services/custom-resources/custom-resources.custom-resource.ts'; +import { ResourceInstance } from '../services/resources/resources.instance.ts'; + +class HttpServiceInstance extends ResourceInstance> {} + +export { HttpServiceInstance }; diff --git a/src/instances/redis-server.ts b/src/instances/redis-server.ts new file mode 100644 index 0000000..0b94c96 --- /dev/null +++ b/src/instances/redis-server.ts @@ -0,0 +1,7 @@ +import type { CustomResourceObject } from '../services/custom-resources/custom-resources.custom-resource.ts'; +import { ResourceInstance } from '../services/resources/resources.instance.ts'; +import type { redisServerSpecSchema } from '../custom-resouces/redis-server/redis-server.schemas.ts'; + +class RedisServerInstance extends ResourceInstance> {} + +export { RedisServerInstance };