Skip to content

Commit

Permalink
Merge pull request #7 from mohemohe/lambda
Browse files Browse the repository at this point in the history
Lambdaで動かせるように変更
  • Loading branch information
naaaaaaaaaaaf authored Apr 16, 2023
2 parents ecb1402 + 0b3def6 commit e2acc04
Show file tree
Hide file tree
Showing 15 changed files with 2,106 additions and 140 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cdk
src/chainfiles
src/config.ini
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ WORKDIR /var/app
COPY src/Pipfile ./
COPY src/Pipfile.lock ./
RUN pip install pipenv
RUN pipenv install --system
RUN pipenv install --system
RUN cp /etc/mecabrc /usr/local/etc/mecabrc
23 changes: 18 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,26 @@ Mastodon上のアカウントの投稿を、マルコフ連鎖して投稿する
例: https://ap.ketsuben.red/@mecha_naf/105073696514947785

## 必要なもの
Dockerが入ったマシン(入れ方は各自調べてください)
Dockerが入ったマシン(入れ方は各自調べてください) または AWSアカウント

## 動かし方

### ローカルで動かす

1. Mastodonのアクセストークンを取得(https://example.com/settings/applications/new から取得可能)
2. `src/config.ini.sample``src/config.ini` にコピー
3. `src/config.ini` の必要項目を入力(コメントに従って書いてください。)
4. `docker-compose up -d` でDockerコンテナがビルドされ起動します。

### AWS Lambdaで動かす

## 動かし方
1. Mastodonのアクセストークンを取得(https://example.com/settings/applications/new から取得可能)
2. src/config.ini.sample を src/config.ini にコピー
3. src/config.ini の必要項目を入力(コメントに従って書いてください。)
4. docker-compose up -d でDockerコンテナがビルドされ起動します。
2. `cdk` ディレクトリに移動する
3. `npm ci` でCDKと依存ライブラリをインストールする
4. `.env.sample``.env` にコピー
5. `.env` の必要項目を入力(コメントに従って書いてください。)
6. `npm run cdk:bootstrap` を実行(使用するAWSアカウントで一度もAWS CDK v2を使ったことがない場合)
7. `npm run cdk:deploy` を実行

## おすすめ開発方法
VScodeのRemote containerから開発
19 changes: 19 additions & 0 deletions cdk/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#### 環境名の設定
# AWSアカウント内で複数のBOTを動かせるように、一意の環境名を指定する
ENV_NAME=


#### 学習元アカウントの情報

# インスタンスのドメイン(https://抜き)
DOMAIN=

# アクセストークンを入力
READ_ACCESS_TOKEN=


#### 投稿用アカウントの情報

# アクセストークンを入力
# 学習用アカウントと同じアカウントを利用したい場合は同じアクセストークンを入力(非推奨)
WRITE_ACCESS_TOKEN=
5 changes: 5 additions & 0 deletions cdk/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
cdk.out
cdk.context.json
.env.*
!.env.sample
3 changes: 3 additions & 0 deletions cdk/cdk.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"app": "npx ts-node ./deploy.ts"
}
109 changes: 109 additions & 0 deletions cdk/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import "source-map-support/register";
import path from "path";
import { GetCallerIdentityCommand, STSClient } from "@aws-sdk/client-sts";
import { aws_events, aws_events_targets, aws_iam, aws_lambda, aws_s3, App, Duration, Stack, StackProps, RemovalPolicy } from "aws-cdk-lib";
import { Construct } from "constructs";
import { Platform } from "aws-cdk-lib/aws-ecr-assets";

Error.stackTraceLimit = Infinity;

const environmetKeys = [
"ENV_NAME",
"DOMAIN",
"READ_ACCESS_TOKEN",
"WRITE_ACCESS_TOKEN",
"S3_BUCKET",
] as const;

type Env = { [key in typeof environmetKeys[number]]: string };

function parseEnv() {
const targets = [...environmetKeys];

return targets.reduce((obj, target) => {
obj[target] = process.env[target] || "";
return obj;
}, {} as Env);
}

function checkEnv(env: Env) {
const required: Partial<typeof environmetKeys> = [
"ENV_NAME",
"DOMAIN",
"READ_ACCESS_TOKEN",
"WRITE_ACCESS_TOKEN"
];
for (const key of required) {
if (key && !env[key]) {
throw new Error(`環境変数 '${key}' が設定されていません。.envファイルを確認してください。`);
}
}
}

export class NafStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps, env: Env) {
super(scope, id, props);

const isX64 = process.arch === "x64";
const lambdaArchitecture = isX64 ? aws_lambda.Architecture.X86_64 : aws_lambda.Architecture.ARM_64;
const lambdaPlatform = isX64 ? Platform.LINUX_AMD64 : Platform.LINUX_ARM64;

const role = new aws_iam.Role(this, "MarkovBotFunctionRole", {
roleName: `markovbot-${env.ENV_NAME}-function-role`,
assumedBy: new aws_iam.ServicePrincipal("lambda.amazonaws.com"),
managedPolicies: [
aws_iam.ManagedPolicy.fromAwsManagedPolicyName("CloudWatchLogsFullAccess"),
],
});

const s3 = new aws_s3.Bucket(this, "S3Bucket", {
encryption: aws_s3.BucketEncryption.S3_MANAGED,
blockPublicAccess: aws_s3.BlockPublicAccess.BLOCK_ALL,
autoDeleteObjects: true,
removalPolicy: RemovalPolicy.DESTROY,
});
env.S3_BUCKET = s3.bucketName;

const lambda = new aws_lambda.Function(this, "MarkovBotFunction", {
runtime: aws_lambda.Runtime.FROM_IMAGE,
architecture: lambdaArchitecture,
memorySize: 1536,
timeout: Duration.minutes(10),
code: aws_lambda.Code.fromAssetImage(path.resolve("../"), {
platform: lambdaPlatform,
file: "lambda.Dockerfile",
}),
handler: aws_lambda.Handler.FROM_IMAGE,
environment: env,
role,
});
s3.grantReadWrite(lambda);

const schedulerRule = new aws_events.Rule(this, "MarkovBotFunctionSchedulerEvent", {
schedule: aws_events.Schedule.cron({
minute: "0/20",
}),
});
schedulerRule.addTarget(new aws_events_targets.LambdaFunction(lambda));
}
}

(async () => {
const env = parseEnv();
checkEnv(env);

const account = await new STSClient({}).send(new GetCallerIdentityCommand({}));

const app = new App();
const stack = new NafStack(
app,
`markovbot-${env.ENV_NAME}`,
{
env: {
account: account.Account,
region: process.env.AWS_REGION || "ap-northeast-1",
},
},
env,
);
})();
Loading

0 comments on commit e2acc04

Please sign in to comment.