Skip to content

Commit

Permalink
Example of deploying a Go project to fargate.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zemnmez committed Dec 27, 2024
1 parent d39cadd commit 4e17114
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 23 deletions.
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ use_repo(
go_deps,
"co_honnef_go_tools",
"com_github_a_h_generate",
"com_github_aws_aws_lambda_go",
"com_github_bazelbuild_bazel_watcher",
"com_github_bazelbuild_buildtools",
"com_github_go_delve_delve",
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ toolchain go1.23.4

require (
github.com/a-h/generate v0.0.0-20220105161013-96c14dfdfb60
github.com/aws/aws-lambda-go v1.47.0
github.com/bazelbuild/bazel-gazelle v0.40.0
github.com/bazelbuild/bazel-watcher v0.25.3
github.com/bazelbuild/buildtools v0.0.0-20240918101019-be1c24cc9a44
Expand Down
16 changes: 2 additions & 14 deletions go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ts/pulumi/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ ts_project(
"//ts/pulumi/lulu.computer:pulumi_ts",
"//ts/pulumi/pleaseintroducemetoyour.dog:ts",
"//ts/pulumi/shadwell.im",
"//ts/pulumi/zemn.me/hello_world:ts",
],
)

Expand Down
64 changes: 57 additions & 7 deletions ts/pulumi/lib/oci/oci_image.tmpl.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,79 @@
import { createHash } from 'node:crypto';
import { writeFile } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import path, { resolve } from 'node:path';

import { local } from '@pulumi/command';
import { ComponentResource, ComponentResourceOptions, Input, output } from "@pulumi/pulumi";
import { all, ComponentResource, ComponentResourceOptions, Input, Output, output } from "@pulumi/pulumi";


export interface Args {
repository: Input<string>
token?: Input<string|undefined>
}

export async function createPodmanAuthFile(
token: string,
registry: string
): Promise<string> {
// Encode credentials

// Build the auth.json structure
const authData = {
auths: {
[`https://${registry}`]: {
auth: token
},
},
};

const fileContent = JSON.stringify(authData)

const hash = createHash('sha256').update(fileContent).digest('hex');

// Generate a temporary file path
const tempDir = tmpdir();
const randomName = `${hash}.json`;
const filePath = path.join(tempDir, randomName);

// Write the JSON data to the file
await writeFile(filePath, JSON.stringify(authData));

// Return the path to the newly created temporary file
return resolve(filePath)
}

export class __ClassName extends ComponentResource {
url: string = "TODO" // will fill once i've deployed for the first time
url: Output<string>
constructor(
name: string,
args: Args,
opts?: ComponentResourceOptions
) {
super('__TYPE', name, args, opts);

const arg = all([args.repository]).apply(([repo]) => [
"--repository", `${repo}`
])

const authFile = all([args.token, args.repository]).apply(([token, registry]) => {
if (!token || !registry) return;
return createPodmanAuthFile(registry, token)
});

const upload = new local.Command(`${name}_push`, {
create:
output(args.repository).apply(repository => [
environment: output(authFile).apply(f => ({
REGISTRY_AUTH_FILE: f
})as {[v: string]: string}),
interpreter:
arg.apply(arg => [
"__PUSH_BIN",
"--repository",
repository,
].join(" "))
...arg
])
}, { parent: this })

this.url = upload.stdout


super.registerOutputs({ upload })
}
Expand Down
2 changes: 1 addition & 1 deletion ts/pulumi/lib/oci/rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def pulumi_image(
oci_push(
name = name + "_push_bin",
image = src,
repository = "why is this mandatory",
repository = "None",
)

expand_template_rule(
Expand Down
2 changes: 1 addition & 1 deletion ts/pulumi/lib/tags.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { all, Input } from '@pulumi/pulumi';

type TagSet = Input<Record<string, Input<string>>>;
export type TagSet = Input<Record<string, Input<string>>>;

export const mergeTags = (a?: TagSet, b?: TagSet): TagSet =>
all([a, b]).apply(([a, b]) => ({ ...a, ...b }));
Expand Down
60 changes: 60 additions & 0 deletions ts/pulumi/zemn.me/hello_world/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
load("@rules_oci//oci:defs.bzl", "oci_image")
load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
load("//bzl:rules.bzl", "bazel_lint")
load("//go:rules.bzl", "go_binary", "go_library")
load("//ts:rules.bzl", "ts_project")
load("//ts/pulumi/lib/oci:rules.bzl", "pulumi_image")

go_library(
name = "hello_world_lib",
srcs = ["hello.go"],
importpath = "github.com/zemn-me/monorepo/ts/pulumi/zemn.me/hello_world",
visibility = ["//visibility:private"],
deps = ["@com_github_aws_aws_lambda_go//lambda"],
)

go_binary(
name = "hello_world",
embed = [":hello_world_lib"],
visibility = ["//visibility:public"],
)

bazel_lint(
name = "bazel_lint",
srcs = ["BUILD.bazel"],
)

pkg_tar(
name = "tar",
srcs = [":hello_world"],
)

oci_image(
name = "image",
base = "@distroless_base",
entrypoint = ["/hello_world"],
tars = [":tar"],
)

pulumi_image(
name = "oci_image",
src = ":image",
component_name = "HelloWorldImage",
)

ts_project(
name = "ts",
srcs = [
"hello_world.ts",
],
visibility = [
"//ts/pulumi:__subpackages__",
],
deps = [
":oci_image",
"//:node_modules/@pulumi/aws",
"//:node_modules/@pulumi/awsx",
"//:node_modules/@pulumi/pulumi",
"//ts/pulumi/lib",
],
)
17 changes: 17 additions & 0 deletions ts/pulumi/zemn.me/hello_world/hello.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"context"

"github.com/aws/aws-lambda-go/lambda"
)

// Handler is the Lambda function entry point
func Handler(ctx context.Context) (string, error) {
return "Hello, World!", nil
}

func main() {
// Start the Lambda function
lambda.Start(Handler)
}
61 changes: 61 additions & 0 deletions ts/pulumi/zemn.me/hello_world/hello_world.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as aws from "@pulumi/aws";
import { ComponentResource, ComponentResourceOptions } from "@pulumi/pulumi";

import { mergeTags, TagSet, tagTrue } from "#root/ts/pulumi/lib/tags.js";
import { HelloWorldImage } from "#root/ts/pulumi/zemn.me/hello_world/HelloWorldImage.js";

export interface Args {
tags?: TagSet;
}

export class LambdaHelloWorld extends ComponentResource {
constructor(
name: string,
args: Args,
opts?: ComponentResourceOptions
) {
super("ts:pulumi:Component", name, args, opts);

const tag = name;
const tags = mergeTags(args.tags, tagTrue(tag));

// Create the ECR repository to store our container image
const repo = new aws.ecr.Repository("repo", {
forceDelete: true,
tags: tags,
});

const auth = aws.ecr.getAuthorizationToken();

// Build and push the container image
const img = new HelloWorldImage(`${name}_img`, {
repository: repo.repositoryUrl,
token: auth.then(auth => auth.authorizationToken)
});

// Create the Lambda function using the container image
const lambda = new aws.lambda.Function(`${name}_lambda`, {
packageType: "Image",
imageUri: img.url,
role: new aws.iam.Role("lambdaRole", {
assumeRolePolicy: aws.iam.assumeRolePolicyForPrincipal({
Service: "lambda.amazonaws.com",
}),
}).arn,
timeout: 30,
memorySize: 512,
tags: tags,
});

// Add permissions for Lambda to log to CloudWatch
new aws.iam.RolePolicyAttachment(`${name}_lambda_logging`, {
role: lambda.role!,
policyArn: aws.iam.ManagedPolicy.AWSLambdaBasicExecutionRole,
});

// Export the Lambda function name
this.registerOutputs({
lambdaFunctionName: lambda.name,
});
}
}
5 changes: 5 additions & 0 deletions ts/pulumi/zemn.me/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { bskyDid } from '#root/project/zemn.me/bio/bio.js';
import { BlueskyDisplayNameClaim } from '#root/ts/pulumi/lib/bluesky_username_claim.js';
import { mergeTags, tagTrue } from '#root/ts/pulumi/lib/tags.js';
import Website from '#root/ts/pulumi/lib/website.js';
import { LambdaHelloWorld } from '#root/ts/pulumi/zemn.me/hello_world/hello_world.js';

export interface Args {
zoneId: Pulumi.Input<string>;
Expand Down Expand Up @@ -33,6 +34,10 @@ export class Component extends Pulumi.ComponentResource {
{ parent: this }
);

new LambdaHelloWorld(`${name}_fargate`, {
tags: args.tags
});

this.site = new Website(
`${name}_zemn_me`,
{
Expand Down

0 comments on commit 4e17114

Please sign in to comment.