diff --git a/ts/BUILD b/ts/BUILD index a851c17b6a..e243b8017e 100644 --- a/ts/BUILD +++ b/ts/BUILD @@ -4,8 +4,4 @@ package(default_visibility = ["//:__subpackages__"]) ts_project( name = "ts", - srcs = glob( - include = ["*.ts"], - exclude = ["*_test.ts"], - ), ) diff --git a/ts/fs/BUILD b/ts/fs/BUILD new file mode 100644 index 0000000000..7fb550c5f9 --- /dev/null +++ b/ts/fs/BUILD @@ -0,0 +1,8 @@ +load("//ts:rules.bzl", "ts_project") + +package(default_visibility = ["//:__subpackages__"]) + +ts_project( + name = "fs", + deps = ["@npm//@types/node"], +) diff --git a/ts/fs/index.ts b/ts/fs/index.ts new file mode 100644 index 0000000000..5428b4205f --- /dev/null +++ b/ts/fs/index.ts @@ -0,0 +1,9 @@ +import { Dirent } from 'fs'; +import { readdir } from 'fs/promises'; + +export async function* walk(path: string): AsyncGenerator { + for (const entity of await readdir(path, { withFileTypes: true })) { + if (entity.isDirectory()) yield* walk(entity.name); + yield entity; + } +} diff --git a/ts/pulumi/BUILD b/ts/pulumi/BUILD index f08fa275d2..7a3bc2ec2b 100644 --- a/ts/pulumi/BUILD +++ b/ts/pulumi/BUILD @@ -1,4 +1,4 @@ -load("//ts:rules.bzl", "nodejs_binary", "ts_project") +load("//ts:rules.bzl", "jest_test", "nodejs_binary", "ts_project") load("@bazel_skylib//rules:native_binary.bzl", "native_test") package(default_visibility = ["//deploy:__subpackages__"]) @@ -16,26 +16,18 @@ ts_project( deps = [ "//ts/pulumi/dog", "//ts/pulumi/im", + "//ts/pulumi/im/shadwell/thomas", "//ts/pulumi/me", "@npm//@types/cross-spawn", + "@npm//@types/jest", "@npm//cross-spawn", ], ) -nodejs_binary( - name = "configs", - data = [ - ":pulumi", - ":pulumi_files", - ], - entry_point = "test.js", -) - -native_test( - name = "configs_test", - src = ":configs.sh", - out = "whatever", - data = [":configs"], +jest_test( + name = "tests", + srcs = ["pulumi_test.js"], + deps = [":pulumi"], ) nodejs_binary( diff --git a/ts/pulumi/dog/pleaseintroducemetoyour/index.ts b/ts/pulumi/dog/pleaseintroducemetoyour/index.ts index 90561fbd84..fffc1bd836 100644 --- a/ts/pulumi/dog/pleaseintroducemetoyour/index.ts +++ b/ts/pulumi/dog/pleaseintroducemetoyour/index.ts @@ -1,5 +1,5 @@ -export * from './A'; -export * from './cert'; -export * from './cloudfront'; -export * from './zone'; +export * from 'monorepo/ts/pulumi/dog/pleaseintroducemetoyour/A'; +export * from 'monorepo/ts/pulumi/dog/pleaseintroducemetoyour/cert'; +export * from 'monorepo/ts/pulumi/dog/pleaseintroducemetoyour/cloudfront'; export * as Public from 'monorepo/ts/pulumi/dog/pleaseintroducemetoyour/public'; +export * from 'monorepo/ts/pulumi/dog/pleaseintroducemetoyour/zone'; diff --git a/ts/pulumi/dog/pleaseintroducemetoyour/public/BUILD b/ts/pulumi/dog/pleaseintroducemetoyour/public/BUILD index 6fb71b93c3..1a05b7c16d 100644 --- a/ts/pulumi/dog/pleaseintroducemetoyour/public/BUILD +++ b/ts/pulumi/dog/pleaseintroducemetoyour/public/BUILD @@ -6,6 +6,8 @@ ts_project( name = "public", data = ["//ts/pulumi/dog/pleaseintroducemetoyour/public/static"], deps = [ + "//ts/fs", + "//ts/pulumi/lib", "@npm//@bazel/runfiles", "@npm//@pulumi/aws", "@npm//@pulumi/pulumi", diff --git a/ts/pulumi/dog/pleaseintroducemetoyour/public/index.ts b/ts/pulumi/dog/pleaseintroducemetoyour/public/index.ts index ca8d11aea7..207a43f3bc 100644 --- a/ts/pulumi/dog/pleaseintroducemetoyour/public/index.ts +++ b/ts/pulumi/dog/pleaseintroducemetoyour/public/index.ts @@ -1,42 +1,55 @@ import { runfiles } from '@bazel/runfiles'; import * as aws from '@pulumi/aws'; -import * as pulumi from '@pulumi/pulumi'; -import glob from 'glob-promise'; import mime from 'mime'; +import { walk } from 'monorepo/ts/fs'; +import { fileAsset } from 'monorepo/ts/pulumi/lib'; import path from 'path'; -const basePath = 'ts/pulumi/dog/pleaseintroducemetoyour/public/static/out'; +const basePath = runfiles.resolveWorkspaceRelative( + 'ts/pulumi/dog/pleaseintroducemetoyour/public/static/out' +); -const file = - (bucket: aws.s3.BucketObjectArgs['bucket']) => (relativePath: string) => { - const workspacePath = path.posix.join(basePath, relativePath); - const absolutePath = runfiles.resolveWorkspaceRelative(workspacePath); - return new aws.s3.BucketObject(workspacePath, { - key: workspacePath, - bucket, - contentType: mime.getType(absolutePath) || undefined, - source: new pulumi.asset.FileAsset(absolutePath), - acl: 'public-read', - }); - }; +function trimPrefix(prefix: string, haystack: string): string { + if (!haystack.startsWith(prefix)) + throw new Error( + `Can't trim prefix; ${haystack} doesn't start with ${prefix}` + ); + + return haystack.slice(prefix.length); +} + +export const indexPage = fileAsset(path.join(basePath, 'index.html')); +export const errorPage = fileAsset(path.join(basePath, '404.html')); + +export const files = (async function* () { + for await (const entity of walk(basePath)) { + if (!entity.isFile()) continue; + yield fileAsset(entity.name); + } +})(); export const bucket = new aws.s3.Bucket('pleaseintroducemetoyour.dog', { acl: 'public-read', website: { - indexDocument: 'index.html', + indexDocument: indexPage.then(async asset => + trimPrefix(basePath, await asset.path) + ), + errorDocument: errorPage.then(async asset => + trimPrefix(basePath, await asset.path) + ), }, }); -const File = file(bucket); - -async function Files() { - const ret = []; - for (const file of await glob(basePath + '/*')) { - ret.push(File(file)); +export const bucketObjects = (async function* () { + for await (const file of files) { + yield new aws.s3.BucketObject(await file.path, { + key: trimPrefix(basePath, await file.path), + bucket, + contentType: mime.getType(await file.path) ?? undefined, + source: file, + acl: 'public-read', + }); } - return ret; -} - -export const files = Files(); +})(); export default bucket; diff --git a/ts/pulumi/dog/pleaseintroducemetoyour/public/static/BUILD b/ts/pulumi/dog/pleaseintroducemetoyour/public/static/BUILD index fc94d86722..5ff3529841 100644 --- a/ts/pulumi/dog/pleaseintroducemetoyour/public/static/BUILD +++ b/ts/pulumi/dog/pleaseintroducemetoyour/public/static/BUILD @@ -6,6 +6,7 @@ package(default_visibility = ["//ts/pulumi/dog/pleaseintroducemetoyour/public:__ ts_project( name = "ts", deps = [ + "@npm//@bazel/runfiles", "@npm//@types/react", "@npm//next", "@npm//react", diff --git a/ts/pulumi/im/shadwell/thomas/BUILD b/ts/pulumi/im/shadwell/thomas/BUILD index 989345349d..9bd9697057 100644 --- a/ts/pulumi/im/shadwell/thomas/BUILD +++ b/ts/pulumi/im/shadwell/thomas/BUILD @@ -1,6 +1,7 @@ load("//ts:rules.bzl", "ts_project") -package(default_visibility = ["//ts/pulumi/im/shadwell:__pkg__"]) +#package(default_visibility = ["//ts/pulumi/im/shadwell:__pkg__"]) +package(default_visibility = ["//visibility:public"]) ts_project( name = "thomas", diff --git a/ts/pulumi/im/shadwell/thomas/public/BUILD b/ts/pulumi/im/shadwell/thomas/public/BUILD index 9e86b4691a..62c8fb7c38 100644 --- a/ts/pulumi/im/shadwell/thomas/public/BUILD +++ b/ts/pulumi/im/shadwell/thomas/public/BUILD @@ -6,6 +6,7 @@ ts_project( name = "public", data = ["index.html"], deps = [ + "//ts/pulumi/lib", "@npm//@bazel/runfiles", "@npm//@pulumi/aws", "@npm//@pulumi/pulumi", diff --git a/ts/pulumi/im/shadwell/thomas/public/index.ts b/ts/pulumi/im/shadwell/thomas/public/index.ts index 5177b024f1..d08c09a0cb 100644 --- a/ts/pulumi/im/shadwell/thomas/public/index.ts +++ b/ts/pulumi/im/shadwell/thomas/public/index.ts @@ -1,7 +1,7 @@ import { runfiles } from '@bazel/runfiles'; import * as aws from '@pulumi/aws'; -import * as pulumi from '@pulumi/pulumi'; import mime from 'mime'; +import { fileAsset } from 'monorepo/ts/pulumi/lib'; import path from 'path'; const basePath = 'ts/pulumi/im/shadwell/thomas/public'; @@ -14,7 +14,7 @@ const file = key: workspacePath, bucket, contentType: mime.getType(absolutePath) || undefined, - source: new pulumi.asset.FileAsset(absolutePath), + source: fileAsset(absolutePath), acl: 'public-read', }); }; diff --git a/ts/pulumi/lib/BUILD b/ts/pulumi/lib/BUILD new file mode 100644 index 0000000000..efeae30463 --- /dev/null +++ b/ts/pulumi/lib/BUILD @@ -0,0 +1,11 @@ +load("//ts:rules.bzl", "ts_project") + +package(default_visibility = ["//visibility:public"]) + +ts_project( + name = "lib", + deps = [ + "@npm//@pulumi/pulumi", + "@npm//@types/node", + ], +) diff --git a/ts/pulumi/lib/index.ts b/ts/pulumi/lib/index.ts new file mode 100644 index 0000000000..a1ec0b68d4 --- /dev/null +++ b/ts/pulumi/lib/index.ts @@ -0,0 +1,8 @@ +import * as fs from 'node:fs/promises'; + +import * as pulumi from '@pulumi/pulumi'; + +export async function fileAsset(file: string | Promise) { + await fs.access(await file); + return new pulumi.asset.FileAsset(await file); +} diff --git a/ts/pulumi/me/zemn/BUILD b/ts/pulumi/me/zemn/BUILD index 074845536f..f8551373b2 100644 --- a/ts/pulumi/me/zemn/BUILD +++ b/ts/pulumi/me/zemn/BUILD @@ -5,7 +5,6 @@ package(default_visibility = ["//ts/pulumi/me:__pkg__"]) ts_project( name = "zemn", deps = [ - "//ts/pulumi/me/zemn/factorio", "//ts/pulumi/me/zemn/zone", "@npm//@pulumi/aws", "@npm//@pulumi/pulumi", diff --git a/ts/pulumi/me/zemn/factorio/BUILD b/ts/pulumi/me/zemn/factorio/BUILD deleted file mode 100644 index 79e82f7a04..0000000000 --- a/ts/pulumi/me/zemn/factorio/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -load("//ts:rules.bzl", "ts_project") - -package(default_visibility = ["//ts/pulumi/me/zemn:__pkg__"]) - -ts_project( - name = "factorio", - data = [ - "map.zip", - "startupScript.sh", - ], - deps = [ - "//ts/pulumi/me/zemn/zone", - "@npm//@pulumi/aws", - "@npm//@pulumi/pulumi", - ], -) diff --git a/ts/pulumi/me/zemn/factorio/config.json b/ts/pulumi/me/zemn/factorio/config.json deleted file mode 100644 index de01a83f8c..0000000000 --- a/ts/pulumi/me/zemn/factorio/config.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "factorio.zemn.me", - "tags": ["game", "tags"], - - "_comment_max_players": "Maximum number of players allowed, admins can join even a full server. 0 means unlimited.", - "max_players": 0, - - "_comment_visibility": ["public: Game will be published on the official Factorio matching server", - "lan: Game will be broadcast on LAN"], - "visibility": - { - "public": false, - "lan": false - }, - - "_game_password_comment": "inject this somehow", - - "game_password": "", - - "_comment_require_user_verification": "When set to true, the server will only allow clients that have a valid Factorio.com account", - "require_user_verification": true, - - "_comment_max_upload_in_kilobytes_per_second" : "optional, default value is 0. 0 means unlimited.", - "max_upload_in_kilobytes_per_second": 0, - - "_comment_max_upload_slots" : "optional, default value is 5. 0 means unlimited.", - "max_upload_slots": 5, - - "_comment_minimum_latency_in_ticks": "optional one tick is 16ms in default speed, default value is 0. 0 means no minimum.", - "minimum_latency_in_ticks": 0, - - "_comment_ignore_player_limit_for_returning_players": "Players that played on this map already can join even when the max player limit was reached.", - "ignore_player_limit_for_returning_players": false, - - "_comment_allow_commands": "possible values are, true, false and admins-only", - "allow_commands": "admins-only", - - "_comment_autosave_interval": "Autosave interval in minutes", - "autosave_interval": 10, - - "_comment_autosave_slots": "server autosave slots, it is cycled through when the server autosaves.", - "autosave_slots": 10, - - "_comment_afk_autokick_interval": "How many minutes until someone is kicked when doing nothing, 0 for never.", - "afk_autokick_interval": 0, - - "_comment_auto_pause": "Whether should the server be paused when no players are present.", - "auto_pause": true, - - "only_admins_can_pause_the_game": true, - - "_comment_autosave_only_on_server": "Whether autosaves should be saved only on server or also on all connected clients. Default is true.", - "autosave_only_on_server": true, - - "_comment_non_blocking_saving": "Highly experimental feature, enable only at your own risk of losing your saves. On UNIX systems, server will fork itself to create an autosave. Autosaving on connected Will", - "non_blocking_saving": false, - - "_comment_segment_sizes": "Long network messages are split into segments that are sent over multiple ticks. Their size depends on the number of peers currently connected. Increasing the segment size will...", - "minimum_segment_size": 25, - "minimum_segment_size_peer_count": 20, - "maximum_segment_size": 100, - "maximum_segment_size_peer_count": 10 -} \ No newline at end of file diff --git a/ts/pulumi/me/zemn/factorio/index.ts b/ts/pulumi/me/zemn/factorio/index.ts deleted file mode 100644 index 5b14bcc1dc..0000000000 --- a/ts/pulumi/me/zemn/factorio/index.ts +++ /dev/null @@ -1,108 +0,0 @@ -import * as aws from '@pulumi/aws'; -import * as pulumi from '@pulumi/pulumi'; -import fs from 'fs/promises'; -import { zone } from 'monorepo/ts/pulumi/me/zemn/zone'; - -//import * as command from '@pulumi/command'; - -export const ami = aws.ec2.getAmi({ - mostRecent: true, - // magic number from https://ubuntu.com/server/docs/cloud-images/amazon-ec2 - owners: ['099720109477'], - filters: [ - { - name: 'architecture', - values: ['x86_64'], - }, - { - name: 'description', - values: ['*LTS*'], - }, - { - name: 'name', - values: ['ubuntu/images/ubuntu-*-*-amd64-server-*'], - }, - { - name: 'virtualization-type', - values: ['hvm'], - }, - ], -}); - -const factorioPorts = [ - { - protocol: 'udp', - fromPort: 34197, - toPort: 34197, - cidrBlocks: ['0.0.0.0/0'], - }, - { - protocol: 'tcp', - fromPort: 27015, - toPort: 27015, - cidrBlocks: ['0.0.0.0/0'], - }, -]; - -export const securityGroup = new aws.ec2.SecurityGroup( - 'factorio-server-security-group', - { - ingress: [...factorioPorts], - } -); - -export const startupScript = new pulumi.asset.FileAsset( - 'ts/pulumi/me/zemn/factorio/startupScript.sh' -); -export const defaultSaveFile = new pulumi.asset.FileAsset( - 'ts/pulumi/me/zemn/factorio/map.zip' -); - -export const factorioData = new aws.ebs.Volume('factorio-server-data', { - availabilityZone: 'us-east-1a', - size: 2, -}); - -export const ec2 = new aws.ec2.Instance('factorio-server', { - ami: ami.then(ami => ami.id), - // should be burstable https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances.html - instanceType: 't3.medium', - tags: { - CreatedBy: 'monorepo / pulumi', - Game: 'Factorio', - }, - vpcSecurityGroupIds: [securityGroup.id], - userData: startupScript.path.then(async path => - (await fs.readFile(path)).toString('utf-8') - ), -}); - -export const factorioDataMount = new aws.ec2.VolumeAttachment( - 'factorio-server-data-mount', - { - deviceName: '/dev/sdh', - volumeId: factorioData.id, - instanceId: ec2.id, - } -); - -export const cname: aws.route53.Record = new aws.route53.Record( - 'cname_factorio.zemn.me', - { - name: pulumi.interpolate`factorio.${zone.name}`, - zoneId: zone.zoneId, - type: 'CNAME', - records: [ec2.publicDns], - } -); - -/* -Could try copying the save file over from s3 or something with this. -export const fileCopy = new command.remote.CopyFile("factorio-save-file", { - localPath: defaultSaveFile.path, - remotePath: '/opt/factorio/saves', - connection: { - host: ec2.publicDns, - } -}) -*/ diff --git a/ts/pulumi/me/zemn/factorio/map.zip b/ts/pulumi/me/zemn/factorio/map.zip deleted file mode 100644 index b8619f040a..0000000000 Binary files a/ts/pulumi/me/zemn/factorio/map.zip and /dev/null differ diff --git a/ts/pulumi/me/zemn/factorio/startupScript.sh b/ts/pulumi/me/zemn/factorio/startupScript.sh deleted file mode 100644 index a5980c6840..0000000000 --- a/ts/pulumi/me/zemn/factorio/startupScript.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash - -# See https://hub.docker.com/r/factoriotools/factorio/ - -set -e - -function apt { - DEBIAN_FRONTEND=noninteractive sudo apt -yqq $@ -} - -echo Installing docker server... -apt update -apt install docker - -# mount the ebs volume in opt -sudo ln -s /dev/sdh /opt/factorio -sudo chown 845:845 /opt/factorio - -sudo docker pull factoriotools/factorio - -sudo docker run -d \ - -p 34197:34197/udp \ - -p 27015:27015/tcp \ - -v /opt/factorio:/factorio \ - --name factorio \ - --restart=always \ - factoriotools/factorio - diff --git a/ts/pulumi/me/zemn/index.ts b/ts/pulumi/me/zemn/index.ts index 6f4de6f460..1b4062e0a1 100644 --- a/ts/pulumi/me/zemn/index.ts +++ b/ts/pulumi/me/zemn/index.ts @@ -1,2 +1 @@ -export * as factorio from 'monorepo/ts/pulumi/me/zemn/factorio'; export * as zone from 'monorepo/ts/pulumi/me/zemn/zone'; diff --git a/ts/pulumi/pulumi_test.ts b/ts/pulumi/pulumi_test.ts new file mode 100644 index 0000000000..26ec223fd1 --- /dev/null +++ b/ts/pulumi/pulumi_test.ts @@ -0,0 +1,10 @@ +import '@pulumi/pulumi'; +import 'monorepo/ts/pulumi/setMocks'; + +import * as tree from 'monorepo/ts/pulumi'; + +describe('pulumi', () => { + test('smoke', async () => { + expect(await tree).toBeDefined(); + }); +}); diff --git a/ts/pulumi/test.ts b/ts/pulumi/setMocks.ts similarity index 93% rename from ts/pulumi/test.ts rename to ts/pulumi/setMocks.ts index 36db9badb4..316951bc88 100644 --- a/ts/pulumi/test.ts +++ b/ts/pulumi/setMocks.ts @@ -4,7 +4,7 @@ pulumi.runtime.setMocks({ // Mock requests to provision cloud resources and return a canned response. newResource: ( args: pulumi.runtime.MockResourceArgs - ): { id: string; state: any } => + ): { id: string; state: { inputs: unknown } } => // Here, we're returning a same-shaped object for all resource types. // We could, however, use the arguments passed into this function to // customize the mocked-out properties of a particular resource based @@ -14,6 +14,7 @@ pulumi.runtime.setMocks({ id: `${args.name}-id`, state: args.inputs, }), + // Mock function calls and return whatever input properties were provided. call: (args: pulumi.runtime.MockCallArgs) => args.inputs, }); diff --git a/ts/typeutil/index.ts b/ts/typeutil/index.ts deleted file mode 100644 index 26cf14f540..0000000000 --- a/ts/typeutil/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export type Upgrade = Omit & T2; - -export const assertInvalidNever: (what: string) => (v: never) => void = - what => - (v: never): asserts v is never => { - throw InvalidNever(v); - }; - -export const InvalidNever = (what: string) => (v: never) => - new Error(`Invalid ${what} ${v}`); - -export type ElementProperties = - JSX.IntrinsicElements[T];