Terraform における Assume Role と S3 Backend

Terraform で S3 を Backend に指定してステートファイルを管理したい。これを達成するため .tf ファイルに次のような記述をするとしよう。 terraform { ... required_providers { aws = { source = "hashicorp/aws" version = "3.23.0" } ... } backend "s3" { bucket = "my-bucket-for-tfstate" key = "terraform.tfstate" region = "ap-northeast-1" } } provider "aws" { region = var.region access_key = var.aws_access_key secret_key = var.aws_secret_key assume_role { role_arn = var.aws_role_arn } } 次に S3 に my-buekct-for-tfstate バケットを作成して terraform init をするとしよう。次のようなエラーが表示されるだろう。 $ terraform init Initializing modules. [Read More]

家計簿作成の自動化スクリプト (ソニー銀行を対象)

前回の記事で次のように書いた。 今は家計簿をつけるためにレシートから CSV ファイルを手入力して支出の管理をしているけど、これは時間の無駄だ。 これを解消する GAS (Google Apps Script) を作成したので、紹介しよう。 僕のメインバンクはソニー銀行である。ソニー銀行のキャッシュカードには Visa デビットカード機能がついている。そして、このデビットカードを使用すると明細がメールで通知される。メール本文には次のような内容が含まれている。 姓 名 さま Sony Bank WALLET(Visaデビット)のご利用がありました。 ・カード利用日: 2021年04月25日 ・ご利用金額(※):1,000円 ・ご利用加盟店:AMAZON CO JP ・承認番号: xxxxxxxx これらを正規表現で抜き出してスプレッドシートに転記できればよい。具体的には次のような GAS を書いた。 var SearchString = "from:banking@sonybank.net Subject:[Sony Bank WALLET ]Visaデビットご利用のお知らせ -label:processed newer_than:1d"; function _createlabel(labelString) { labelDomain = GmailApp.getUserLabelByName(labelString); if (labelDomain === null) { labelDomain = GmailApp.createLabel(labelString); } return labelDomain; } function kakeiboSpreadsheet() { var myThreads = GmailApp. [Read More]

NOT to-do list (および時間を作るための自動化)

息子が生まれてからというもの、時間に追われる生活をしている。昔はテレビゲームをしたり、(漫画) 本を読みふけるなどしたものだが、そういう贅沢は自分にはもうない。…ないんだけど、魔が差してテレビゲームを購入したり漫画を購入したりすると、やはり時間をどんどん溶かせてしまう。その結果、勉強時間と睡眠時間が削られる。

そこで “NOT to-do list” を作ろうかと思う。「自分はこれに時間を費やしていいのか?」と迷うときは NOT to-do list を参照して、迷いなく Yes/No の決断をできるようにしたい。NOT to-do list は時間をかけて項目を考えたいと思う。例として挙げた「テレビゲーム」と「漫画」は最初に入れる。

逆に時間を生み出すものには逆にどんどん投資していきたい。たとえば、今は家計簿をつけるためにレシートから CSV ファイルを手入力して支出の管理をしているけど、これは時間の無駄だ。すべての生活費をクレジットカードで精算して、支払い通知の E メールをトリガーにして Google Apps Script でスプレッドシートに直せば、時間を節約できる。こういうアイディアは昔からあったけど、腰が重くて手をつけられていなかった。しかし、未来の時間のために現在の時間を投資するという観点はやはり重要だ。姿勢をあらためていきたい。

【読書メモ】Learn or Die

Learn or Die」を読んだ。副題は「死ぬ気で学べ プリファードネットワークスの挑戦」である。だいぶ主張の強いタイトルだ。

本書はプリファードネットワークス (以下 PFN と書く) の共同創業者二人が書いた本である。Startup DB の記事によれば PFN は日本のユニコーンの中でも最も時価総額が高く、かつ二位とはダブルスコア以上の差をつけている。広く業界からリスペクトを集めている企業だ。僕も PFN には注目している。

実は過去の職場で PFN の前進である PFI 出身の方と一緒に働いた経験があり、PFN も順風満帆であったわけではないという話は聞いていた。本書では「創業者同士で借金をしながら従業員の給与を払った」という過去のエピソードも紹介されている。輝かしい企業の生々しい苦労話を読むのは楽しい。こういう読書経験を通してこそ、自分自信の苦労も肥やしにする力がつくように思う。

著者らの Nerd な一面 (“一面” というより、こちらの方が本質なのかもしれない) を垣間見えるのもよい。著者の西川徹さんが中高生の頃に教室にパソコンを持ち込み、プログラミングをしながら授業を聞いていた話などは、率直に「羨ましい」と思った。西川さんは筑波大学附属駒場の中高一貫校のご出身らしく、その環境を「自由な校風」と表現している。僕が卒業した小・中学校にはそのような自由はなかった。せめて自分の子どもにはなるべく自由な世界で過ごしてもらいたいと思った。

ところで、つっこみたくなったのは Epilogue の次の一節である。

これからの5年、10年くらいで人間はコードを書かなくなるだろう。本編でも書いたとおり、私たちは、人間がコードを書かなくてもプログラムを組めるようなシステムを作っているということになる。

もしかしたら、そういう日が来るかもしれない。本書の出版は 2020 年なので、著者らは 2025~2030 年くらいに「人間がコードを書かなくなる」時代が来ると考えているのだ。しかし PFN は「小学生から始めるプログラミング教材」を作っている会社でもある。彼らの予想が的中すれば、今の小学生が大人になる頃がまさに「人間がコードを書かなくなる」時代ということになる。本当に 10 年後に人間がコードを書かなくなると思っているなら、このプログラミング教材は何のためのものなのか。ちなみに、僕は 2030 年でも人間はばりばりコードを書いているのではないかと予想している。

そのようなことを思いながら、本書を読んだ。

LeetCode - Repeated Substring Pattern

LeetCode で「難易度: Easy」とされている Repeated Substring Pattern を解いた。与えられた文字列が「部分文字列を繰り返している文字列かどうか」を判定せよという問題だ。たとえば "abab""ab" を繰り返しているので true であり、"aba" は部分文字列を繰り返してできる文字列ではないので false である。

文字列の長さが 10^4 なので、部分文字列を繰り返しているのであれば、最長でも 10^4/2 の範囲を調べればよい。このくらいであれば確かにブルートフォースできそうなので、難易度は Easy でもよいかもしれない。

しかし、解答の Approach #2 Concatenation はずっと簡潔である。

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        return s in (s + s)[1: -1]

僕はこれを理解するのに時間がかかった。未来の自分のために、これが何をしているのか書いてみよう。

(s + s)[1: -1] は与えられた文字列を二度繰り返して、そこから先頭と末尾の1文字を削ったものだ。つまり、"ab" が与えられたのであれば "abab" から先頭と末尾を削って "bab" である。これには "ab" が含まれているので true が返る。"aba が与えられたのであれば、(s + s)[1: -1]"baab" であり、これは与えられた文字列を含まない。

なぜこれでうまく行くのか。与えられる文字列 s が部分文字列を繰り返したものであれば、s + s は最小でも部分文字列を 4 つ含むことになる。前後の1文字を削ることで、少なくとも 2 つの繰り返される部分文字列を持つことになる。それこそが与えられる文字列 s となる。

自分自身のブログを読み返す話

ブログを書くようになってから、それなりに時間が経った。過去に自分で Movable Type をホストしていたときの記事や、はてなダイアリーに書いたりしたものは消えてしまったけど、それでも 2012 年から先の記事はまだ生きている。 ところで、僕のブログ記事をもっとも楽しく読めるのは自分自身なのではないかと思う。調べ物をしているときに検索エンジンが導いてくれるページはしばしば過去の自分のブログ記事だし、何より自分の記事は読みやすい。「過去の自分が名文を書いたから」ではなく、記事を理解するのに必要な前提知識があるからである (なにせ書き手が自分自身なので)。 自分がメンテナンスしているブログの sitemap.xml をパースしてリダイレクトするプログラムを Heroku で動かし、それをブラウザの新規タブのデフォルトページに設定したこともある。 新しいタブを開いたとき、自分のブログの中からページをランダムに選んで表示するようにしてみた。 — ヾ(✿❛◡❛)ノ Yasu 🤡 (@mahata) January 15, 2021 ただし、これだと新規タブを開くのが遅くなってしまう。よりよい方法はないかと模索している。 現在の暫定解は macOS の Launchd を使い、定期的にブログ記事をランダムに選んで Slack にポストするというものだ。 具体的には $HOME/LaunchAgents/slack-reminder.plist を作り、次のように記述した。 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>Slack Notifier 1 hour</string> <key>ProgramArguments</key> <array> <string>/Users/mahata/.pyenv/shims/python</string> <string>/Users/mahata/bin/slack-post.py</string> </array> <key>StartInterval</key> <integer>3600</integer> <key>StandardOutPath</key> <string>/tmp/slack-post.out</string> <key>StandardErrorPath</key> <string>/tmp/slack-post.err</string> </dict> </plist> 雰囲気で読めそうな気がするので詳細は割愛するけれど、これで 3600 秒ごと (つまり 1 時間ごと) に次のコマンドを実行する、と指定している。 [Read More]

Vagrant (VirtualBox) でディスクサイズを変更する方法

macOS を使い Vagrant で VirtualBox の VM を作り、そこで作業をするとしよう。そして途中で VM のディスク容量が足りないことに気づいたとする。どうすればいいのだろう? (なお、この記事では VM で CentOS 8 が動いていると仮定する) Vagrant で VM の設定を変更するのであれば、現時点でふたつの手がある。 Experimental なオフィシャルの機能を使うというのがひとつめ。この機能を使うには VAGRANT_EXPERIMENTAL="disks" という環境変数を設定した上で、Vagrantfile に config.vm.disk :disk, size: "100GB", primary: true というような記述を加えればよい。 もしくは vagrant-disksize というプラグインを使うという手もある。こちらを使うには vagrant plugin install vagrant-disksize というコマンドでプラグインをインストールし、config.disksize.size = "100GB" というような記述を Vagrantfile に追加する。 いずれかの手段をとった後、VirtualBox の GUI で VM の設定を眺めると次のようになる。 しかし、ここまでの操作では Linux が空きスペースをディスクとして割り当てない。例えば df -h コマンドを実行すると次のようになる。 [vagrant@ip-10-0-x-x ~]$ df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 1.9G 0 1. [Read More]

【読書メモ】リモートワークの達人

リモートワークの達人」を読んだ。「NO HARD WORK!」と同じく BasecampJason FriedDHH が書いた本である。

なぜ僕は Basecamp の創業者の本を読んでしまうのか…。だいぶ前に「小さなチーム、大きな仕事」を読んで、それに感銘を受けたからだろうな。過去にはそれに触発されて「僕も制約を受け入れ、副産物を売るぞ」という具合の記事を書いたりもした。

「NO HARD WORK!」についての記事を書いたときと同じく、Basecamp の主張をずっと読んできた身としては特に新しい話はなかった。自分は Basecamp のファンではあるけど、頷きづらいところもあった。たとえば「本当に集中したいときにオフィスに行こうという者はほとんどいない」という主張には「そうでもないんじゃないか」と思った。僕が「小さなチーム、大きな仕事」を読んでいた頃は独身で、こういう主張には頷かされたけど、家庭で乳幼児を育てている身としては、家よりオフィスの方がだいぶ集中できる。リモートワークの恩恵を受けられるのは、そういう家庭環境にある者だけだ。

今の職場では、東京都の緊急事態宣言に応じて「消極的にリモートワークを導入している」という感じだ。みな「一時的に」リモートワークをしているという認識なので、さまざまなほころびが出ている。具体的に言えばマイクの音質のせいでミーティングの音声が聞きづらかったり、オフィス側とリモート側で情報格差が出たりという具合だ。本書ではリモートワーカーの割合が低いとリモートワーカーは「少数派」になるので意識的にケアしようという主張がある。まったくだ。しかし、こういう意見は会社全体としてのコンセンサスがなければ通らない。消極的なリモートワーク導入では改善も難しかろう。「本を読んで翌日から実践」というわけには中々いかない。

現職の消極的なリモートワーク導入を経験て思うのは「オフィスには行きたくないが自宅で働くのも難しい」ということだ。この本では「リモートワークは必ずしも自宅で働くことではない。コワーキングスペースやカフェなどで働いてもいいのだ」と主張している。僕も数年後にはそういう働き方をしていそうな気がする。ただし、その場合はリモートワークという働き方に積極的に投資をしている会社に移っているという前提がありそうだ。

fork (2) に関するあれこれ

こちらは「C 言語コンプレックスを払拭したいシリーズ」の派生記事である。 fork (2) の簡単なサンプル Linux では fork (2) を使ってプロセスを複製できる。fork() のプロトタイプは次の通りだ。 #include <unistd.h> pid_t fork(void); このシステムコールを実行すると、プロセスの情報が複製される。システムコールをコールしたプロセスは親と呼ばれ、複製されたプロセスは子と呼ばれる。fork() の返り値は親プロセスの場合は子プロセスの ID であり、子プロセスの場合は 0 である。 fork() を使うもっとも簡単なサンプルは次のようなものだろう。 #include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h> int main() { pid_t pid; pid = fork(); if (pid < 0) { fprintf(stderr, "fork(2) failed\n"); exit(1); } if (pid == 0) { printf("Hey, I'm a child process\n"); } else { int status; waitpid(pid, &status, 0); // 親は子を待つ必要がある printf("I spawned PID=%d, and it's done! [Read More]

Switch Role して aws コマンドを発行する方法

ある AWS アカウントから別な AWS アカウントに対して操作をするとき、AWS Console では Switch Role して操作できる。 これと同等の操作を AWS CLI で行う設定を紹介する。設定は $HOME/.aws/config と $HOME/.aws/credentials に記述する。 $HOME/.aws/config $HOME/.aws/config に次のような内容を追加する。 [profile another-project] role_arn = arn:aws:iam::012345678901:role/MyRoleToAssume source_profile = my-terraform 012345678901 は操作対象の AWS アカウントで、MyRoleToAssume は操作対象の AWS アカウントから引き受ける IAM ロールである。arn:aws:iam::012345678901:role/MyRoleToAssume は既に操作対象の AWS アカウント内のロールとして存在していると仮定している。 source_profile は AWS CLI のプロファイルである。ここでは my-terraform というプロファイルを使うと仮定する。なお my-terraform というプロファイル名から想像できるように、Terraform 専用の AWS アカウントから他の AWS アカウントの環境をプロビジョンするときなどに、この記事の内容が役に立つ。 $HOME/.aws/credentials $HOME/.aws/credentials には次のような内容を追加する。 [my-terraform] aws_access_key_id = AKIAXXXXXXXXXXXXXXXX aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX 特に変わったことはない。単に my-terraform が使う ACCESS KEY と SECRET ACCESS KEY を設定しているだけである。なお、前セクションで設定した $HOME/. [Read More]