AWS RDS には IAM 認証を使って接続する機能があります。
MySQL および PostgreSQL に対する IAM データベース認証 IAM 認証情報を使用して Amazon RDS への接続をユーザーに許可する方法を教えてください。 これを使って接続するGo言語のSQLドライバを書いてみました。
https://github.com/shogo82148/rdsmysql 使い方 IAMデータベース認証はデフォルトで無効になっているので、まずはこれを有効化します。 次に AWSAuthenticationPlugin を認証方式に指定して、新しいユーザーを作りましょう。
IAM データベース認証の有効化と無効化 データベースアカウントの作成 CREATE USER jane_doe IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; 他のSQLドライバはimportするだけで使えるのですが、 rdsmysqlではAWSへの権限情報を設定しなければならない都合上、 sql.Register を自前で呼び出す必要があります。 とは言っても、AWS SDKがいい感じに設定ファイルとか環境変数とか読んでくれるので、 rdsmysql.Driver にAWSセッションを渡すだけです。
c := aws.NewConfig().WithRegion("ap-northeast-1") s := session.Must(session.NewSession(c)) d := &Driver{ Session: s, } sql.Register("rdsmysql", d) db, err := sql.Open("rdsmysql", "jane_doe:@tcp(db-foobar.ap-northeast-1.rds.amazonaws.com:3306)/") if err != nil { log.Fatal(err) } defer db.Close() あとは通常のMySQLドライバとして呼び出すだけです。 go-sql-driver/mysql のラッパーになっているので、 DNS等の書き方はこれに準じます。 認証部分は rdsmysql がやってくれるので、パスワードは空でOKです。 パスワードの管理から開放されて楽ですね!
この記事は Perl Advent Calendar 2018の15日目の記事です。 (キリの良いところまでできたのと、記事が書かれていなかったので代打投稿)
Custom Runtime のリリースにより、AWS Lambda 上でPerlが動くようになりました。
PerlをAWS Lambdaで動かす 次は AWS Lambda + CGI でサーバーレスだな...
— Ichinose Shogo (@shogo82148) 2018年12月8日 ということで、やっていきましょう。
できたもの 動かすのはもちろん、 CGIアクセスカウンター 。 なんと嬉しいことに、最近になって WwwCounter の新バージョン(Ver3.16)がリリースされ、 Perl 5.26 に対応しました!
2018-11-11 perl 5.26に対応。(Ver3.16)
更新履歴によれば一つ前の Ver 3.15 のリリースは2003-03-23なので、なんと15年ぶりのアップデートです。 杜甫々さんの AWS Lambda で動かしてくれ!! という声が聞こえてきそうですね・・・!!!
動いたーーーー!!!!
実装はこちら
AWS::Lambda ちなみにWwwCounterのアップデートはPerl 5.26で「@INCからカレントディレクトリが削除」された件への対応だと思います(コミットログがないので予想)。
第46回 Perl 5.26で変わること(1) - Perl Hackers Hub 実装説明 「そもそもCGIってなんだ?」っていう人も多くなってきたと思うので、そこらへんの歴史の話にも軽く触れます。 この辺の歴史をリアルに体験したわけではないので、誤り等あればご指摘ください。
CGIとは Common Gateway Interface の略で、 WebサーバーとCLI(Command Line Interface)アプリケーションのやり取りの方法を決めた規格です。
AWS Lambda で Custom Runtime が発表されました!
新機能 – AWS Lambda :あらゆるプログラム言語への対応と一般的なコンポーネントの共有 New for AWS Lambda – Use Any Programming Language and Share Common Components AWS Lambda Now Supports Custom Runtimes, and Enables Sharing Common Code Between Functions Custom Runtime により好きなプログラミング言語でLambda関数を書くことができ、 いくつかの言語についてはAWSおよびパートナーから bootstrap が提供されます。
提供される言語にCOBOLが入って話題になっていますが、 当然ながら(?)Perlはありません。
Custom Runtimeは shell script でも書ける簡単なものなので、Perlでも書いてみました。
Perl in AWS Lambda 以下のスクリプトを bootstrap という名前で保存します。
#!/usr/bin/env perl use utf8; use warnings; use strict; use lib "$ENV{LAMBDA_TASK_ROOT}/local/lib/perl5"; use Furl; use JSON; my $furl = Furl->new; my ($handler, $function) = split /\.
@Linda_pp さんのツイートをみて
Go 言語の nil って NilLit じゃなくて Ident "nil" としてパースされるのか.それで気付いたけど nil := 42 みたいに普通に変数宣言できる(unused でエラーになるけど)
— ドッグ (@Linda_pp) 2018年11月22日 なるほど、これは面白い。 と少し遊んでみたメモ。
言語仕様にある通り、Goのキーワードは以下の25個です(Go1.11.2)。
break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var この一覧に nil や true, false は入っていません。 これらは builtinという扱いになっており、識別子として利用可能です。
そのため、変数名等に利用可能というわけですね。面白い。
package main import ( "fmt" ) func main() { nil := 42 fmt.Println(nil) // Output: // 42 } 以下、色々遊んでみた例。
必要に迫られて作りました。 PHPでエンコードしたJSONをいい感じにデコードしてくれるGoのパッケージです。
shogo82148/go-phper-json 背景 さて、PHPerの方々には当たり前のことかもしれませんが、PHPの言語仕様について少しおさらいです。 それがどうしてGoで問題になるか見ていきます。
PHPのarray問題 PHPはとても便利なプログラミング言語なので、配列を扱うことができます。 ここでPHPの配列のマニュアルを読んでみましょう。
http://php.net/manual/ja/language.types.array.php
PHP の配列は、実際には順番付けられたマップです。マップは型の一種で、 値をキーに関連付けます。 この型は、さまざまな使い道にあわせて最適化されます。 配列としてだけでなく、リスト (ベクター)、 ハッシュテーブル (マップの実装の一つ)、辞書、コレクション、スタック、 キュー等として使用することが可能です。 PHP の配列には他の PHP 配列を値として保持することができるため、 非常に簡単にツリー構造を表現することが可能です。 (強調部分は筆者によるもの)
重要なことなのでもう一度。
配列としてだけでなく、リスト (ベクター)、 ハッシュテーブル (マップの実装の一つ)、辞書、コレクション、スタック、 キュー等として使用することが可能です。
他の言語でリスト、ハッシュテーブル、辞書等と呼ばれているものは、PHPにおいてはいずれも配列です。 PHPにとっては、整数を添字にしているか、文字列を添字にしているかの違いでしかありません。 (PHP7.xから整数が添字の場合に最適化が入るようになったらしいけど、大きな挙動の変更はないはず)
そのため、以下のスクリプトは true を返します。
<?php $a = array("apple", "banana"); $b = array(0 => "apple", 1 => "banana"); var_dump($a == $b); // bool(true) この仕様のため、JSONにエンコードすると最初は配列だったのに、 処理を進めていくうちにうっかり文字列のキーを作ってしまって、 JSONのオブジェクトに変わってました、ということが起こりえます。 Goにおいて両者は全く違う型なので、デコードの際に非常に困ります。
<?php $a = array(1, 2, 3); print json_encode($a); // [1,2,3] $a["foo"] = "bar"; print json_encode($a); // {"0":1,"1":2,"2":3,"foo":"bar"} このような悲劇を防ぐために、 JSON_FORCE_OBJECT というオプションがあるのですが、 オプションの名前通りに全部JSONのオブジェクトになってしまいます。 この要素だけJSONの配列にして欲しい!といった細かな操作はできません。
僕は知っています。
ぜひ、みなさんもお手元の電波時計で試してみてください!
と書いても、試してくれる人なんていないことを。
僕は知っています。
説明書や仕様書に書いてあったとしても、書いてあるとおりに動作する機械なんて、ほんの一握りだということを。
というわけで、楽しい夏休みの自由研究です。 秋葉原で適当に買った1000円から3000円くらいの電波時計に、サマータイムのフラグを有効にした電波を受信させてみて、どういう挙動になるか調査してみました。
TL;DR 10機種(SEIKO, CITIZEN, CASIO, MAG, ELECOM, その他)に対して、サマータイムフラグを有効にした状態で Web JJY の電波を送信しました。
今回の調査範囲では、夏時間の時刻(1時間 or 2時間ズレた時刻)を表示する時計は見つからなかった 夏時間実施中(DST)と表示 する時計は実在する 室内で使うならCASIOの電波時計はクオーツ時計だと思ったほうがいい 電波受信の様子をYouTubeにあげておいたので興味のある方はどうぞ。
背景 2018年、日本は記録的な猛暑に見舞われ、 観測史上最高の気温41.1度を記録し、 熱中症とみられる症状で90人以上が亡くなるという甚大な被害を被った。
今週の天気 記録的な猛暑 底知れぬ暑い夏 日本で猛暑 気温41.1度で観測史上最高 気象庁「災害と認識」熱中症死の疑い6日で90人超 この記録的猛暑を受け、政府・与党によって2020年の東京五輪・パラリンピックの酷暑対策として、夏の期間だけ時間を2時間繰り上げる「サマータイム(夏時間)」の導入が検討されている。
酷暑対策でサマータイム導入へ 秋の臨時国会で議員立法 31、32年限定 これに対して、「電波時計が狂うのではないか」「日本中の電波時計がゴミになる」等、電波時計が正しい時刻を示さなくなるとの指摘が相次いでいる。
サマータイム導入で「電波時計が狂う」? メーカーに聞いた サマータイムで日本中の電波時計がゴミになる(かも)という話 電波時計は、NICT(情報通信研究機構)が提供している標準電波(JJY)を受信し、時刻の同期を行っている。 この標準電波には、時、分、通算日、年、曜日といったタイムコード情報に加え、 将来の拡張性のための「予備ビット」が設けられている。 この予備ビットに関して、「標準電波の出し方について」には、夏時間情報として意味を持たせる場合の例が記載されているが、これはあくまでも例であり、告示などで正式に決まっているものではない。 しかし、現実に市販されている電波時計のなかにも、仕様上予備ビットの状態を認識する機種がする。
標準電波の送信周波数40kHzを提供する「おおたかどや山標準電波送信所」は1999年6月運用開始、送信周波数60kHzを提供する「はがね山標準電波送信所」は2001年10月運用開始である。 日本でサマータイムが導入されたのは1948年から1951年の期間だけなので、 今後サマータイムが導入されることとなれば、標準電波の運用が始まってから初のサマータイム導入となる。
夏時刻法 - Wikipedia 長波帯標準電波施設 パンフレット(PDF) そのため、仕様上はサマータイムへ対応している電波時計であっても、初のサマータイム実施によって未知の挙動を示すことが十分に想定される。 そこで、本記事では、実際にサマータイム実施中の電波を電波時計に受信させ、 どのような挙動を示すのかを明らかにする。
目的 2018年8月現在日本で市販されている電波時計が、サマータイムの情報を含んだ標準電波(JJY)を受信した場合の挙動を調査し、 仮に、2019年、2020年にサマータイムが導入された場合の影響を明らかにする。
実験方法 秋葉原で購入した以下の電波時計に対して、標準電波と同様の電波を送信し、時刻の同期を行う。
CITIZEN 8RZ152 CITIZEN 4RL432-019 SEIKO SQ698S SEIKO KR331W MAG T-694 SM-Z ELECOM CLK-DD001RD 京都大和 171038 (製造元不明) 31756 CASIO DQD-710J-8JF CASIO TTM-160NJ-8JF 電波の送信には、Samsung Galaxy Note8 SC-01K を用いて、JJYシミュレータWeb版を実行する。
もうすぐリリースのGo1.11ではWebAssemblyのサポートが予定されています。 (2018/08/19現在の最新版はGo1.11rc1)
Go言語がWebAssemblyをサポートへ。GOARCHは「wasm」、GOOSは「js」に 正式リリース前に少し遊んでみようということで、@yuroyoroさんのGoAst ViewerをWebAssemblyへビルドしてみました。
GoAst Viewer WebAssembly Version shogo82148/goast-viewer JavaScriptの連携方法 コードをASTに変換し、JSONとしてエンコードする部分(ast.go)に関しては、一切変更しなくても動きました。素晴らしい。
ただし、さすがにブラウザ上でHTTPサーバーは動かない(そういえば試してないけど、動かないよね??)ので、JavaScriptとの連携部分を実装してあげる必要があります。 syscall/jsパッケージはまだ実験段階というステータスで機能が限られているので、 連携には少し工夫が必要です。
JavaScriptからGoの関数を呼ぶ JavaScriptからGoの関数を呼ぶには window にコールバック関数として必要な関数を登録します。
// GoASTParse 関数を定義(Go言語) js.Global().Set("GoASTParse", js.NewCallback(func(args []js.Value) { source := args[0].String() // ...ASTへの変換処理... })) 戻り値をGoからJavaScriptへ返す js.NewCallback なのですが、もともとは addEventListener にわたすコールバック関数なので、 関数の戻り値を受けわたす方法がありません。 回避方法はいろいろあるでしょうが、今回はコールバック関数の引数にコールバック関数指定してもらうことにしました。
// GoASTParse 関数を定義(Go言語) js.Global().Set("GoASTParse", js.NewCallback(func(args []js.Value) { source := args[0].String() // ...ASTへの変換処理... args[1].Invoke(string(body)) })) // GoASTParseを呼び出す(JavaScript) GoASTParse("package main; func main() {}", function(body) { // ASTの表示処理 }) まとめ Goのバイナリ全般に言えることですが、WASMになってもやっぱりサイズが大きい(3.5M)。 今後のパフォーマンス向上に期待です。
GoよりAngulerJSの方が難しかったʕ ゚皿゚ ʔ
サマータイムなんて日本人には関係ないと思っていた時期が僕にもありました。 ところが何やら日本にもサマータイムがやってくる動きがあるようです。
酷暑対策でサマータイム導入へ 秋の臨時国会で議員立法 31、32年限定 さて、長波JJY(市販の電波時計のための電波)には夏時間の情報が含まれています。 「将来の拡張性のための予備ビット」という扱いなので、対応している時計なんてないだろう、と思っていたら、 なんと対応している時計が存在しているらしいということを知りました。
その事実を確かめるため、Webブラウザを使って電波を出してみたで紹介した JJYシミュレータWeb版に夏時間を有効にするチェックボックスを追加しました。
CITIZEN 8RZ152 の動作例 夏時間への同期、完了しました 😂😂😂 pic.twitter.com/3tMcCYdXpP
— Ichinose Shogo (@shogo82148) 2018年8月9日 念の為書いておきますが、今は午前8時です
— Ichinose Shogo (@shogo82148) 2018年8月9日 DST(Daylight Saving Time)の表示が出て、夏時間に切り替わったことがわかりますが、なぜか6時間もズレています・・・。
もう、こんな時間だ……そろそろ寝よう……
???お前24時間表記だっただろ?どうしたんだ???
(今は20時です) pic.twitter.com/8PViLOaj85
— Ichinose Shogo (@shogo82148) 2018年8月10日 悲報 11日を迎えることができず pic.twitter.com/pw0k0Qo8RY
— Ichinose Shogo (@shogo82148) 2018年8月10日 もはや数字ではないものが出てきた。
まとめ 夏時間に対応した電波時計の存在は事実でした。 しかし、機種によっては挙動がおかしくなるようです(N=1)。
ぜひ、みなさんもお手元の電波時計で試してみてください!
JJYシミュレータWeb版 ※ 利用の結果生じた損害について、一切責任を負いません。
参考 標準電波の出し方について 酷暑対策でサマータイム導入へ 秋の臨時国会で議員立法 31、32年限定 Webブラウザを使って電波を出してみた サマータイムで日本中の電波時計がゴミになる(かも)という話 サマータイム導入で「電波時計が狂う」? メーカーに聞いた 「サマータイム導入はコンピュータシステム的に難あり」は本当か サマータイム実施は不可能である from UEHARA, Tetsutaro 僕もサマータイム実施は不可能だと思います・・・。
S3からファイルを落とすだけのツールを作りました。
s3cli-mini 目的 流行りのCD(継続的デリバリー)を実践するために、専用のデプロイツールをダウンロードする目的で作りました。
主なデプロイ先はAWSなので、デプロイ操作には awscli が必要です。 しかしCDに使用しているCircleCIが公式に提供しているコンテナイメージにはawscliがインストールされていません。 もちろん apt-get install awscli であとからインストールすることは可能ですが、そのぶんジョブの実行時間が長くなってしまいます。 また、インストールされる awscli のバージョンが古く、ローカル環境ではうまく動くけど、 CircleCI上では最新の機能が使えず失敗するということがありました。
そこでもう awscli を使うことは諦めて、Goで AWS API を叩いてデプロイするバイナリを作ってしまうことを考えました。 Goであればシングルバイナリでインストール可能で、CI/CD環境とローカルでバージョンが一致せず悩まされることはありません。 また並行処理が得意なので、デプロイの時間短縮も図れます。
しかし、このデプロイ用のバイナリをどこに置くか・・・プロジェクト固有の処理が入っているので外部には公開したくない。 かといってプライベートなS3バケットに置くと、ダウンロードに awscli が必要になってしまう・・・。 awscli を使うのは諦めたはずでは・・・という、いわゆる「鶏が先か、卵が先か」問題に陥ってしまいました。
そこでS3からのダウンロードの処理に特化したミニawscliが欲しくなって作成したのが s3cli-mini です。
使い方 現状v0.0.1でサポートしているのは cp コマンドのみです。 S3バケットからファイルをダウンロードしたり、S3バケットへファイルをアップロードしたり、 別のS3バケットへファイルを転送することができます。
# download from a S3 bucket s3cli-mini cp s3://your-bucket/foobar.zip . # upload to a S3 bucket s3cli-mini cp foobar.zip s3://your-bucket/ # copy the file from a S3 bucket to another S3 bucket.
Goの http.Transport には RegisterProtocol というメソッドが生えていて これを使うと、 HTTP以外のプロトコルを透過的に扱うことができます。 代表的なのは http.NewFileTransport で、これを使うと、file://path/to/file.txt みたいなURLでファイルにアクセスすることができます。 (Goオフィシャルの例) この仕組を使って、S3へのアクセスも透過的にできるようにしてみたので、メモ。
新しいプロトコルを作成するのは非常に簡単です。 http.RoundTripperインターフェースを実装し、リクエストに応答するレスポンスを作ってあげればいいだけです。 S3の場合以下のようになります。(エラー時の扱いが雑だけど・・・)
package main import ( "net/http" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" ) type s3RoundTripper struct { s3 *s3.S3 } func newS3RoundTripper(session *session.Session) http.RoundTripper { return &s3RoundTripper{ s3: s3.New(session), } } func (rt *s3RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { host := req.Host if host == "" { host = req.URL.Host } path := req.URL.Path ctx := req.Context() out, err := rt.