ServerlessFrameworkでdeployを成功させるまでに嵌ったことまとめ
環境
OS: linux Node Version: 8.12.0 Serverless Version: 1.32.0 Python Version: 3.6
本題
$ sls deploy -v
を実行時に発生したエラーで、個人的に解決まで時間がかかったものを書く
The security token included in the request is invalid.
Serverless Error --------------------------------------- ServerlessError: The security token included in the request is invalid.
~/.aws/credentials
に記載のaws_access_key_id
とaws_secret_access_key
の記述が間違ってた
⇒ vim
で手動で書いたためミスした
⇒ sls config credentials --provider aws --key XXXKEYXXX --secret XXXSECRETXXX
とコマンドから発行すれば解決した
User is not authorized to perform: cloudformation:DescribeStacks on resource: arn:aws:cloudformation
Serverless Error --------------------------------------- ServerlessError: User: arn:aws:iam::XXXXXXXXXX:user/(user名) is not authorized to perform: cloudformation:DescribeStacks on resource: (省略)
同じエラーメッセージに出会った人はいるらしい。
cloudformation:CreateStack cloudformation:DescribeStacks cloudformation:DescribeStackEvents cloudformation:DescribeStackResources
cloudformationに関しては、けっこう怒られるが、 上記の4つの権限を付与したら解消した。
⇒ このあと、下の③が発生し、これを解決したら
cloudfortmation:ValidateTemplate cloudfortmation:UpdateStack
の権限がないことで怒られた。
Missing required key 'Bucket' in params
Serverless Error --------------------------------------- Missing required key 'Bucket' in params
いい感じに解説してくれている記事は見つからなかったが、
AWSコンソールから「CloudFormation」でスタックを削除したら、問題が解消された
このとき「状況」は「ROLLBACK_FAILED」みたいな赤字表記になっており、Rollbackが途中で止まったっぽい様子だった。
※表記は正しく覚えてない
webpack4でビルドしたときにエラーになる
■前提
webpack初心者
■本題
もともとはこの記事にしたがってVue.jsを勉強してて、
この記事にしたがって、Sassをビルドしようとした
するとこのコマンドでビルドしようとしたらエラーになった
$ webpack --watch --progress
tkfric:Sample tkfric$ webpack --watch --progress Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema. - configuration[0].module has an unknown property 'loaders'. These properties are valid: object { exprContextCritical?, exprContextRecursive?, exprContextRegExp?, exprContextRequest?, noParse?, rules?, defaultRules?, unknownContextCritical?, unknownContextRecursive?, unknownContextRegExp?, unknownContextRequest?, unsafeCache?, wrappedContextCritical?, wrappedContextRecursive?, wrappedContextRegExp?, strictExportPresence?, strictThisContextOnImports? } -> Options affecting the normal modules (`NormalModuleFactory`).
ググったらあった。
webpack.config.js
のloadersプロパティがunknownなので、これをrules
に変えればいいらしい。
tkfric:Sample tkfric$ webpack --watch --progress 0% [0] compiling webpack is watching the files… (node:5770) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead 77% [0] module and chunk tree optimization unnamed compat plugin/(Sampleディレクトリパス)/node_modules/webpack/lib/Chunk.js:824 throw new Error( ^ Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead at Chunk.get (/(Sampleディレクトリパス)/node_modules/webpack/lib/Chunk.js:824:9) at /(Sampleディレクトリパス)/node_modules/extract-text-webpack-plugin/dist/index.js:176:48 at Array.forEach (<anonymous>) at /(Sampleディレクトリパス)/node_modules/extract-text-webpack-plugin/dist/index.js:171:18 at AsyncSeriesHook.eval [as callAsync] (eval at create (/(Sampleディレクトリパス)/node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:12:1) at AsyncSeriesHook.lazyCompileHook (/Users/tkfric/WORKS/MYDEV/VuePractice/node_modules/tapable/lib/Hook.js:154:20) at Compilation.seal (/(Sampleディレクトリパス)/node_modules/webpack/lib/Compilation.js:1214:27) at hooks.make.callAsync.err (/(Sampleディレクトリパス)/node_modules/webpack/lib/Compiler.js:547:17) at _err0 (eval at create (/(Sampleディレクトリパス)/node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:11:1) at _addModuleChain (/(Sampleディレクトリパス)/node_modules/webpack/lib/Compilation.js:1065:12) at processModuleDependencies.err (/(Sampleディレクトリパス)/node_modules/webpack/lib/Compilation.js:981:9) at process._tickCallback (internal/process/next_tick.js:61:11)
それでもエラーになる
$ npm i -D extract-text-webpack-plugin@next
とりあえずこのブログの通りに実行してみた
tkfric:Sample tkfric$ webpack --watch --progress 0% [0] compiling webpack is watching the files… [0] Hash: a7e5ea6c26ddff43982f Version: webpack 4.19.1 Child Hash: a7e5ea6c26ddff43982f Time: 227ms Built at: 2018-09-19 02:18:27 2 assets Entrypoint style = style.css style.css.map [0] ./style.scss 1.13 KiB [built] [failed] [1 error] [1] ./style.scss 200 bytes [built] [failed] [1 error] + 2 hidden modules WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/ ERROR in ./style.scss Module build failed (from ../node_modules/extract-text-webpack-plugin/dist/loader.js): ModuleParseError: Module parse failed: Unexpected token (1:5) You may need an appropriate loader to handle this file type. > body { font-size: 14px;} | p { margin: 0.5em;} | @keyframes fade-in { at handleParseError (/(Sampleディレクトリパス)/node_modules/webpack/lib/NormalModule.js:432:19) at doBuild.err (/(Sampleディレクトリパス)/node_modules/webpack/lib/NormalModule.js:466:5) at runLoaders (/(Sampleディレクトリパス)/node_modules/webpack/lib/NormalModule.js:327:12) at /(Sampleディレクトリパス)/node_modules/loader-runner/lib/LoaderRunner.js:370:3 at iterateNormalLoaders (/(Sampleディレクトリパス)/node_modules/loader-runner/lib/LoaderRunner.js:211:10) at /(Sampleディレクトリパス)/node_modules/loader-runner/lib/LoaderRunner.js:202:4 at process.nextTick (/(Sampleディレクトリパス)/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:73:15) at process._tickCallback (internal/process/next_tick.js:61:11) @ ./style.scss ERROR in ./style.scss 1:5 Module parse failed: Unexpected token (1:5) You may need an appropriate loader to handle this file type. > body { font-size: 14px;} | p { margin: 0.5em;} | @keyframes fade-in { @ ./style.scss 2:14-39 Child extract-text-webpack-plugin ../node_modules/extract-text-webpack-plugin/dist ../node_modules/style-loader/index.js!style.scss: Entrypoint undefined = extract-text-webpack-plugin-output-filename [0] ../node_modules/style-loader!./style.scss 967 bytes {0} [built] [1] ./style.scss 200 bytes {0} [built] [failed] [1 error] + 2 hidden modules ERROR in ./style.scss 1:5 Module parse failed: Unexpected token (1:5) You may need an appropriate loader to handle this file type. > body { font-size: 14px;} | p { margin: 0.5em;} | @keyframes fade-in { @ ./style.scss (../node_modules/style-loader!./style.scss) 2:14-39
まだ何か出る
WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
これはこんな記述をすれば解決するらしい。
"scripts": { ... "dev": "webpack --mode development", "build": "webpack --mode production", "production": "webpack --mode production"
でもまだ下のようなwarningが残る
ERROR in ./style.scss Module build failed (from ../node_modules/extract-text-webpack-plugin/dist/loader.js): ModuleParseError: Module parse failed: Unexpected token (1:5) You may need an appropriate loader to handle this file type.
調べたらこの記事が出てきたのでひとまず参考に以下の記述をwebpack.config.js
に追記
module: { rules: [ .... { test: /\.css$/, loader: "style!css" }, { test: /\.(png|jpg|jpeg|gif|woff)$/, loader: 'url?limit=8192' }, { test: /\.(otf|eot|ttf)$/, loader: "file?prefix=font/" }, { test: /\.svg$/, loader: "file" } ] },
まだエラーが残る
ERROR in Entry module not found: Error: Can't resolve 'css/style.scss' in '/(Sampleディレクトリパス)/css'
この記事を読めば最初からうまくいったのかもしれない。
いったん
* cssディレクトリをsrcに変更
* context
entry
の記述を削除
* src下に空のindex.jsを作成
これで無事に解決した(っぽい)
tkfric:Sample tkfric$ webpack --watch --progress --mode production 0% [0] compiling webpack is watching the files… [0] Hash: aa5b75cccf66cd9b1ffa Version: webpack 4.19.1 Child Hash: aa5b75cccf66cd9b1ffa Time: 119ms Built at: 2018-09-19 03:18:25 Asset Size Chunks Chunk Names main.css 3.61 KiB 0 [emitted] main main.css.map 3.51 KiB 0 [emitted] main Entrypoint main = main.css main.css.map [0] ./src/index.js 0 bytes {0} [built]
でも結論としてはまだわかってない
Laravelでバリデーションルールにorやandがほしかった話
経緯と概要
携わってるプロジェクトで、メールアドレスのバリデーションを変えるということになった。
既存会員 : オリジナルの正規表現
新規会員 : Laravelのemail
ルール(RFC準拠)
となったのだが、
結果としてこの形で全員救う必要性が出てきた。
でも、正規表現も当てて、Laravelのemailも当てて…という都合の良いものはいくら調べても出てこなくて、 結果自力でどうにかするかと思い立ち実装した次第。
実装した内容
前提として
- Laravel5.3
- PHP7.0
バリデーションルールを複数指定し(Laravel内のもの、カスタム問わず)、
or
: どちらかが通るand
: どちらも通る
としてカスタムバリデーションルールを作った。
まず、カスタムバリデーションを記述するファイルとして
app\Providers\ValidationServiceProvider.php
を作成
処理の概要としては、指定されたバリデーションルールで1つずつバリデータを通すだけの簡単なもの。
/** * 複数のバリデーションルールでorチェックする */ Validator::extend('or', function ($attribute, $value, $parameters, $validator) { foreach ($parameters as $key => $val) { $validator = Validator::make([$attribute => $value], [$attribute => $val]); if ($validator->fails()) { continue; } return true; } return false; }); /** * 複数のバリデーションルールでandチェックする */ Validator::extend('and', function ($attribute, $value, $parameters, $validator) { foreach ($parameters as $key => $val) { $validator = Validator::make([$attribute => $value], [$attribute => $val]); if ($validator->fails()) { return false; } } return true; });
最後に
こんなことする必要あったのかなぁ
Python3でリクエストパラメータ付のPOST通信をしたときに、リクエストパラメータが抜け落ちる
この記事でやったことの続き
def http_post(url, headers, body): req = urllib.request.Request(url, json.dumps(body).encode(), headers, 'POST') try: with urllib.request.urlopen(req) as res: body = res.read().decode()
でbodyの中身が
{ 'id' : 1 }
という形だったのだが、
POST先のAPIから「idは必須です」というメッセージが返ってきた。
かなりはまって、かなり検索しまくって、
結果的にどの記事を見たかは覚えてないが、
(たしかStackoverflowだった)
以下のように書き直したら動いた
def http_post(url, headers, body): data = urllib.parse.urlencode(body).encode('utf-8') request = urllib.request.Request(url, data, headers) try: with urllib.request.urlopen(url=url, data=data) as response: body = response.read().decode("utf-8")
リクエストパラメータの処理の仕方を
json.dumps(body).encode()
から
urllib.parse.urlencode(body).encode('utf-8')
に書き換えた。
これでタイトルの問題は解決したのだが、非常に謎。
can't concat bytes to str: TypeErrorを解決する
コードは以下
def http_post(url, headers, body): req = urllib.request.Request(url, body, headers, 'POST') try: with urllib.request.urlopen(req) as res: body = res.read().decode()
でてきたエラーは以下
can't concat bytes to str: TypeError Traceback (most recent call last): File "/var/task/sample.py", line xx, in handler http_post(url, headers, body) File "/var/task/sample.py", line xx, in http_post with urllib.request.urlopen(req) as res: File "/var/lang/lib/python3.6/urllib/request.py", line 223, in urlopen return opener.open(url, data, timeout) File "/var/lang/lib/python3.6/urllib/request.py", line 526, in open response = self._open(req, data) File "/var/lang/lib/python3.6/urllib/request.py", line 544, in _open '_open', req) File "/var/lang/lib/python3.6/urllib/request.py", line 504, in _call_chain result = func(*args) File "/var/lang/lib/python3.6/urllib/request.py", line 1361, in https_open context=self._context, check_hostname=self._check_hostname) File "/var/lang/lib/python3.6/urllib/request.py", line 1318, in do_open encode_chunked=req.has_header('Transfer-encoding')) File "/var/lang/lib/python3.6/http/client.py", line 1239, in request self._send_request(method, url, body, headers, encode_chunked) File "/var/lang/lib/python3.6/http/client.py", line 1285, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "/var/lang/lib/python3.6/http/client.py", line 1234, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/var/lang/lib/python3.6/http/client.py", line 1064, in _send_output + b'\r\n' TypeError: can't concat bytes to str
参考にした記事
分かったこと
・byte型とstring型は結合できないよ、というエラー
じゃあどうしたらいいの?
Stackoverflowの記事を参考にこう直してみた。
def http_post(url, headers, body): req = urllib.request.Request(url, json.dumps(body).encode(), headers, 'POST') try: with urllib.request.urlopen(req) as res: body = res.read().decode()
動いたっぽい
LambdaでHTTPリクエストしたときに遭遇したやつ
Lambdaから外部のAPIを叩いてたときに遭遇した
<urllib.request.Request object at 0x7faa06fe2278>
サンプルコードは以下
def http_post(url, headers, body): method = 'POST' data = urllib.parse.urlencode(body).encode() req = urllib.request.Request(url, data, headers, method) try: with urllib.request.urlopen(req) as res: body = res.read().decode() except urllib.error.HTTPError as err: logger.info(err.code) except urllib.error.URLError as err: logger.info(err.reason)
とりあえずそのままググったら、1件目にstackoverflowで引っかかった。 でも2013年6月で少し不安 stackoverflow.com
とりあえず回答にあるようにreq.__dist__
をログに出してみた
{ '_full_url': 'APIのURL', 'fragment': None, 'type': 'https', 'host': 'APIのドメイン', 'selector': 'APIのURI', 'headers': {}, 'unredirected_hdrs': {}, '_data': b'key1=val1&key2=val2&…’, '_tunnel_host': None, 'origin_req_host': 'POST', 'unverifiable': False }
一応dir(req)
もログに出してみた
(※見やすいように適度に改行を入れている)
これでreq
で使用できるキーが出るとのこと。
[ '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_data', '_full_url', '_parse', '_tunnel_host', 'add_header', 'add_unredirected_header', 'data', 'fragment', 'full_url', 'get_full_url', 'get_header', 'get_method', 'has_header', 'has_proxy', 'header_items', 'headers', 'host', 'origin_req_host', 'remove_header', 'selector', 'set_proxy', 'type', 'unredirected_hdrs', 'unverifiable' ]
結果よくわからず数日経って、
これ読んだら解決した。
PHPでいうvar_dump()みたいなのがほしいとずっと思ってた。
Pythonを初めて数日の僕にはありがたい記事でした。
awkの使い方を毎回調べてしまうから自戒の念を込める
タイトル通り
アプリケーションログやアクセスログから調査をするときに 気付けばいつも「awk 使い方」でググってしまう。
いつもやってること
$ cat アクセスログ | awk -F'[ ]' '{print $1,$2,$3}' | less
-F
のあとに[]
を使ってdelimiterの指定
上の例では半角スペース
そのあとに$1
のように区切った中から、{print}
と一緒に抽出したい列数を指定
余談
あと他によくやってるのが、
$ cat アクセスログ | awk -F'[ ]' '{print URI}' | sort | uniq -c | sort -nr | less
- URIで抽出して
- 重複削除しつつ、カウントして
- 件数の降順で
less
する
これも備忘録的に。