Instant Potを使った簡単ほろほろチキンのスパイスカレー試作

※ "試作" とタイトルに入れた通り、出来上がりにはあまり満足していない。 鶏肉はホロホロになったものの、味がしっかりしみておらず、カレー全体としても塩っ気が足りない気がした。

  • 鶏肉を圧力鍋にかけて柔らかくしつつ鶏のスープを作り、それにスパイスカレーの素を加えればお手軽にほろほろチキンのカレーができあがるのでは?
  • 鶏肉に軽く焼き目をつけて圧力をかける
  • スパイスカレーの素を作る
  • 圧力をかけた鶏肉を入れる
  • できました

うちでは Instant Potがかなり活躍している。 鶏肉(またはウィンナー、ベーコン)・キャベツ・じゃがいも入れてコンソメキューブを入れて圧力をかければサクッと野菜スープ(ないしポトフ)ができあがる。 野菜がドロッドロになるけど僕はこれくらいが食べやすくてすき。このスープを週1~2で食べるようになったら体重が2~3キロ減った。

ところで本日 1/22はカレーの日らしい。

www.curry.or.jp

ということで

鶏肉を圧力鍋にかけて柔らかくしつつ鶏のスープを作り、それにスパイスカレーの素を加えればお手軽にほろほろチキンのカレーができあがるのでは?

と思いやってみた次第。

これまでに何度もスパイスカレーを作ってきたものの、実はあまり安定して満足のいくものが作れていない。できるだけ簡単に、かつ再現性の高いレシピを目指したい。

いろいろなレシピを試してみたけど、最近はこちらの作り方を参考にしている。

note.com

あとはこちらも。

www.hotpepper.jp

続きを読む

Ruby 2.5.0コンテナでRails6の開発環境を作るときのトラブルシューティング

こちらのハンズオンをやっていたところ、いくつかの問題に遭遇したので対処法をまとめておく。

Rails アプリケーションをコンテナで開発しよう ! 第 1 回 - まずは Rails アプリケーション作りから

Rails7のインストールに失敗する

記事では Ruby2.5 & Rails6 を使用しているが、現時点(2022/1)での最新版は 7.0.1。 エラーメッセージにもあるように7.0.1 ではRuby2.7以上が必要であるため gem install railsに失敗する。

root@810c33297af8:/work# gem install rails
Fetching: concurrent-ruby-1.1.9.gem (100%)
Successfully installed concurrent-ruby-1.1.9
Fetching: i18n-1.8.11.gem (100%)
Successfully installed i18n-1.8.11
Fetching: tzinfo-2.0.4.gem (100%)
Successfully installed tzinfo-2.0.4
Fetching: activesupport-7.0.1.gem (100%)
ERROR:  Error installing rails:
    There are no versions of activesupport (= 7.0.1) compatible with your Ruby & RubyGems. Maybe try installing an older version of the gem you're looking for?
    activesupport requires Ruby version >= 2.7.0. The current ruby version is 2.5.0.

gem install のオプションでRailsのバージョンを指定してインストールすることとした。

root@810c33297af8:/work# gem install -v 6.0.3.2 rails

Nokogiriのインストールに失敗する

さて、Railのバージョン指定をして改めてgem installを実施したところ、

