RailsとJavaScriptを同時に扱っていると*1、snake_caseからCamelCaseに置換したい時がしばしば訪れます。 一つずつ修正した方が、人間の温かみを感じることができるコードになると思うのですが、置換の方法も知った方が良いと思ったので、メモとして残しておきます。
:s/_\(.\)/\u\1/g
*1:Style Guideで記法が異なる言語を同時に扱っている場合
ReactNativeを使い始めたものの、基本的に参考になる記事が少なくて詰みかけてしまったり、英語の記事がメイン(これはまだ良いけど)であったり、参考書が少ないので、初心者にはだいぶハードルが高いなぁと感じていました。 写真者同士で助け合ったり、気軽に質問できる場があったら良いなぁ〜と思い、よちよちReactNativeを開催することにしました!
参加予定者が6名だったので結構集まった感あったのですが、土曜日の10時スタートというストイックな時間設定にしてしまったので、自分含めて4名での開催となりました!もくもく会は遊びじゃねぇんだよ!
イベント開催(connpassで人集め ~ 会場作り ~ 当日のアレコレ)が初めてだったので、良い体験になりました。 また、もくもく会にしたので、運営の手間とか難しさがほぼなく、ワンオペでもなんとかなることがわかりました!(寝坊で爆死しない限りなんとかなる!)
参加者のみなさんは、プログラムを書きながら実況もする訓練されたエンジニアが多かったので、Twitterを追ったりするのも楽しかったです。
継続的に改善していくために、KPT(K: 良かったこと/続けていきたいこと、P: 改善点、T: 次に取り組むこと)で振り返りをしていきます!
小規模だし、運営者として何をしたってわけではないのですが、人を集めてイベント開催することの楽しさがわかりました! 発表するようになったり、イベントで飲食したりするようになると、もっと楽しくなるんだろうなぁ〜と思いました!
React Nativeによるアプリ開発では、Expoを使うと中々捗るのですが、*1
2018年11月3日にExpo SDKがv31.0.0にバージョンアップしました。
blog.expo.io
このリリースの大きなポイントとしては、2018年9月にリリースされたReact Native 0.57に対応したことです。 React Nativeはバージョン0.57でTypeScriptをサポートしました。 そのため、Expoを使ってもTypeScriptでの開発ができるようになります。
今回はExpo + React Native環境をTypeScript化するための手順をまとめます。
$ expo init typescript-project $ cd typescript-project
TypeScriptを使用するのでbabelは削除します。
$ rm babel.config.js $ yarn remove babel-preset-expo
続いて、TypeScript関連のモジュールをインストールします。
yarn add typescript tslint @types/expo @types/react @types/react-native yarn add -D tslint
{ "compilerOptions": { "target": "es5", "lib": ["es2015", "esnext.asynciterable"], "jsx": "react-native", "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "types": [] } "include": [ "./App.tsx" ], "exclude": [ "node_modules" ] }
{ "extends": [ "tslint:recommended" ], "rules": { "no-any": true, "prefer-array-literal": [true, { "allow-type-parameters": true }], "variable-name": [true, "ban-keywords", "check-format", "allow-pascal-case", "allow-leading-underscore"] } }
以上でインストールと設定は終わりです
単純に拡張子を.tsxにするだけでTypeScript化ができます。簡単ですね。
jsxを含まない場合は、.tsとします。
$ mv App.js App.tsx
App.jsをApp.tsxにTypeScript化したので、わざとコンパイルエラーとなるような修正を入れて、tslintやtscで怒られてみましょう。
App.tsxを開き、下記のコードを追加します。
...省略 const a: number = 1; const b: string = a ...省略
定数bへの代入している行ではセミコロンが抜けているため、tslintで怒られるはずです。 文字列型の定数bに数値型の定数aを代入しようとしているため、コンパイルエラーになるはずです。
$ yarn tslint App.tsx ERROR: App.tsx[5, 20]: Missing semicolon
予想通りの結果です!
$ yarn tsc -p ./ --noEmitOnError App.tsx:5:7 - error TS2322: Type 'number' is not assignable to type 'string'. 5 const b: string = a ~ App.tsx:5:7 - error TS6133: 'b' is declared but its value is never read. 5 const b: string = a ~ Found 2 errors. error Command failed with exit code 1.
こちらは、型が異なるも代入でfailしていることに加え、定数bを使用していないこともわかりました。 *2
最後にApp.tsxがこれまで通り動作するかを確認します。
$ yarn start
問題なく動作しましたね!
今回はExpo + React Nativeの環境にTypeSCriptを導入する手順について書きました。 これまで通り(?)TypeScriptのinstallと設定を書き、.jsを.tsxに変更するだけでTypeScriptの恩恵を受けることができました。
TypeScriptの導入とは話が別ですが、Expo SDKがReact Nativeを追従する速さには驚きですね。 9月のリリースに対して11月に対応するのは素晴らしいです。 React Natibe のブログやExpoのブログは要チェックですね。
Goでスクリプトを書いていると、巨大なmain関数ができてしまったり、1つのファイルに色々な関数がごちゃまぜになることはよくあります。 そこで、今回はGo言語のパッケージを作る方法について紹介します。
下記のスクリプトをパッケージ化していくことを想定して説明します。
package main import "fmt" func foo(num int) int{ return num * num } func main(){ fmt.Println(foo(5)) }
main関数からfoo関数を呼んでいます。
foo関数は引数でint型を受け取り、引数を引数で除算した値を戻り値とします。
まず、パッケージ化するために新たにフォルダを作成します。
mkdir sample
作成したフォルダにfoo.go
を配置します。
この時点でのフォルダ構成は下記の通りです。
. ├── main.go └── sample └── foo.go
配置したfoo.goの内容は下記の通りです。
package sample // 1 func Foo(num int) int{ // 2 return num * num }
パッケージ化するには、パッケージ化対象のファイルの先頭にpackage {パッケージ名}
とします。
今回は、sampleフォルダを作っているので、パッケージ名をsampleにします。
また、関数名は大文字から始めます。
これはGo言語の仕様で、名前の先頭一文字が大文字になっていれば、パッケージの利用者側から参照可能となるためです。
main関数は下記の通りに修正します。
package main import ( "fmt" "./sample" // 1 ) func main(){ fmt.Println(sample.Foo(5)) // 2 }
sampleパッケージを作成したので、それを参照しなければなりません。
パッケージの参照はimport文の中で指定します。参照先は相対パスになります。
最後に、foo.goで定義した関数を呼び出します。
呼び出し方はパッケージ名.関数名
となります。今回だとsample.Foo(5)
です。
今回はGo言語のパッケージについて紹介しました。
Go言語のパッケージ化は下記を行うだけです。
package名.関数名
で呼び出すパッケージ化することにより、あるまとまった機能単位に分割ができます。
何も考えずに書いてしまうと、ついmain関数が肥大化してしまうので注意が必要です。
TreasureDataを運用していて、存在するDBとその中のテーブルのスキーマを一覧で取得したいことがあったので調べて見ました。 GUI上からDBとテーブルを一つずつ確認するのはさすがにツラいのでサクッと見れる方法はこちらです。
td db:list -f tsv | awk '{ print ""$1""}' | grep -v Name | awk '{ print "echo \""$1"\" ;td db:show "$1" -f tsv; echo \"\\n\""; }'|sh
やっていることはとても簡単で、td db:list
でDBのリストを出力し、そのDBリストを元にtd db:show
でスキーマを確認
といったことをやっています。
以前の記事でLocalStackをインストールしました。 今回はLocalStackを使用してGoで書いたLambdaからDynamoDBを呼び出す方法を紹介します。
LocalStackはAWSのマネジメントコンソールと違い、各サービスに対しての操作はCLIから行います。 まずは、DynamoDBに対してテーブルとデータを登録します。
LocalStackを立ち上げた直後はテーブルが存在しません。
$ aws --endpoint-url=http://localhost:4569 dynamodb list-tables { "TableNames": [] }
テーブル生成コマンドは下記の通りです。 このコマンドでは、「Nameという文字列のカラムがキー」である「testテーブル」を作成しています。
aws --endpoint-url=http://localhost:4569 dynamodb create-table \ --table-name test \ --attribute-definitions AttributeName=Name,AttributeType=S \ --key-schema AttributeName=Name,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=1,WriteCapacityUnits=1
次にデータを1つ登録します。
aws --endpoint-url=http://localhost:4569 dynamodb put-item \ --table-name test \ --item '{ "Name": { "S": "testtest" } }'
最後に、登録したデータが取得できるかを確認します。
aws --endpoint-url=http://localhost:4569 dynamodb scan --table-name test
続いて、DynamoDBに登録したデータを呼び出すLambdaの処理を書きます。 今回はGo言語で書きます。
環境構築はbrewで済ませることができます。
brew install go
続いて、Lambda関数で使用するパッケージをインストールしていきます。
go get -u github.com/aws/aws-sdk-go/aws \ github.com/aws/aws-sdk-go/aws/session \ github.com/aws/aws-sdk-go/aws/credentials \ github.com/aws/aws-lambda-go/lambda \ github.com/guregu/dynamo
DynamoDBへの操作はSDKをそのまま使う操作がだいぶ辛いです。
そこで、DynamoDBへの操作を容易に行えるgithub.com/guregu/dynamo
を使います。
具体的にどれだけ楽になるかを同じデータ更新処理で比較してみます。
SDKの場合
param := &dynamodb.UpdateItemInput{ TableName: aws.String("TableName"), Key: map[string]*dynamodb.AttributeValue{ "id": { N: aws.String("123"), }, }, ExpressionAttributeNames: map[string]*string{ "#username": aws.String("username"), }, ExpressionAttributeValues: map[string]*dynamodb.AttributeValue{ ":username_value": { S: aws.String("hoge"), }, }, UpdateExpression: aws.String("set #username = :username_value"), ReturnConsumedCapacity: aws.String("NONE"), ReturnItemCollectionMetrics: aws.String("NONE"), ReturnValues: aws.String("NONE"), } resp, err := ddb.UpdateItem(param)
guregu/dynamoの場合
type User struct { id int `dynamo:"id"` username string } db := dynamo.New(session.New(), &aws.Config{ Region: aws.String("us-east-1"), }) table := db.Table("TableName") user := User{id: 123, username: "hoge"} err := table.Put(user).Run()
guregu/dynamo
を使用した方が簡潔に書けますね!
先述のguregu/dynamo
を使ってDynamoDBに接続する処理を書きます。
ポイントは、エンドポイントをLocalStackのエンドポイントに変更することです。
package main import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-lambda-go/lambda" "github.com/guregu/dynamo" ) type Event struct { Name string `json:"name"` } type Response struct { Result string `json:"Name:"` } type Test struct { Name string `dynamo:"Name"` } func handler(event Event) (Response, error) { conf := &aws.Config{ Credentials: credentials.NewStaticCredentials("dumy", "dumy", ""), Region: "us-east-1", Endpoint: "http://localhost:4569", } sess, err := session.NewSession(conf) db := dynamo.New(sess) table := db.Table("test") var result Test err = table.Get("Name", "testtest").One(&result) println(result.Name) return Response{Result: result.Name}, err } func main(){ //handler(Event{Name: "testtest"}) lambda.Start(handler) }
スクリプトを書いたあとは、デプロイパッケージの作成をしてLambdaにデプロイします。
macOSを使用している場合は、ハンドラ関数がLambda実行コンテキストと互換性を持たせなければなりません。そのため、コンパイルするときにLinux用のGOOS*1環境変数を設定する必要があります。
GOOS=linux GOARCH=amd64 go build -o handler zip handler.zip ./handler
Lambdaへのデプロイは下記コマンドです。
# 新規作成(コンテナ立ち上げ直後) aws lambda create-function \ --endpoint-url http://localhost:4574 \ --region us-east-1 \ --profile localstack \ --function-name handler \ --runtime go1.x \ --role r1 \ --handler handler \ --zip-file fileb://handler.zip # 既存ハンドラ関数の更新 aws lambda update-function-code \ --endpoint-url http://localhost:4574 \ --region us-east-1 \ --profile localstack \ --function-name handler \ --zip-file fileb://handler.zip --publish
デプロイまでしておきつつ、動作確認はLocalStackを経由せずに手元から直接Goを動かすのが速くて楽です。
実行は下記コマンドで行います。
go run handler.go
せっかくデプロイしたので、LocalStack上のLambdaを呼び出したいですよね。 実行自体は下記のコマンドで実行します。
aws lambda --endpoint-url=http://localhost:4574 invoke \ --function-name handler \ --payload '{ "name": "testtest"}'\ result.log
しかし、LocalStack上のLambdaからDynamoDBに接続できない問題があります。 エンドポイントを変えずにAWSにデプロイし、実行すると問題なく接続できるので、LocalStack固有の問題なのではないかと思います。
参考までに、発生したエラーはこちらです。
HTTPConnectionPool(host='localhost', port=4574): Read timed out. (read timeout=60) localstack_1 | START RequestId: b7879ca4-4d51-15b6-ea01-1145f4c29e0c Version: $LATEST localstack_1 | RequestError: send request failed localstack_1 | caused by: Post http://localhost:4569//: dial tcp 127.0.0.1:4569: connect: connection refused localstack_1 | END RequestId: b7879ca4-4d51-15b6-ea01-1145f4c29e0c localstack_1 | REPORT RequestId: b7879ca4-4d51-15b6-ea01-1145f4c29e0c Duration: 51179.39 ms Billed Duration: 51200 ms Memory Size: 1536 MB Max Memory Used: 9 MB localstack_1 | { localstack_1 | "errorMessage": "RequestError: send request failed\ncaused by: Post http://localhost:4569//: dial tcp 127.0.0.1:4569: connect: connection refused", localstack_1 | "errorType": "baseError" localstack_1 | }
今回はGoで書いたLambdaからDynamoDBを呼び出す方法を紹介しました。
DynamoDBに接続するためのGoの処理はguregu/dynamo
を使用することで、複雑な処理を書かなくて済みました。
LocalStackはCLIでしか操作できない点は難点であるものの、Lambdaを手元ですぐに実行できるのは大きなメリットだと思います。ただし、LocalStackに登録したLambda関数からDynamoDBへはうまく接続できないので、go run
などで直接goの関数を叩かなければならないという手間も発生します。*2
以前ServerlessFrameworkでLambdaからDynamoDBを呼び出す処理を書いていました。しかしServerlessFramework単体だと修正, デプロイ, 動作確認のビルドライフサイクルが遅くなる問題があります。 今回は、その問題を解消すべく、LocalStackのインストールからDocker Composeで動かすまでの手順について紹介します。
LocalStackは、AWSの主要サービスのモックをローカル環境で動作させるツールです。
現在モックとして提供できるサービスはこちらです。
API Gateway, Kinesis, DynamoDB, DynamoDB Streams, Elasticsearch, S3, Firehose, Lambda, SNS, SQS, Redshift, ES (Elasticsearch Service), SES, Route53, CloudFormation, CloudWatch, SSM, SecretsManager
AWSのモックサービスをローカルに立てることで下記のようなメリットがあります。
今回はLocalStackをDocker(Docker Compose)で動かします。
Docker for Macの場合、Dockerのインストールと共にDocker Composeが使用可能になります。
LocalStack用のクレデンシャル情報を作成します。アクセスキーとシークレットアクセスキーは"dummy"のような感じで問題ありません。
$ aws configure --profile localstack AWS Access Key ID [None]: dummy AWS Secret Access Key [None]: dummy Default region name [None]: us-east-1 Default output format [None]: text $ cat ~/.aws/credentials [localstack] aws_access_key_id = dummy aws_secret_access_key = dummy $ cat ~/.aws/config [profile localstack] region = us-east-1 output = text
LocalStackは単純にgit clone
を行うだけです。
git clone https://github.com/localstack/localstack
cd localstack
Macを使用している場合、起動時に共有パスの設定をする必要があります。具体的なエラーは下記の通りです。
ERROR: for localstack Cannot start service localstack: b'Mounts denied: The path /var/folders/dx/dnnz2ft55rn2j7s6m0mbzkl80000gn/Tis not shared from OS X and is not known to Docker.You can configure shared paths from Docker -> Preferences... -> File Sharing.See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info..'
このエラーが出た場合はDockerマークをクリック => Preference => File Sharing => /var/foldersを設定し、Docker再起動で解決します。
また、LambdaがDocker環境で動作させるための環境変数を設定します。 .envファイルを作成し、下記の通り設定します。
#!/usr/bin/env bash export LAMBDA_EXECUTOR=docker
編集が終わったらsource .env
で環境変数を設定します。
最後Docker Compose
で起動します。
docker-compose up
LocalStackの起動確認はブラウザからでも確認できます。 http://0.0.0.0:8080
ブラウザからだけでなく、awsコマンドを実行した場合にLocalStackで起動したモックに対して操作ができるか確認します。
aws --endpoint-url=http://localhost:4569 dynamodb list-tables { "TableNames": [] }
上記はDynamoDBのテーブル一覧を取得するコマンドですが、--endpoint-url
オプションを指定してローカルに向けています。
基本的には他のAWSサービスも--endpoint-url
を指定するだけです。
git cloneして多少設定するだけで、AWSのモック環境がすぐに手に入りました。手軽にモック環境が手に入るのは、ローカルでスクリプトの修正と確認をするサイクルの高速化につながります。また、単純にAWS利用料金もかからないので、サクッと動作確認などしたい場合は有用なツールだと感じました。
ただ、デメリットとしてはAWS各サービスの操作は全てCLIとなります。 そのため、awsコマンドに慣れていなかったり知らない場合は、awsコマンド自体を覚えたり調べる時間がかかってしまいます。 AWSの公式ドキュメントを参照すればわかるのですが、結構な手間になると感じました。 継続的に使用する場合は、CloudFormationを使って自動化しておくと良いでしょう。
技術書典でRe:VIEWを使っていたものの、文章を書き、textlintを回すというCI環境を整えることができませんでした。また、このCI環境は、ブログ執筆においても有効であるため、このタイミングで構築することにしました。
今回はRe:VIEWで書いた文章の校正をCircleCIとtextlintでGitHubのPRに自動コメントする仕組みを作ったのでその紹介をします。
仕様は下記の通りです。
まず最初にローカルでtextlintが実行できるようにします。 textlintはnpmで入れていきます。
$ node -v v8.11.3 $ npm -v 6.3.0
続いて、textlintのインストールと、textlintで使うルールのインストールを行います。
$ npm init -y $ npm install --save-dev textlint textlint-rule-max-ten
上記で入れるtextlint-rule-max-ten
は「一つの文で出現する読点の数をチェックする」ルールです。
次に、textlintのデフォルトでは、Re:VIEWの拡張子である.reに対応していないため、プラグインを入れる必要があります。
$ npm install --save-dev textlint-plugin-review
最後にtextlintの設定ファイルで、ルールとプラグインを有効にします。
{ "rules": { "max-ten": true }, "plugins": [ "review" ] }
この状態でtextlintを実行すると下記のような結果となります。
$ ./node_modules/.bin/textlint sample.re /Users/naoshihoshi/repo/sample.re 1:11 error 一つの文で"、"を3つ以上使用しています max-ten ✖ 1 problem (1 error, 0 warnings)
今回は便宜上、textlint-rule-max-ten
だけの紹介ですが、そのほかにも様々なルールが存在するので、お好みで設定していくのが良いと思います。
CircleCIは2017年夏あたりにバージョン2.0がリリースされましたので、今回はそれで作っていきます。
バージョン2.0からは.circleci/config.yml
の書き方が変わりましたが、公式のドキュメントがとてもわかりやすかったです。
個人的には、後述するconfig.ymlの紹介で全体感を見た後にドキュメントを読むとより理解が進みやすくなると思います。
バージョン2.0からはDockerが使えるようになります。また、CircleCIが用意しているイメージも各言語揃っています。 今回、GitHubへのコメントにRubyのgemを使うので、Rubyのイメージを使用します。
version: 2 jobs: build: docker: - image: circleci/ruby:2.4.1-node-browsers working_directory: ~/repo steps: - checkout - run: command: npm install - run: command: ./.circleci/review-textlint.sh
最終行で指定している./.circleci/review-textlint.sh
でtextlintの実行とGitHubのPRヘコメントを実行します。
まず、GitHubへの操作をするためのアクセストークンを取得し、CircleCIに設定をします。
GitHubにアクセスし、Settings > Developer settings > Personal access tokens
ページに遷移し、Generate new tokenでアクセストークンを取得します。
このトークンは次で使うのでメモっておいてください。また、このトークンは、この画面を離れると二度と表示されなくなります。
CircleCIにアクセスし、Settings > ${ユーザー名} > ${リポジトリ名} > Environment Variables
に遷移しAdd Variableボタンを押下します。
すると、モーダルが表示されるので、下記の通り入力します。
これで準備が整いました。最後にスクリプトを書いていきます。
#!/bin/bash # Test if pull request if [ "$CI_PULL_REQUEST" = "false" ] || [ -z "$CI_PULL_REQUEST" ]; then echo 'not pull request.' exit 0 fi REMOTE_MASTER_BRANCH="remotes/origin/master" gem install --no-document findbugs_translate_checkstyle_format checkstyle_filter-git saddler saddler-reporter-GitHub # filter files and lint echo "Put textlint review comments to GitHub" declare diffFiles=$(git diff ${REMOTE_MASTER_BRANCH} --diff-filter=ACMR --name-only | grep -a '\.[re$|md$]') echo ${diffFiles} if [ -n "$diffFiles" ]; then echo ${diffFiles} | xargs ./node_modules/.bin/textlint -f checkstyle \ | sed -e 's/\"/\'/g' \ | checkstyle_filter-git diff ${REMOTE_MASTER_BRANCH} \ | saddler report \ --require saddler/reporter/github \ --reporter Saddler::Reporter::Github::PullRequestReviewComment exit 1 fi
それでは処理をざっくり説明していきます。
GitHubのPRの存在確認
まず、GitHub上にPRがない場合はコメント先がないため、処理をスキップする条件分岐を書いています。
if [ "$CI_PULL_REQUEST" = "false" ] || [ -z "$CI_PULL_REQUEST" ]; then echo 'not pull request.' exit 0 fi
gem install
次にgem install
を実行します。
今回は、GitHubへのコメントはSaddler
を使って行います。
gem install --no-document findbugs_translate_checkstyle_format checkstyle_filter-git saddler saddler-reporter-GitHub
textlint対象ファイル抽出
この処理は、textlintの対象ファイルを抽出するコマンドです。
リモートのmasterと、CircleCIで回しているリポジトリのdiffを取得し、拡張子が.reと.mdのファイルだけを抜き出しています。
declare diffFiles=$(git diff ${REMOTE_MASTER_BRANCH} --diff-filter=ACMR --name-only | grep -a '\.[re$|md$]') echo ${diffFiles}
GitHubへコメント送信
最後に、textlintを実行した結果をXML化し、GitHubのPRへコメント送信処理を行います。
エラーがある場合は、XMLのエスケープ処理を行なった上で、GitHubへ送信します。
具体的な処理はSanddlerにお任せしています。
if [ -n "$lintResult" ]; then echo ${lintResult} | sed -e 's/\"/\'/g' \ | checkstyle_filter-git diff ${REMOTE_MASTER_BRANCH} \ | saddler report \ --require saddler/reporter/GitHub \ --reporter Saddler::Reporter::GitHub::PullRequestReviewComment exit 1 fi
処理は以上です。
まず、適当なリポジトリにブランチを切ります。
次に、.reか.mdファイルを作成します。ファイルの中身は読点を3つ以上含んだ文を書いておきます。
例)
読点が、3つ以上の、文にしておくと、GitHubに、コメントが、つくはず。
最後に、そのファイルをpushします。
良い感じに落ちてますね!
ばっちりですね👏
今回は、CircleCIとGitHubのPRを用いて、textlintを実行、コメントしてくれる環境を作りました。
執筆していたときは、都度textlintを実行していたのが本当にめんどくさかったです...。
今回構築してみて、比較的簡単に構築することができたので、これから執筆活動をする方は、まずこのCI環境を作ってから執筆することをお勧めします!
技術書典5に参加したのですが、自分で本を作るのは初めてだったので、Re:VIEWの使い方から学び、入稿して印刷所のサポートの方から指摘を受けて再入稿して、やっと物理本を完成させることができました。
今回この記事では、Re:VIEWで執筆とPDF出力を行い、印刷所に不備のない入稿をするポイントの紹介をします。
印刷所への入稿はPDFであれば良いため、執筆ツールはなんでも良かったりします。
当初、書き慣れているMarkdownで執筆をしようとしていました。 しかし、Re:VIEWを調査すると、レイアウト、目次ページ、ページ番号の挿入、表紙挿入、ノンブル設定など書籍執筆を支援する機能が充実していたので、記法を覚える学習コストを払ってでも使うべきだと考え、Re:VIEWで執筆をしました。
まずはRe:VIEWの概要を知り、インストールをしました。 gem化されていたり、Dockerでも動かせるため、導入はとても楽です。
Re:VIEWは独自の記法を覚える必要があります。 ただ、覚えることはそんなに多くはありませんでした。自分はチートシートを見ながら書いていました。 下記リンクが簡潔にまとまっています。
PDF出力するためには、下記がインストールされている必要があります。
下記リンクを参考にしました。 mkdir.g.hatena.ne.jp
推敲の際、日本語のチェックを機械的にやりたかったので、textlintを使いました。
執筆が終わったら入稿の準備です! サークル仲間の@kaibaさんが先陣を切って日光企画さんに不備を指摘されており、そのポイントがまとめられてました。(めちゃくちゃありがたい!) ポイントは下記の通りです。
技術書典、Re:VIEWで作った原稿で印刷所(日光企画様)に怒られたポイントと対応まとめ – Pokosho!
執筆お疲れ様でした!いよいよ入稿です。 印刷所は運営からも案内されている日光企画さんにしました。 サポートの方がめちゃくちゃ優しい方です!
日光企画さんは、
という感じで、オペレーションで困ることはあまりありませんでした。
平トジと中トジかで、ページ数を調整しなければなりません。
非常に難しいですね。強気でチェック数以上に刷る人や、日和って50部未満にしてしまう人などなど。
爆死リスクと機会損失を天秤にかけなければならないので一概に正解はないと思います。
自分の場合は、在庫を抱えたくなかったので、40部に抑え、ダウンロードカードも準備して機会損失にも対応できるようにしました。
ただ、次回は、日光企画さんの早割(50%)で入稿して、100部くらい刷ろうと思います
物理本だけではなく、PDFでも売りたい場合、ダウンロードカードを作成しなければなりません。 ダウンロードカードとは、PDF頒布サイトのURL(通常はQRコードが記載されている)とシリアルコードが書かれているカードのことです。 私は対面電書というサービスを使いました。
対面電書の良いところは下記の点です。
という点が良いところです。
BOOTHも検討したのですが、購入者が会員登録しなければならないのが煩わしいだろうと思い、対面電書にしました。
ダウンロードカードは別途印刷所で刷るのも良いですし、プリンターで印刷したものをカッターで切るのでも良いと思います。 自分は、温かみがあった方が良いと思ったため、プリンターで印刷してカッターで一枚一枚切りました。
印刷する際、A4の1枚の紙から複数のダウンロードカードを作りたかったので、設定をする必要がありました。下記リンクが参考になります。
執筆から入稿、ダウンロードカード作成までに使ったもの、調べたものは以上です。 初めてだったとはいえ、調べれば意外になんとなることがわかりました! 印刷所への入稿は流石に不安しかなかったのですが、@kaibaさんが指摘されたポイントをまとめてくれたのには頭が下がります!ありがとうございました!
10月8日(月)に開催された技術書典5で出店者側として参加しました。 今回は技術書典5の参加レポートと振り返り(KPT)について書こうと思います。
技術書典には今回初参加でした。
また、これまでの執筆実績といえばSoftwareDesignに2回寄稿したくらいでした。
そのため、原稿を書いた後の工程はほぼわからない状態で臨みました。
Re:VIEWの存在も入稿の仕方もわからない状態です。
BFF(BackendsForFrontends)について書きました! 本の内容はこんな感じです。
本当は、下記のようなアーキテクチャで、何かしらのアプリを作るような本を書こうと思ってました。
しかし、8/1(水)の当選通知を受けてから、技術検証を始めるというスロースタートだったので、スコープを絞らないと爆死すると思い、BFFのみに集中しました。
#技術書展 、スコープ絞らないと爆死するぞコレ
— 星 直史 技術書典5 け54 (@NaoshiHoshi) 2018年8月4日
正直、技術検証と執筆を2ヶ月で行うのは結構キツかったです
今回は出店者として参加でしたが、非常に楽しかったです!!
2ヶ月もかけて制作したものが、リアルな本になったことが純粋に嬉しかったです。自分が書いた文章が本になり達成感を感じました。
そして、本が売れていく瞬間はこれまで経験したことがない嬉しさでした。
すごい、売れる売れる! #技術書典5 https://t.co/DoZpJy9dyI
— 星 直史 技術書典5 け54 (@NaoshiHoshi) 2018年10月8日
ブースの設営自体は改善の余地はありますし、コミュ力のなさを発揮してしまい、@kaibaさんの営業力に嫉妬したりしましたが、現時点で次回の参加もしようと決めています。
また、イベント自体、ここまで人がくるとは思っていなかった点や、後払いアプリが非常に使いやすく、とても満足でした◎
項目 | 計算 | 金額 |
---|---|---|
物理本売上 | 1,000円 * 43冊 | 43,000 |
DL版売上 | 1,000円 * 15冊くらい | 15,000 |
参加費 | 7,000 / 2 | △3,500 |
印刷費 | 物理本 60項40部 | △33,772 |
計 | 売上 58,000 - 費用 37,272 | 20,728 |
黒字でした!!!!!! 人件費は自分だけなので0円です!素晴らしい! 当初、赤字になってもいいかなぁ〜くらいに思っていたのと、特に利益は求めていなかったで、棚から牡丹餅です!
また、印刷費用に関しては、日光企画さんの場合は早割が存在します。最も早い入稿で割引率は50%です。
原価の多くは印刷費であるため、次回は早割を狙っていきたいです。
利益となった2万円は、タイトルの通りスマホを購入しました!!ひゃっほい!*1
時間別売上推移はこんな感じです。
当初、物理本は11時台が最も売れ、その後1時間ごとに半減していくという予想をしていましたが、13時まで一定のペースで売れ続けました。 また、14時以降は見本を手に取ってもらうことが少なくなったため、顧客層の変化を感じました。 その他、物理本がない == 売り切れと認識とされる方が多く、少なからずDL版の売れ行きに影響があったと思われます。
日和って40部にしないで、60部くらい用意しておけば良かったのは反省点です。また、次回は見本を手に取った件数をカウントしていきたいです。
参加サークルは、事前に被チェック数*2がわかります。
最終的な被チェック数は170でしたが、印刷時点(イベント開催1週間前)で120でした。
被チェック数から推測される販売数から発行部数を推測した場合、イベント直前になる程、信頼性は高まると思います。
しかし、早割(50%)の入稿期限は1ヶ月前であるため、被チェック数から販売数が推測できないというジレンマがあります。
ただ、原価がざっくり半分になるので、爆死しても痛みは少なくなるでしょう。
販売数を左右する要素の一つとして、価格は重要だと思います。
同じく参加した@kaibaさんは80部@500円 売り上げていました。
本の内容が異なるので一概には言えませんが、500円で80部売れるものが、1,000円で60部売れるので、価格弾力性は0.25で被弾力的と言えます。
ただ、自分の体感的には1,000円以下の場合はお祭り気分で購入できる価格帯であり、1,500円以上は現実に立ち返り、本題材に対して必要性を感じ、かつ、その本が有用である場合に購入するなぁと思いました。
価格 | 感じ方 |
---|---|
500円 | 気になるくらいなら買う |
1,000円 | 面白い内容なら買う |
1,500円以上 | 必要性を感じていれば買う |
需要から考えると60ページくらいの本であれば、1,000円が妥当なのではないかと思います。
弱小サークルが発行する本であっても、60ページで1,000円であれば60部程度なら売れることがわかりました。
そのため、早割(50%)で入稿し、60~120部用意するの最良の手だと思いますので、次回Tryしてみます。
次回参加を決めているので、振り返りをして改善していこうと思います。
技術書典5に参加し、初めて本を書いたのですが、本が読まれる喜びを知ることができました。 また、値付けや売り上げ予測など書くこと以外にも考えることがあり、良い経験になりました。
次回も参加しようと決めているのですが、今回の学びや反省を活かして改善していこうと思います!!
サービスを公開したと同時に、mackerelを導入してみました。 CPU, Memory, filesystemのアラートをデフォルトの閾値で設定した結果、一瞬でfilesystemのアラートが鳴りました。
ぬほほ、mackerelで監視項目追加したろ^^
— 星 直史 (@NaoshiHoshi) July 17, 2018
とか思って設定したら、その項目既にcriticalの値だったから汗でた
すぐさま対応できなかったので、とりあえずアラートを止めるために閾値を変えるというワークアラウンド対応をしました(白目)
ただ、ディスク容量の75%ほど使用していたので、根本的に対応しなければサービス断になると思われるため、ボリューム拡張をすることにしました。 今回はAWS EC2のルートボリューム(EBS)をダウンタイム0で拡張する方法について書こうと思います。
何はともあれ、AWS マネジメントコンソール > EC2 > ELASTIC BLOCK STORE > Volumes画面に行きましょう。
Actionsプルダウンを押下し、Modify Volumeを選択します。
続いて、任意のVolume TypeとSizeを選びます。
今回は、Volume Typeの変更はなく、Sizeを8GiBから16GiBに拡張します。
そして、Modifyボタンを押下。
すると、アラート的なものが表示されます。
Are you sure that you want to modify volume vol-xxxxxxxxxxxxx?
It may take some time for performance changes to take full effect.
You may need to extend the OS file system on the volume to use any newly-allocated space.
Learn more about resizing an EBS volume on Linux and Windows.
=> vol-xxxxxxxxxxxxxを変更してもよろしいですか?
=> パフォーマンスの変更が有効になるまでには時間がかかることがあります。
=> 新しく割り当てられた領域を使用するには、ボリューム上のOSファイルシステムを拡張する必要があります。
=> LinuxおよびWindowsでのEBSボリュームのサイズ変更の詳細については、こちらをご覧ください。
とのこと。Yes!!!
モーダルが閉じたところで、念のため、Sizeが変わったことを確認します。
また、Stateがin-use - completed(100%)になるまで少し待ちましょう。
AWS マネジメントコンソール上の操作は以上です。
さきほど出てきたアラートの通り、インスタンスにSSHアクセスし、コンソール上からボリューム拡張を反映させる必要があります。
file -s
コマンドで使用しているファイルシステムを確認します。
$ sudo file -s /dev/xvd* /dev/xvda: DOS/MBR boot sector; ...... /dev/xvda1: Linux rev 1.0 ext4 filesystem data, .....
Linux ext4 ファイルシステムと DOS/MBR boot sectorというファイルシステムなのがわかりました。
インスタンスにアタッチされたブロックデバイスを確認するためにlsblk
コマンドを使います。
$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 16G 0 disk └─xvda1 202:1 0 8G 0 part /
おぉ〜、しっかり16Gibがアタッチされていますね。
この情報から、ルートボリュームである/dev/xvdf1 は、16 GiB のデバイス(/dev/xvda)に含まれる 8 GiB のパーティションでだということがわかります。
また、この/dev/xvdaはパーティションは/dev/xvdf1以外ありません。そのため、ボリュームの残りの領域を使用するために、パーティションのサイズを変更する必要があるということがわかります。
growpart
コマンドでパーティションのサイズ拡張をします。
$ sudo growpart /dev/xvda 1 CHANGED: disk=/dev/xvda partition=1: start=4096 old: size=16773086,end=16777182 new: size=33550302,end=33554398
再び、lsblk
コマンドで、意図した変更になっているか確認します。
$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvda 202:0 0 16G 0 disk └─xvda1 202:1 0 16G 0 part /
良さそうですね。
このままでは、ディスクのパーティションが切れただけで、ファイルシステムに変更が反映されていません。
$ df -h ファイルシス サイズ 使用 残り 使用% マウント位置 devtmpfs 488M 56K 488M 1% /dev tmpfs 497M 0 497M 0% /dev/shm /dev/xvda1 7.8G 5.5G 2.2G 72% /
Linux ext4 ファイルシステムの変更反映はresize2fs
で行います。
$ sudo resize2fs /dev/xvda1 resize2fs 1.42.12 (29-Aug-2014) Filesystem at /dev/xvda1 is mounted on /; on-line resizing required old_desc_blocks = 1, new_desc_blocks = 1 The filesystem on /dev/xvda1 is now 4193787 (4k) blocks long.
最後に変更がうまく行っているか、確認します。
$ df -h ファイルシス サイズ 使用 残り 使用% マウント位置 devtmpfs 488M 56K 488M 1% /dev tmpfs 497M 0 497M 0% /dev/shm /dev/xvda1 16G 5.5G 11G 36% /
/dev/xvda1のサイズ16Gibになり、使用率が72% => 36%に下がりましたね!
AWSマネジメントコンソール上でEBSのSizeをアップし、数分待つことで、容量が増えました。
また、EC2インスタンス上にSSH接続し、パーティションの容量変更とファイルシステムへの反映を行うだけで、インスタンスを停止せずにルートボリュームの拡張を行うことができました。
インスタンス停止せずにボリューム拡張できるのは素晴らしいですね!
mackerelのグラフも、ぴょこんと上がりました!
これまで、Webサービスを作ったことはあれど、サーバーの管理/監視は構築したことがありませんでした。
手軽に導入したかったので、SaaS型サーバー監視サービスを導入しようと考えていました。
そこで、今回はmackerelを使って監視をしようと思います。また、AWS OpsWorksのカスタムクックブックでプロビジョニングしていたので、mackerelをAWS OpsWorks カスタムクックブックでインストールする方法について書こうと思います。
何はともあれ、スタートアップガイドを読みます。今回はAmazonLinuxを使用しているので、それ用のガイドを読みます。
ステップは超絶簡単ですね。
curl -fsSL https://mackerel.io/file/script/amznlinux/setup-all-yum.sh | MACKEREL_APIKEY='<YOUR_API_KEY>' sh echo "apikey = '<YOUR_API_KEY>'" >> /etc/mackerel-agent/mackerel-agent.conf sudo /sbin/service mackerel-agent start
こんだけ!
まずはmackerelのダッシュボードでAPIキーの確認をします。
Organization > APIキータブ から確認します。
AWS OpsWorks スタック におけるCustom Chef cookbooksを適用する方法 - production.log
こちらを参考にレシピを作っていきます。 レシピはスタートガイドにある通り、3つのコマンドを実行するだけのシンプルなものです。
api_key = node[:deploy][:testrooper][:mackerel_apikey] execute "mackerel install" do user "root" command "curl -fsSL https://mackerel.io/file/script/amznlinux/setup-all-yum.sh | MACKEREL_APIKEY='#{api_key}' sh" action :run end bash "add api key" do not_if 'grep "apikey" /etc/mackerel-agent/mackerel-agent.conf' code <<-EOC echo "apikey = '#{api_key}'" >> /etc/mackerel-agent/mackerel-agent.conf EOC end execute "run agent" do user "root" command "/sbin/service mackerel-agent start" action :run end
こちらのコードはGitで管理しているわけですが、APIキーをコードに直接書かないようにしています。
何も知らずにPublicリポジトリにしちゃったりなんだりした場合に、意図せずインターネットにAPIキーが晒されてしまうためです。
そのため、APIキーはOpsWorksのCustomJSONから取得するようにしています。
先述の通り、AWS OpsWorksのCustomJSONに記述したAPIキーを使ってプロビジョニングするので、その設定をします。
AWS OpsWorks > Stack > Stack Settings > Edit
{ "deploy": { "testrooper": { "mackerel_apikey": "xxxxxxxxxxxxxxx" } } }
最後に、カスタムクックブックを実行して終了です。
ステップは、Deployments > RunCommandで下記2つを実行するだけです。
無事にmackerelのagentが動いていれば、ダッシュボードに1ホストだけACTIVEになっているはずです。
無事にmackerelをAWS OpsWorks カスタムクックブックでインストールできました👏
そもそもの導入が簡単というのもありますが、手順をコード化することで、今後サーバーが何台増えてもレシピを実行するだけで済むようになりました。
あとは、mackerelの方で通知の設定などを行うだけで楽々とサーバー管理ができそうです!
最近個人プロジェクトの開発をしているのですが、気づけばGithubの草が60日間連続で生えていました。 60日間も毎日草を生やしていると、完全に習慣されたと思ったため、 今回はGithubの草を60日間連続で生やしてわかった習慣化のコツを紹介します。
自分がモチベーションを感じることとしては、学びたいことを学んでいるときや、なりたい自分に近くための学習など「やりたいこと」を実行しているときです。
「やりたいこと」と関連がある学習を行なっているときは、少なくとも2ヶ月くらいは継続的に学習ができていた記憶があります。
一方、必要に迫られた学習など、「やるべきこと」を実行しているときは、あまりモチベーションの高まりを感じることができず、長期的には習慣化できませんでした。
とはいえ、やりたいことを優先しすぎると、成果*1の最大化には繋がらないと思い、「やるべきこと」と「やりたいこと」が重なるように意識しました。
学習の対象が、学びたいものかつ、学ぶべきものだったばあい、「やるべき」と「やりたい」が重なっている状態になります。
この動機のスイートスポット*2が存在する場合は、まずはそこにフォーカスすることをおすすめします。
先述した学習のスイートスポット*3が存在すれば苦労しませんが、多くはないでしょう。
ただ、「やるべきことは、必ずしもやりたいことと重なるわけではないが、少なからず、好影響があるかもしれない」といったように、楽観的に考えることが重要です。
物事は、何にでもグラデーションがあるので、一見、やりたいこととは無関係でも巡り巡って自分のやりたいことに繋がるか?を考える事が重要です。
そのため、やるべきことの中から、やりたいことに近付く要素が最も多いものを取捨選択することになります。
取り得る選択始の中でモチベーションと成果が最大化されるものを吟味していきましょう!
Githubの草を生やす上で欠かせないのはGItHub-Gardenerです。
こんな感じで可視化されるのですが、各種スコアが表示されます。
consecutive days (best record updating) 60 days
特に、継続日数が表示されるこの部分ですが、強烈な強制力があります。
継続日数を増やしていく中で、下記のような嬉しさ、達成感、充実感がありました。
継続日数 | 嬉しみ |
---|---|
7 days | 草が一本に繋がって単純に嬉しい |
10 days | 値が2桁になって嬉しい |
30 days | 草から芝生となった嬉しさと、謎の達成感 |
60 days | 習慣化された充実感 |
先述の通り、GitHub-GardenerはGitHubの芝生を可視化ツールであり、継続日数を数値として表示します。
初心者Gardenerだった自分は、まずは3 daysを目標にしました。3 days達成すると7days, 10 days, 30 days, 60days....、と次の目標を意識することができました。
この効能は、ある程度粒度が大きい到達点(マイルストーン)を認識することで、目標達成に対する意識が芽生えさせることができることです。
また、継続日数をマイルストーンとして設定した場合、自分のリアルなスケジュールを見比べて、「○曜日は仕事の帰りが遅いから次の日の朝に影響が出そうだ。タスクの粒度を極小にしよう」といったリスク回避について考えることもできます。
朝6時に起きたとしても、確保できる時間は3時間前後です。3時間しかないと、できることは多くはありません。
そこで、コミットするタスクを分解して、目標達成に向けてのリズム作りをしました。
よくある継続学習指南では、しばしば「まずは本を開くところから始めよ」「まずは5分から始めよ」というのを目にしますが、まさにこれです。
週: 平日/休日 | 1日あたりの作業時間 | 作業内容 |
---|---|---|
1週目: 休日 | 12h | 規模が大きめの実装 |
1週目: 平日 | 3h | 些細なデザイン調整や規模の小さいリファクタなど、作業開始から30分以内でコミットできるような粒度のタスク |
2週目: 休日 | 12h | 技術調査と平日のためのタスク分解 |
2週目: 平日 | 3h | 休日に行なった粒度の小さいタスクの実装 |
といったように、割り当てることができる時間と、タスクの粒度を合わせることで、無理のないペースで確実に成果を出すことができます。 平日は粒度は小さいタスクの積み重ねがメインとなるのですが、自身で成功体験を積み重ねることと、それを自分自身で承認することが習慣化のコツです。
その点、GitHub-Gardenerは、GitHub-Gardenerを使うことで、自然と上記が達成できるような仕組みになっていると言えます。
すごいぞ、GitHub-Gardener。
GitHub-Gardenerを使うと、草を生やしていない(commitしていない)と、謎の不安感に包まれるようになります。 これは適度な負荷であり、生活にちょっとした緊張感を与えるストレスだと思います。ストレスを力に変えましょう。
GitHub-Gardenerを使うと、朝目が覚めたときに、まず「commitしなきゃ!」と、頭に浮かぶようになりました。 普段は「眠いなぁ〜、もう少し寝ようかなぁ〜...ZZzz」ってなるのですが、この思考のインターセプトはやばいですね。 そのため、結果的に朝、目覚めと同時にcommitするようになりました。
また、朝6時に起きてcommitという生活を続けていると、スケジュールや体調に左右されずに安定して自己研鑽できることがわかりました。
素晴らしいぞ、GitHub-Gardener。
60日間継続的にアウトプットし続けることができたので、習慣化のコツを書いてみました。
基本的には、何が学びたいんだっけ?何を得たいんだっけ?を軸に考えていくと継続はできるのではないかと思います。
ただ、人間は易きに流れやすい生き物であるため、ある程度、強制力や自己承認のための仕組みが必要です。
自分は補助的な役割としてGitHub-Gardenerを選びましたが、継続をするための仕組みが無駄なく全て揃った良いサービスでした。
おすすめです。
個人開発において、Railsのdeviseから配信されるメールは、これまでGmailを使用していたのですが、せっかくドメインを取得したので、AWS SESからメールを送信することにしました。
今回はRailsにおいて、deviseが送信するメールをAWS SESから配信する方法について書きます。
SESはデフォルトでは特定のメールアドレスには設定さえすれば、送信することができます。
しかし、多くのWebサービスは不特定多数のユーザーにメールを送信するため、その設定を行います。
Identity Management > Domains > Verify a New Domain
Verify a New Domain を押下すると、ポップアップが出てドメインの入力を求められます。
取得したドメインを入力し、Generate DKIM Settingsもチェックします。*1
Route53でドメインを取得している場合は、Use Route53ボタンを押下すれば、AWSの方で自動でRecord Setを設定してくれます。
しばらく時間をあけると
Identity Management > Domains > 登録したドメイン にアクセスするとVerificationとDKIMのステータスがverifiedになっています。
Email Sending > Sending Statisticsにアクセスすると、上記のような警告がでます。
現状、特定のメールアドレスにしか送信できない送信制限がかかっているので、サポート制限緩和申請をする必要があります。
上記の通り、各種項目を入力します。
1日くらいすると、AWSの審査の末、SESからメール送信が可能になります。
Identity Management > Domains > Send a Test Email から、任意のメールアドレスにメール配信が可能になります。
Send Test Mailボタンを押し、メールが受信できれば成功です。
SES自体が使えるようになったので、今度はRails側の設定をしていきます。
Railsでaws sdkを使用するためにGemfileに下記を追記します。
gem 'aws-ses'
config/initializers/aws.rbを新規で作成し、下記の通り、SESを使用するように変更します。
ActionMailer::Base.add_delivery_method( :ses, AWS::SES::Base, access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), server: 'email.us-west-2.amazonaws.com' )
server はSESで選択したリージョンによって異なるので 公式ドキュメントのリージョンと Amazon SES から API (HTTPS) エンドポイントを確認してください。
次に、config/environments/production.rbの設定をSESを使用するように変更します。
config.action_mailer.default_url_options = { host: 'testrooper.com' } config.action_mailer.delivery_method = :ses
config/initializers/devise.rbのconfig.mailer_sender
を修正します。
# config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' config.mailer_sender = 'Testrooper <noreply@testrooper.com>'
最後にMailerクラスのfromの設定を変更して終わりです。
# frozen_string_literal: true class ApplicationMailer < ActionMailer::Base # default from: "from@example.com" default from: "Testrooper <noreply@testrooper.com>"
これまで説明した通り、SESの設定自体はとても簡単です。
送信制限緩和申請のために、1日程度かかってしまうのですが、特に審査に落ちることもなく使えるようになりました。
また、Railsの方の設定も、難しいことはなく、設定ファイルの修正だけでした。
これまでGmailしか使っていなかったのですが、ドメインがあるのであれば、初手でSESを選択した方が良いかもしれませんね。
*1:DKIM とは DomainKeys Identified Mail の略で、受信した電子メールが「正当な送信者から送信された改ざんされていないメール」かどうかを調べることができる電子署名方式の送信ドメイン認証技術
AWS OpsWorks スタックでは、Chef Supermarketで公開されているCookbooksを適用する方法もありますが、自前で作成したCustom Chef cookbooksを適用することもできます。
今回はAWS OpsWorks スタックにおいて、自前で作成したCustom Chef cookbooksを適用する方法を紹介します。
test-chefという名前のPublicリポジトリを作成します。そして、下記のようなフォルダ構成にします。
naoshihoshi 10:03:00 test-chef$ pwd /Users/naoshihoshi/test-chef naoshihoshi 10:03:02 test-chef$ tree . └── hoge └── recipes └── default.rb
Opsworksではrecipesディレクトリ直下のdefault.rbがデフォルト呼ばれることになります。 default.rbの内容は下記の通りです。とりあえず動かしてみるだけのコードですね。
# hoge/recipes/default.rb log "Hello Chef"
ログに"Hello Chef"と出力されれば、動作していることがわかります。
OpsWorksでスタックを追加し、さきほど作成したcookbooksを適用します。
スタック作成画面で
1. Use custom Chef cookbooksをYesに変更
2. Repository URLは先ほど作成したtest-chefのリポジトリのURLを指定
Layerを追加し、Recipesの変更を行います。
今回は、Setup時に先ほどのレシピを実行させたいので、このような設定になります。
gitで管理しているリポジトリの直下にあるディレクトリを設定すれば、その配下にあるrecipesディレクトリのdefault.rbが呼び出されるという仕組みです。
naoshihoshi 10:03:02 test-chef$ tree . └── hoge <===== このディレクトリが設定された場合、 └── recipes └── default.rb <===== これが呼び出される
インスタンスを作成し、起動をすると、setupで設定したレシピが実行されます。 インスタンス起動後にログがみれるので、インスタンス名をクリックし、ページ下部のログのshowリンクでログを確認します。
無事にHello Chef
が表示されていますね!
default.rb以外に実行したい場合は任意のファイルを作成後hoge::任意のファイル名
とします。
. └── hoge └── recipes ├── configure.rb └── default.rb
configure.rbを作成した場合、Layerの設定ではhoge::configureとなります。
小さなコードではありますが、OpsWorksで自前で用意したCustom Chef cookbooksを動かすことができました。 また、レシピを複数用意して、任意のレシピを実行する方法もとてもシンプルで簡単でした。 動かし方さえわかってしまえば、あとはプロビジョニングのためのコードを書き足していくだけです!