root@810c33297af8:/work# gem install -v 6.0.3.2 rails
...
Fetching: activesupport-6.0.3.2.gem (100%)
Successfully installed activesupport-6.0.3.2
ERROR:  While executing gem ... (Gem::RemoteFetcher::FetchError)
    bad response Forbidden 403 (https://api.rubygems.org/quick/Marshal.4.8/nokogiri-1.13.0-x64-unknown.gemspec.rz)

Nokogiri 1.13.0のインストールに失敗している。 403なのでライブラリが不足している的なやつではないみたい。

rubygems.org でNokogiriの過去バージョンを調べて 1.12.5 を予めインストールすることで解決。

f:id:jacoyutorius:20220108065847p:plain

root@810c33297af8:/work# gem install nokogiri -v 1.12.5
Fetching: nokogiri-1.12.5-x86_64-linux.gem (100%)
Successfully installed nokogiri-1.12.5-x86_64-linux
1 gem installed
root@810c33297af8:/work# gem install -v 6.0.3.2 rails
Fetching: loofah-2.13.0.gem (100%)
Successfully installed loofah-2.13.0
Fetching: rails-html-sanitizer-1.4.2.gem (100%)
Successfully installed rails-html-sanitizer-1.4.2
Fetching: rails-dom-testing-2.0.3.gem (100%)
Successfully installed rails-dom-testing-2.0.3
Fetching: builder-3.2.4.gem (100%)
Successfully installed builder-3.2.4
Fetching: erubi-1.10.0.gem (100%)
Successfully installed erubi-1.10.0
Fetching: actionview-6.0.3.2.gem (100%)
Successfully installed actionview-6.0.3.2
Fetching: actionpack-6.0.3.2.gem (100%)
Successfully installed actionpack-6.0.3.2
Fetching: activemodel-6.0.3.2.gem (100%)
Successfully installed activemodel-6.0.3.2
Fetching: activerecord-6.0.3.2.gem (100%)
Successfully installed activerecord-6.0.3.2
Fetching: globalid-1.0.0.gem (100%)
Successfully installed globalid-1.0.0
Fetching: activejob-6.0.3.2.gem (100%)
Successfully installed activejob-6.0.3.2
Fetching: mini_mime-1.1.2.gem (100%)
Successfully installed mini_mime-1.1.2
Fetching: mail-2.7.1.gem (100%)
Successfully installed mail-2.7.1
Fetching: actionmailer-6.0.3.2.gem (100%)
Successfully installed actionmailer-6.0.3.2
Fetching: nio4r-2.5.8.gem (100%)
Building native extensions. This could take a while...
Successfully installed nio4r-2.5.8
Fetching: websocket-extensions-0.1.5.gem (100%)
Successfully installed websocket-extensions-0.1.5
Fetching: websocket-driver-0.7.5.gem (100%)
Building native extensions. This could take a while...
Successfully installed websocket-driver-0.7.5
Fetching: actioncable-6.0.3.2.gem (100%)
Successfully installed actioncable-6.0.3.2
Fetching: mimemagic-0.3.10.gem (100%)
Building native extensions. This could take a while...
Successfully installed mimemagic-0.3.10
Fetching: marcel-0.3.3.gem (100%)
Successfully installed marcel-0.3.3
Fetching: activestorage-6.0.3.2.gem (100%)
Successfully installed activestorage-6.0.3.2
Fetching: actionmailbox-6.0.3.2.gem (100%)
Successfully installed actionmailbox-6.0.3.2
Fetching: actiontext-6.0.3.2.gem (100%)
Successfully installed actiontext-6.0.3.2
Fetching: thor-1.2.1.gem (100%)
Successfully installed thor-1.2.1
Fetching: method_source-1.0.0.gem (100%)
Successfully installed method_source-1.0.0
Fetching: railties-6.0.3.2.gem (100%)
Successfully installed railties-6.0.3.2
Fetching: sprockets-4.0.2.gem (100%)
Successfully installed sprockets-4.0.2
Fetching: sprockets-rails-3.4.2.gem (100%)
Successfully installed sprockets-rails-3.4.2
Fetching: rails-6.0.3.2.gem (100%)
Successfully installed rails-6.0.3.2
29 gems installed

CloudWatch Rumを試す

今開催されているAWS re:Invent2021 にて、CloudWatchの新機能が発表された模様。

aws.amazon.com

CloudWatch RUM(Real-User monotoring) はWebアプリケーションのログやエラー、アクセスしているユーザーの情報をモニタリングすることができる様子。

ざっくり言えばAWSGoogleアナリティクスって感じですか。

先月までAmplifyアプリケーションからCloudWatchLogsにログを送る方法を四苦八苦していたのですが、この CloudWatch RUMがあればその必要も無さそうな気がしてきた。。

で、簡単に試してみました(手間なので設定の仕方はいちいち書きません。。)

強いて言えば、RUMにデータを送るためのIdentityPoolを作るときに一緒に作成されるIAMロールに対してRUMへイベントを送ることを許可してあげる必要があるくらい。

f:id:jacoyutorius:20211201222638j:plain
アプリケーションからRUMにデータを送るためのIdentityPoolの設定

IdentityPoolに紐付けられているIAMロールに対してrum:PutRumEvents アクションを許可してやります。

f:id:jacoyutorius:20211201222845j:plain
こんな感じで

あとは作成された Javascriptスニペットをアプリケーションのindex.htmlの header内に貼り付けてデプロイしてやるだけです。

f:id:jacoyutorius:20211201223153j:plain
権限が適切に付与されていない場合はこんな感じのエラーがでます

CloudWatch RUMの画面で見れるデータ。だいたいGoogleアナリティクスと似たようなデータが取れている気がする。。?(GAあんまし使ったことないけど)

f:id:jacoyutorius:20211201223922j:plain

f:id:jacoyutorius:20211201224245j:plain

ところでログが取れるようになってもアプリケーションのコンソールに色々エラーが出るんだけど大丈夫なのかな。

f:id:jacoyutorius:20211201224712j:plain
不穏だ

ちなみに↓のアプリケーションに組み込んだのでぜひぜひアクセスしていただいて、ログを収集するのに協力していただければと思います。

webspeechtranslate.yutoogi.com

ところでこのアプリケーションですが、先日開催された JAWS Pankration 2021にて開発について発表したのでした。

jawspankration2021.jaws-ug.jp

speakerdeck.com

AmplifyでデプロイしたアプリケーションからCloudWatchLogsにログを送る方法について話したんですけど冒頭に書いたとおり、CloudWatch RUMがあれば本番稼働しているアプリケーションのログ収集が楽勝でできそうで、この発表で話したようなことを頑張らなくても大丈夫になりそうです。

Amplify Logger から CloudWatchLogsに送信する の補足、或いはAmplifyで未ログイン状態でもAWSリソースを操作したいときの覚書

Amplifyを組み込んだアプリケーションからCloudWatchLogsにログイベントを送信するには amplify add auth で認証関連の機能を組み込んでログ送信用のIAMロールを作る必要があると書いた。

jacoyutorius.hatenablog.com

amplify add authを実行すると対話的に認証設定ができるのだけど、デフォルトの設定だけでは未ログインのときにはAWS側の操作ができない状態になるので このコマンドによって生成されたamplify ディレクトリ配下のファイルを一箇所書き換えてあげる必要がある。

認証機能をつけない場合はだいたい適当に答える感じでOK。

ddd4143c63e0:/workspaces/amplify-dev# amplify add auth
Using service: Cognito, provided by: awscloudformation
 
 The current configured provider is Amazon Cognito. 
 
 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Email
 Do you want to configure advanced settings? No, I am done.
Successfully added auth resource amplifyapp locally

Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
$  tree amplify 
amplify
├── backend
│   ├── amplify-meta.json
│   ├── auth
│   │   └── amplifyapp1122334455
│   │       ├── amplifyapp1122334455-cloudformation-template.yml
│   │       └── parameters.json   # これをいじる

この parameters.jsonallowUnauthenticatedIdentitiestrue に書き換える。

{
    "identityPoolName": "amplifyapp1122334455_identitypool_00aabbcc",
    "allowUnauthenticatedIdentities": true, 
    "resourceNameTruncated": "amplifyapp1122334455",
    "userPoolName": "amplifyapp1122334455_userpool_00aabbcc",
    "autoVerifiedAttributes": [
        "email"
    ],

この変更をしてから amplify push を実施すると以下のようにフェデレーテッドアイデンティティが作成される。

f:id:jacoyutorius:20211104054355j:plain
認証されていないIDのところ

これでログインしていなくてもAWS側のリソースを扱うことができるようになる。

もしAuth関連のリソースが作成済の場合は amplify update auth を実行し、Walkthrough all the auth configurations を選んで

Allow unauthenticated logins? (Provides scoped down permissions that you can control via AW S IAM)Yes にする。

その他

どのファイルで設定しているのかわからなくてdiffで頑張って調べました。

f:id:jacoyutorius:20211104055714j:plain

Amplify Logger から CloudWatchLogsに送信する

Amplify Logger というのだから、ただのログ出力じゃなくて CloudWatchLogsにいい感じインテグレーションしてくれるものと思っていたら全然そんなことはなかった。

通常の使い方は前回の記事を見てみてください。

jacoyutorius.hatenablog.com

で、issueを漁ってみたら同じことを考えている人はいて、AWSCloudWatchProvider を通してAmplify Loggerでログを出すだけで CloudWatchLogsにログを飛ばしてくれるようになるプルリクエストがあって、既にマージされていた。

github.com

マージされてはいるものの、公式のドキュメントには何も記載は無かったのでプルリクエストのコードとかコメントを読みつつ試してみた(ちなみに、かなり手間取った)

手順など

その前に余談

Amplify で Storage とか Geo を追加するときに、一緒に Auth関連のリソースも作らされるの、何でなんだろう?って思ってたんだけど、AmplifyのアプリケーションからAWSのリソースを操作するためのロールが必要だから一緒に作られるんですね。 なので、ログイン機能とかが不要な場合は後述する unauthRole だけ見ておけばいい。

(多分必要)ログ送信用のIAMロールを作る

amplify add auth で認証情報を作る。ログイン機能とかは付けないので、認証情報に関する問いには雑に回答して大丈夫。

XXXX-authRoleXXXX-unauthRole の2つのロールが作られる。認証していなくてもログを送信したいので、コンソールから unauthRole に以下のロールを付与する。 .amplify 配下に生成される parameters.json をいじればロールも一緒に登録できそうだけども、今回はマネジメントコンソールから登録した。

  • DescribeLogGroups
  • DescribeLogStreams
  • CreateLogGroup
  • CreateLogStream
  • PutLogEvents
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

アプリケーションに Amplify Loggerを組み込む

プルリクのコメント欄にサンプルコードが記載されてたのでそれを参考に。

import { Amplify, Logger, AWSCloudWatchProvider } from 'aws-amplify';
import awsconfig from './aws-exports';

Amplify.configure({
  Logging: {
    logGroupName: 'app-logs',
    logStreamName: `${process.env.VUE_APP_ENV}_LOGS`,
  },
  ...awsconfig
});

const amplifyLogger = new Logger('app-logs', "INFO");
Amplify.register(amplifyLogger);
amplifyLogger.addPluggable(new AWSCloudWatchProvider());

ログを送信する

amplifyLogger.info("hello world!!");

これで送信されるはずなのだけど、こんなエラーになる。

Failed to load resource: the server responded with a status of 400 (Bad Request)
ConsoleLogger.js?7aaf:127 [ERROR] 31:13.887 AWSCloudWatch - failure during log push: InvalidParameterException: 1 validation error detected: Value '' at 'sequenceToken' failed to satisfy constraint: Member must have length greater than or equal to 1

sequenceToken がブランクなのでエラーになっている様子。

CloudWatchEventsにログを送信する場合は、sequenceTokenをパラメータに含めることでログの連続性を保つ仕組みになっているみたい。

この sequenceToken の解決自体は AWSCloudWatchProvider でやってくれているようなのだけど、最初のログ送信に失敗してしまう。

プルリクのコメントを見てみると同じ問題に遭遇した人がいて、曰く

After adding an event to the stream manually, the sequenceToken value was populated correctly and subsequent log calls worked without issue. 

ログストリームの中身が空なのが良くないみたい。

ということで、マネジメントコンソールから適当なログイベントを一個登録してみた。

このあとアプリケーションからログを出力してみると・・・!

f:id:jacoyutorius:20211029074929p:plain
1行目の 「Hello!」ってログがマネジメントコンソールから登録したやつ

ここまで長かった。。。

まとめ

AmplifyからカジュアルにCloudWatchLogsにログを送ることができるようになるとアプリケーションの監視やデータ分析がかなり便利になると思う。

エラーの収集はもとより、ユーザーの操作履歴などを CloudWatchLogs => S3 に溜めておいてS3 SelectとかAthenaで分析するみたいな使い方ができると絶対楽しい。

(ユーザーの行動分析は amplify analytics があるけど、あれは Amazon Pinpointとのインテグレーションなので、CloudWatchにログを飛ばしてざっくり検証してみたいな〜みたいのとは使い所が異なるという認識です)

Amplify Loggerの使い方について

AWS Amplifyの utilitiesに loggerがある。

https://docs.amplify.aws/lib/utilities/logger/q/platform/js/

使い方

import { Logger } from 'aws-amplify';

const logger = new Logger("my-logger");
logger.warn("warning message");

デバッグコンソールにはこのように出力される。

[WARN] 56:32.69 my-logger - warning message

注意点としては、インスタンスに指定されているレベル以上のログしか出力されないということ。 ログレベルは上から順に以下のようになっている。

  • ERROR
  • WARN
  • INFO
  • DEBUG
  • VERBOSE

デフォルトのログレベルはWARN。 例えば、以下のようなloggerがある場合、WARNERRORのログでないと出力されないので logger.info を実行してもログは出力れない。

import { Logger } from 'aws-amplify';

const logger = new Logger("my-logger");
logger.info("this is info message");  // これはconsoleに出力されない

INFOレベルのログを出したい場合は以下のようにインスタンス生成時にログレベルを指定しておく必要がある。

import { Logger } from 'aws-amplify';

const logger = new Logger("my-logger", "INFO");
logger.info("this is info message");  // これならconsoleに出力される
続きを読む

AWSアクセスキーのコミットされたリポジトリが公開されているのを検知すると『AWSCompromisedKeyQuarantineV2』というロールが付与される

先日誤ってアクセスキーがコード中にベタ書き状態のコミットがあるのを忘れていて(修正したコミットが最新だったのよ。。) Githubにpushしたところ、すぐさまAWSGithubから注意メールが届きまして。

で、 AWSのCloudTrailで不正な操作がないか調べていたところ、そのIAMユーザーにポリシーを付与するという身に覚えのない操作をしている履歴があり。

続きを読む