OmniAICreator/Qiita-1.07M huggingface dataset:
ddu.vimでvim-choosewinを使いたかった

# はじめに

## 経緯 (よみもの)

いわゆる `ShougoWare` のなるべく新しいものを追っている…つもりでありましたが、いつの間にか `ddc.vim` や `ddu.vim` などの `Denops.vim` に依存先を変更したプラグインがリリースされていました
ようやく切り替えたのは確か2021年の秋ごろですが、windowsとmacOSを行ったり来たりすることが多い私にとっては `python` のパスを切り替えて `:healthcheck` のステータスを確認して…という作業がPCが交換されるたびに発生しており、それが非常に煩雑に感じていた為、この切り替えは非常にありがたかったのです

ですが…

### どうして Defx.nvim ではサポートされていた vim-choosewin が使えなくなっているのですか？

知らんよって言われそうなのですが、その辺のことはShougoさんの記述記事に記載されているように思います

にわかものの私にとっては、歴史のところですでに読み物として面白いと感じておりますが、下記リンクの通り、プラグインそのものに拡張性を持たせるというのが `ddc.vim` や `ddu.vim` の設計思想の根幹にあるように思います

https://zenn.dev/shougo/articles/ddu-vim-beta#ui,-source,-filter,-kind-%E3%81%A8%E3%81%84%E3%81%86%E6%A6%82%E5%BF%B5

### でも選んだファイル(item)を任意のウィンドウに開きたいねん！！

しかし、おそらく3年以上ほど Defx.nvim + vim-choosewin でのファイル操作に慣れ親しんだ私にとって、このあたりの修正はインパクトが大きかったです

なにより頭の中で 「`source` …？ `sourceOption` …？ `source.parameter` …？ `filterParams` …？ なにがなにでどれがどれ…？ 😵‍💫😵‍💫😵‍💫」となってしまい、まともに設定を触ることができていませんでした

ただ、最近になってようやくヘルプページから以下の文言を見つけることができ、ここから解決ができました

https://github.com/Shougo/ddu.vim/blob/main/doc/ddu.txt#L950

## 動作確認環境

- OS: Windows 11 Pro
    - バージョン	10.0.22621 ビルド 22621
- Neovim: v0.8.2
```
PS C:\Users\cocoa> nvim --version
NVIM v0.8.2
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3
Compiled by runneradmin@fv-az28-353

Features: -acl +iconv +tui
See ":help feature-compile"

      システム vimrc: "$VIM\sysinit.vim"
       省略時の $VIM: "C:/Program Files (x86)/nvim/share/nvim"

Run :checkhealth for more info
```

# 解決方法

設定ファイルにて、以下の通りに関数を定義し、それを `ddu#ui#<filer|ff>#do_action('itemAction')` で呼んであげるようにするといい感じに vim-choosewin のあとにファイルを開くことができます

```my__ddu_func.vim
function! s:win_all()
  return range(1, winnr('$'))
endfunction

function! MyDduChooseWin(args) abort
  let l:path = a:args.items[0].action.path
  call choosewin#start(s:win_all(), {'auto_choose': v:true, 'hook_enable': v:false})
  execute 'edit ' . l:path
endfunction

call ddu#custom#action('kind', 'file', 'mychoosewin', { args -> MyDduChooseWin(args) })
```

```my__ddu_ui_ff.vim
  nnoremap <buffer><silent> -
        \ <Cmd>call ddu#ui#ff#do_action(
        \     'itemAction', #{ name: 'mychoosewin', quit: v:true }
        \ )<CR>
```
```my__ddu_ui_filer.vim
  nnoremap <buffer><silent> -
        \ <Cmd>call ddu#ui#ff#do_action(
        \     'itemAction', #{ name: 'mychoosewin', quit: v:true }
        \ )<CR>
```

## `ddu#custom#action()` について

こちらもヘルプに記載がありますが、 `ddu.vim` に接続されているあらゆるソースタイプとソースを対象に、任意の名前で `itemAction` からコールする関数を定義できるようです

https://github.com/Shougo/ddu.vim/blob/main/doc/ddu.txt#L329

# そのほか貼っていなかった参考…？

https://github.com/t9md/vim-choosewin

# おわりに

`ddu-source-custom-list` あたりもそうですが、独自拡張が書きやすいのは非常にありがたいですね
なお使いこなせるとは言えないのがつらいところです、かなしみ

おわり
pathのまとめ

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)


# Pathを設定できるオブジェクト

+ [取引先責任者レコードにリード状況と同じステータスを加えたい](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000Jg2mKSAR)

エクスペリエンスビルダーサイトと通常の環境では設定できるオブジェクトが違うようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/7308ff91-8da2-ac8c-85e8-70fc3500d06f.png)

+ [パス (エクスペリエンスビルダーサイトコンポーネント)](https://help.salesforce.com/s/articleView?id=sf.rss_sales_path.htm&type=5)
+ [パスによるユーザのガイド](https://help.salesforce.com/s/articleView?id=sf.path_overview.htm&type=5)


+ [Facing problem for Path Visibility on Page in Lightning.](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000O8mXz)

Lightning のページのパスの可視性の問題に直面しています。
Contact オブジェクトでステージを追跡する必要があります。2 つのレコード タイプを作成し、カスタム フィールド ステージを作成しました。レイアウトでパスをアクティブにしましたが、ページには表示されません。パス設定を確認し、ユーザーのパス設定を記憶するがチェックされています。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c9fb3bd9-c907-67e7-9fc0-4eedc20ec305.png)


レコード タイプを導入する前に、パスは正しく作成されましたか? そのため、このパスは「マスター」レコード タイプに対してのみアクティブになりました (カスタム レコード タイプがオブジェクトに導入される前に作成されたレコードを表示するための内部の組み込み/デフォルト レコード タイプ)。

この「マスター」を確認するには、[オブジェクト マネージャ] > [連絡先] > [レコードの種類] > [ページ レイアウトの割り当て]に移動します(情報のみ。ここでは何も変更しません)。

ここで、作成した「カスタム」レコード タイプごとに、同じオブジェクトに複製パスを作成する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e597d831-1565-1938-f7f2-52c5bf85d126.png)


次に、各カスタム レコード タイプの任意の 1 つのレコードに移動します > ページの編集 > パスの追加 > 必要な組み合わせのアクティブ化 (理想的にはアプリ > レコード タイプまたはアプリ > レコード タイプ > プロファイル)。

オブジェクトの他のすべてのカスタム レコード タイプに対してこれを繰り返します。

次に、パスはマスター + 任意のカスタム レコード タイプ (すべてのレコードのプレ/ポスト レコード タイプ) になります。


# カスタムオブジェクトにてパスの表示をしたいのですが、できない

+ [パスの表示について](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007RdfhT)

:::note
確認したところレコードタイプが間違ってました
:::
docker-compose を楽に書くツール群

もしかしてあるのでは？と思ってググったら有った。

結論からいうと、既知のパターンにはめて全部生成するタイプしかない。

# 8gwifi.org

https://8gwifi.org/dc.jsp

非常に入力項目が多い。yamlの項目を全部そのままFORMに入れる印象。

# Compose Generator 

nodejsで書いてあるcli。対話式で作成。

https://www.compose-generator.com/

https://medium.com/geekculture/compose-generator-d4356d38922d

https://github.com/compose-generator/compose-generator 

あらかじめ定義してあるパターンに応じて作成するが、バリエーションはかなり豊富に見える。

https://github.com/compose-generator/compose-generator/tree/main/predefined-services

# composerize

docker run のワンライナーを、docker-compose yml 3.3 に変換する。

https://www.composerize.com/
https://github.com/magicmark/composerize
SAP知識0から2週間でSAP on AWS - Specialty(PAS)に合格したので、勉強方法まとめます

## はじめに
SAPの知識0から2週間で合格できたので学習方法と重要なポイントを共有できたらと思います。

その他のAWS認定資格の勉強方法は下記にまとめてますので、参考にしてください。
[未経験でもAWS認定全11資格を10ヶ月で取得できたので学習方法をまとめました](https://qiita.com/mani___524/items/7585331df069266cf69f)

## エンジニアの経歴
エンジニア歴は、本投稿時点で1.5年になります。
IT系の営業職から、未経験でエンジニア転職。 現在は都内のSES企業にて、AWS案件に参画中。

SAPの利用経験は全くなく、勉強開始前は「サップ」と呼んでるレベルでした。

:::note info
「SAP」は、「サップ」ではなく「エスエーピー」と呼ぶみたいです。
:::


# 目次

[1. 学習方法](#1-学習方法)
[2. 試験の感想](#2-試験の感想)
[3. おわりに](#3-おわりに)

# 1. 学習方法
下記順番で学習していきました。
1. 試験ガイドの確認
2. サンプル問題
3. AWS BenchPrep(模擬)
4. SAP on AWS 技術文書

それぞれ詳しく紹介していきます。
#### 1.試験ガイドの確認(時間に余裕があれば）
[AWS Certified: SAP on AWS - Specialty 試験ガイド](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sap-on-aws-specialty/SAP-on-AWS-Specialty_Exam-Guide.pdf)
試験ガイドを確認して、SAPonAWSの試験概要を把握する！、、、が、ベストだと思いますが正直しなくても良いと思います。
SAP知識0の状態で試験ガイド読んでも何を言ってるのかあまり理解できないからです笑

それよりも次の
- サンプル問題
- AWS BenchPrep-模擬

で、試験概要を全体的にまとめた問題が出題されているので、こちらに取り掛かった方が早いと思います。

:::note info
時間がない方は、試験ガイドをスキップ！
:::

#### 2. サンプル問題　
[AWS Certified: SAP on AWS - Specialty サンプル問題](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sap-on-aws-specialty/SAP-on-AWS-Specialty_Sample-Questions.pdf)

正解の理解するのはもちろん、不正解の理由から問題文・全選択肢でわからない単語を無くすまで学習しました。
学習時間の目安は、10~15時間です。

#### 3. AWS BenchPrep-模擬
[AWS BenchPrep-模擬](https://amazonwebservices.benchprep.com/login#exams)

サンプル問題と同じく正解の理解するのはもちろん、不正解の理由から問題文・全選択肢でわからない単語を無くすまで学習しました。
学習時間の目安は、15~20時間です。

:::note info
サンプル問題、 BenchPrep模擬問題はどれも、本番に近い内容になるので理解するまで繰り返し解くことがおすすめです。
:::

#### 4. SAP on AWS 技術文書　
[SAP on AWS 技術文書](https://aws.amazon.com/jp/sap/docs/)

こちらはボリュームがあるので、下記ドキュメントに絞って学習を進めました。
- SAP HANA
- SAP ガイド全般

上記のドキュメントには、全体的に目を通しましたが
特に、サンプル問題や模試問題では出題されてない**制約事項・トラブルシューティング**を重点的に学習しました。

学習時間の目安は、15時間以上です。

# 2. 試験の感想
点数は755点とギリギリの合格でした。(あと一問間違いてたら、不合格、、、、復習します。)
点数からもわかるように、上記で紹介した学習内容は最低限の勉強方法になってます。
また、AWSの基礎的知識(EC2の購入オプション,ストーレージ(EBS,EFS,S3))などSAAレベルの知識は頭に入れておきましょう。

![PASスコア.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2515983/acdcece4-4dd9-74df-baf3-a4e962e52a16.jpeg)


# 3. おわりに
仕事でSAPを使うわけではなくAWS認定資格全冠保持を維持するために勉強したので、最低限の学習で挑みました。
結果、SAP知識0で2週間で合格できたので、是非同じ境遇の方がいれば参考にしていただけると幸いです。

### おすすめの合格記
①[【AWS認定資格】SAP on AWS （PAS-C01）試験問題対策　-概要編-](https://www.youtube.com/watch?v=6MsaoLjseCs&list=PLrbutKlth8WG7Fp7AOP_LGHIjRuWnRBI1)

②[AWS 認定 SAP on AWS - 専門知識(AWS Certified: SAP on AWS - Specialty)の学習方法](https://tech.nri-net.com/entry/aws_certified_sap_on_aws_specialty)
neosでlogix その103

# 概要
neosでlogixやってみる。
Axis Angleノード使ってみた。

# Axis Angle

```
Inputs
 	Float3	Axis
 	Float	Angle
Outputs
 	FloatQ	*
```

# Euler Angles

```
Inputs
 	FloatQ	Q
Outputs
 	Float3	*
```

# To Axis Angle

```
Inputs
 	FloatQ	Q
Outputs
 	Float3	Axis
 	Float	Angle

```

# 俺コード

```
a = AxisAngle 0,1,0 45
b = EulerAngles a
{c, d} = ToAxisAngle a
 

```

# 写真

![2023-01-30 21.22.51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9bfbaef7-62a0-a82b-3fb8-543cc482adc5.jpeg)


以上。
Power Apps で作成したアプリを以前の状態に戻す


# はじめに

時々、Power Apps で作成したアプリを少し変更したら動かなくなっちゃった、エラーが発生するようになったという相談をいただくことがあります。

この対応のために時間を要したり、結果的にリリースが遅くなってしまうのはもったいないと思います。
そのため、知っている人も多いとは思いますが (もっと認知されてほしいので)、今回は、Power Apps で作成したアプリを以前の状態に戻す方法について説明します。

# 利用するアプリ

今回は、このブログでも良く紹介している、日程調整を効率化するアプリをベースに紹介します。
以下のように、候補者の空き時間情報をベースに、日程の候補をベストエフォートで返してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/f458bea8-527e-4d33-0ba1-36c29c4c4cbe.png)

# 以前の状態に戻す方法

このアプリの以下の箇所の処理を少し変更しようとしたところ、以下のようにエラーが発生し、元に戻せなくなってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/149c7e02-10f6-8799-90ff-a36495aeba1e.png)

一旦、以下の画面に戻り、バージョンタブに移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/22ad2a80-ba35-6a05-0a05-022fb2eab96a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/a6a79231-b82d-c95c-cee7-a946f6acaa30.png)

過去 6 か月以内に保存したバージョンが表示されます。これは非常に助かりますね。
今回は、こちらを選択して復元をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/57a4d212-e4f5-ddee-8808-0dfeaabee6fc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/dc319fb3-3055-4a36-2959-c06f0c1b6ca9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/4ec71be3-2cdd-c5b8-4ed2-d3b9e9fcf0b0.png)

正常に復元されました。アプリを再度開いてみます。上記エラーがなくなっていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/3a7f1a38-2e83-595d-dd03-80b77d415c3c.png)

それ以外にも、アプリを行ったん zip ファイルにエクスポートして、インポートして更新をすることも可能ですが、変更のたびにエクスポートしてファイル管理するのは面倒なため、ちょっとしたことであれば上記方法の方が良いと思います。
(以下はパッケージの例です。ソリューションについては割愛します)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/510fa886-ff72-37ac-a3d3-2429378756b6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/10b7f052-ae91-f1b7-37fe-2838a3bc474f.png)
みんな知ってるデータベースとは！

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はデータベースについて更に詳しく調べてみましょう！
![インスタスライド_202301131.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/e5d494f1-7988-ec94-0a8c-4bcd987b3abe.gif)


# データベースについて
データを整理・一元管理し、必要に応じて、保存や抽出が行えるようにした仕組みを指す。

このソフトウェアの事をDBMS
（データベース Database マネージメント Management システム System）
と呼ぶ

# データベースの機能
基本的な機能として

データを
・照会(SELECT)
・更新(UPDATE)
・登録(INSERT)
・削除(DELETE)
できる機能をもつ

# データベースのイメージ
情報をSELECT（照会）できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/68994cc8-285e-7815-3ece-8e8a04f1321b.png)

情報をUPDATE（更新）できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/75e51ba5-7385-755b-5cd1-06f7ff66992b.png)

情報をINSERT（作成）できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/52dc8b24-32ff-31d8-44ac-0f52cb0111f7.png)

情報をDELETE（削除）できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/9c3c4037-9f5a-ea0a-66fe-7d1346ff6e35.png)

# データベースの特徴
１．検索速度が早い
　メモリやindexを使って高速化

２．壊れない
　データが壊れない仕組み

３．安全
　アクセス管理でセキュリティ対策

４．一貫性
　データの不整合が起きない仕組み

# まとめ
ー　 データベースのシステムをDBMSと呼ぶ

ー　照会、更新、追加、削除の機能を持つ

ー　速度早い、壊れない、安全、一貫性

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
(続)Raspberrypi(32bit)上のPython-slimが厄介な件

この記事は<a href=https://qiita.com/jishi77/items/2cba2e97000f3cce855c>(続)Raspberrypi 4上のPython-slimコンテナで躓いた話</a>の続きです
面倒な方は<a href="#Conclusion">結論</a>だけどうぞ
2023.02.02追記
Arm32v7環境のみの症状なようで，64bit環境(Arm64v8)では問題ありません．ラズパイ32ビットはあまり想定されてない？

# 状況
筆者はVisual Studio CodeでPythonの編集を行っていますが，Remote機能を使えば，
ネットワーク上にあるサーバ上での開発ができることは皆さんがご存じのとおりです．
Docker extensionを入れればコンテナ上での開発もできます．
RemoteとDockerの組み合わせで，サーバ上で立ち上げたコンテナに入りながらの編集もできます．
ところが...
## 症状
Raspberry PI4上で立ち上げたPython-slimベースのコンテナにVS Codeで入ろうとすると
Timeoutしてしまう

## 原因
ログの内容から，どうやらatomic libraryが見つからない様子

<h1 id=Conclusion>結論</h1>
Python-slimベースのコンテナでlibatomicライブラリをインストールする

~~~Dockerfile
FROM Python:3.9-slim

(中略)

RUN apt-get install libatomic1 -y
~~~

### おまけ
Windows上やArm64v8環境で構築するコンテナでは起こりません．(rustcもVisual studio codeで入れない件も）
技育CAMP vol.10　努力賞を取りました

# 技育CAMPとは
技術への一歩を踏み出す学生のためのスキルアップ支援プラットフォームで、年に15回行っているそうです。完全オンライン型で開発テーマは「初めてのハッカソン」なので参加ハードルも低く、いろんな人が挑戦可能です。

# 作ったもの
タバコを止めたい人向けのタバコ情報可視化アプリを開発しました。
使用技術はVue,PHP,MySQLです
スマホ画面推奨です。
https://zingy-profiterole-accecf.netlify.app/

# 感想
まず結果として努力賞が取れました！
取れた要因としては以下の三つかなと思います。
    ・バックエンドで計算等を全て処理したので、フロントはUIをとてもこだわることができた
    ・いい着眼点を持ったアイデアを出せた
    ・スライドと発表資料をただの作品紹介ではなく、特徴とメリットとこのアプリができることを重点おいて発表できた。

このハッカソンの良かったところとしては、学生メンターさんのレスポンスが2分以内に帰ってくることですね。全体の質問量によるんですが、自分の質問しかないときは1分で返ってきます笑
初めて参加する人からしても心強いですね。

# 東京への切符獲得
今回参加したときに急に発表があったのですが、2022年の10月あたりから2023年の2月までの技育CAMPで賞を受賞した方限定で、東京現地に集まって発表する技育CAMPアドバンスというものが発表されました。
交通費を出してもらえて、かつサポーターズさんのサポート企業さんが当日参加して、作品に対するレビューをもらえるそうです。
今までオンラインであった中で、現地で交流できるイベントがついに出てきました！
私も参加権を得たのでとても楽しみです！
ではこの辺で～
(続)Raspberrypi 4上のPython-slimコンテナで躓いた話

以前書いた
<a href=https://qiita.com/jishi77/items/e7a0db2408b76e5e271e>Raspberry PI上のPython-slimコンテナ（Debianベース）でrustc依存のパッケージ構築に苦労した話</a>
の続きになります
面倒な方は<a href="#Conclusion">結論</a>だけどうぞ


<h1>前提条件</h1>OS: Rasbian( on Raspberrypi4 )<br/>
Docker及びDocker-composeをapt経由でインストール<br/>
Dockerfile内にpip経由でbcryptを含むいくつか（主にFlask関係）をインストールする文を書いた<br/>
ベースコンテナはpython:3.9-slim

# 経緯
Rasbian上のPython-slimコンテナをベースに

~~~Dockerfile
RUN pip install bcrypt
~~~
(正確にはbcryp依存のflask-bcrypt）したところ，rustcがないと怒られたので，rustcを入れてpipでビルドしながらインストールできるようにした

## 問題
コンテナ容量が1GB近くに跳ね上がる

## 仮説
~~~Dockerfile
RUN apt-get install python3-bcrypt && \
    pip install flask-bcrypt -y
~~~
すればいいのでは？

## 結果
apt-getでインストールされたpython3-bcryptが見つからず，bcryptパッケージをビルドしようとしてrustcがないと怒られます

## 原因
apt-getで入るpython packageは

~~~
/usr/lib/python3/dist-packages
もしくは
/usr/lib/python3.9/dist-packages
~~~
に入るのに対し，python-slimコンテナで参照されるモジュールパスは(<a href=https://note.nkmk.me/python-import-module-search-path/>こちら</a>参照)
~~~
>>> import sys
>>> print(sys.path)
['', '/usr/local/lib/python39.zip', '/usr/local/lib/python3.9', '/usr/local/lib/python3.9/lib-dynload', '/usr/local/lib/python3.9/site-packages']
~~~
ということで，参照される先に入りません（汗）
<h1 id=Conclusion>結論</h1>
Dockerfile内のPYTHONPATH環境変数に/usr/lib/python3/dist-packagesと/usr/lib/python3.9/dist-packagesを追加

~~~Dockerfile
ENV PYTHONPATH="/usr/lib/python3/dist-packages:/usr/lib/python3.9/dist-packages"

RUN apt-get install python3-bcrypt && \
    pip install flask-bcrypt
~~~
(説明のため簡略化しています．実際には他のパッケージもインストールしてます）
2023/1/31主にITとかセキュリティの記事

日本人1万3000人以上の個人情報がハッカーにより盗まれ、販売されていたことをNordVPNが発表(1/29)
https://news.yahoo.co.jp/articles/2d08c6db9af7582535c1aec96339a759fa8cddcb?source=rss

Windows CryptoAPIの重大な脆弱性をサイバー攻撃に悪用する概念実証が公開(1/29)
https://news.mynavi.jp/techplus/article/20230129-2577414/

Microsoft、ネットから取得したExcelのXLL アドインをブロックへ(1/29)
https://www.zaikei.co.jp/article/20230129/707477.html

ダークWebにアクセスすることは違法か？アクセス方法は？(1/29)
https://news.mynavi.jp/techplus/article/20230129-2577644/

米国家安全保障局、IPv6セキュリティガイダンスを公開(1/29)
https://www.zaikei.co.jp/article/20230129/707480.html

米下院外交委、ＴｉｋＴｏｋ禁止法案を採決方針　利用禁止広がる(1/29)
https://www.sankei.com/article/20230129-23SPZ65KFRN6LPGVF2V243W3EQ/?ownedutm_source=owned%20site&ownedutm_medium=referral&ownedutm_campaign=ranking&ownedutm_content=%E7%B1%B3%E4%B8%8B%E9%99%A2%E5%A4%96%E4%BA%A4%E5%A7%94%E3%80%81%EF%BC%B4%EF%BD%89%EF%BD%8B%EF%BC%B4%EF%BD%8F%EF%BD%8B%E7%A6%81%E6%AD%A2%E6%B3%95%E6%A1%88%E3%82%92%E6%8E%A1%E6%B1%BA%E6%96%B9%E9%87%9D%E3%80%80%E5%88%A9%E7%94%A8%E7%A6%81%E6%AD%A2%E5%BA%83%E3%81%8C%E3%82%8B

【山形県村山市】カップルの成立実績があるメタバース婚活“marry360”が東北初上陸！(1/29)
https://straightpress.jp/20230129/834719

ネット未接続PCからスマホで情報窃取(1/30)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/041800012/011800200/

攻撃者の「横の動き」をつかめ、サイバー攻撃を受けたNTTコムの教訓(1/30)
https://xtech.nikkei.com/atcl/nxt/column/18/02348/012600003/

ウクライナ危機で多用された「ワイパー」、暗号化・脅迫・破壊系マルウエアの姿(1/30)
https://xtech.nikkei.com/atcl/nxt/column/18/02347/00002/

会津若松市で一歩先行く住民データの本人利用、ネット経由で自動化できる手続きとは(1/30)
https://xtech.nikkei.com/atcl/nxt/column/18/02342/012500003/

庁内DCとAWS併用し基幹系運用　余剰ITインフラなくしコスト抑制へ 北九州市(1/30)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600004/012300123/

熱い鉄が形づくる　日本製鉄のDX戦略(1/30)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/012400135/

ChatGPT(1/30)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/012400133/

デジタル投資に消極的すぎる　DXよりGXを語る経営者の内実(1/30)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600007/012600130/
GCP触ってみた②

~~WindowsのGoogle Cloud SDK Shell入れたけどタブ補完利かなくて不便でWebコンソールからやってるのは内緒~~

# Cloud IAM

「IAMと管理」から「IAM」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704575/5783b40e-3d44-128d-3681-c072d6d7fb8d.png)

「アクセス権を付与」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704575/cc3c7b43-3761-7d88-00b3-26c2b352559d.png)

自分のアカウントを使っているのでここに載せられないが、Gmailアカウントにサービスごとのアクセス権を付与できるらしい
最小限のアクセス権を付与するのが望ましいのはAWSと考え方が変わらないような気がする

# Google Compute Engine(GCE)
AWSでいうEC2。仮想マシンのリソースを利用できる

GCP触ってみた①で一度やっているが、もう一度インスタンスを作成してみる

## インスタンスの作成

```shell
gcloud compute instances create gcp --preemptible --zone=us-west1-a --machine-type=e2-micro
```

今回は起動タイプ、ゾーンを指定してみる

```
Created [https://www.googleapis.com/compute/v1/projects/<projectID>/zones/us-west1-a/instances/gcp].
NAME: gcp
ZONE: us-west1-a
MACHINE_TYPE: e2-micro
PREEMPTIBLE: true
INTERNAL_IP: 10.138.0.4
EXTERNAL_IP: 35.247.113.32
STATUS: RUNNING
```

いいのではないか

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704575/f9bc967b-37b0-8b00-4e6f-ad333d6b6e00.png)

GUIから見てもインスタンスが作成されている
ゾーンも正しそうだ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704575/8ea29775-1863-dfd2-5063-f10b7aa05da4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704575/52d2a5a2-2196-b9bd-c99a-346cc1f5c75c.png)

ほかの起動オプションも動作してるようだ


## インスタンスの削除(できなくて焦る)

```shell
# インスタンス一覧表示
gcloud compute instances list
NAME: gcp
ZONE: us-west1-a
MACHINE_TYPE: e2-micro
PREEMPTIBLE: true
INTERNAL_IP: 10.138.0.4
EXTERNAL_IP: 35.247.113.32
STATUS: RUNNING

NAME: gcppractice
ZONE: us-west1-a
MACHINE_TYPE: n1-standard-1
PREEMPTIBLE: true
INTERNAL_IP: 10.138.0.3
EXTERNAL_IP: 34.168.195.33
STATUS: RUNNING

NAME: gcpstudy
ZONE: us-west1-a
MACHINE_TYPE: n1-standard-1
PREEMPTIBLE:
INTERNAL_IP: 10.138.0.2
EXTERNAL_IP: 35.197.82.4
STATUS: RUNNING
# インスタンス削除
gcloud compute instances delete gcpstudy -q
ERROR: (gcloud.compute.instances.delete) Underspecified resource [gcpstudy]. Specify the [--zone] flag.
```

どうやら削除コマンドの実行の時もゾーンを指定する必要があるらしい

```shell
gcloud compute instances delete gcpstudy --zone=us-west1-a
The following instances will be deleted. Any attached disks configured to be auto-deleted will be deleted unless they are attached to any other instances or the `--keep-disks` flag is given and specifies them for keeping. Deleting a disk is irreversible and any data on the disk will be lost.
 - [gcpstudy] in [us-west1-a]

Do you want to continue (Y/n)?  y

Deleted [https://www.googleapis.com/compute/v1/projects/<projectID>/zones/us-west1-a/instances/gcpstudy].
```

削除できたっぽい、気を付けないと

-qオプションでインタラクティブな確認をyesでスキップできるらしいのでしてみる
```shell
gcloud compute instances delete gcp --zone=us-west1-a -q
Deleted [https://www.googleapis.com/compute/v1/projects/<projectID>/zones/us-west1-a/instances/gcp].
```

できたっぽいですね！
今日はここまで
Azure Private EndpointでApplication Security Groupがサポートされるようになったので試してみた

先日（2023/1/24）にPrivate EndpointでApplication Security Groupがサポートされるようになりました。

https://azure.microsoft.com/ja-jp/updates/general-availability-application-security-groups-support-for-private-endpoints/

## Application Security Groupとは
仮想マシン(NIC)をグループ化する事ができ、NSGの送信元/宛先として適用できます。同じ役割のサーバー同士をグルーピングする事で、アプリケーションの通信パターンに適応したNSG設定が容易になります。
今回このNICの対象にPrivate EndpointのNICも含めるようになり、閉域通信で構築しているPaaSサービスもグルーピングができるようになりました。

### 触ってみた

#### 前提の環境
以下のような環境を作成しました。
Private Linkについては前回の記事をご確認ください。

https://qiita.com/Yosuke_Sakaue/items/d3a6974745c6c05ae293

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/d506602b-7650-54ec-c5e6-6c5646ea8856.png)

結果確認用のVMからはそれぞれのWebAppにアクセスできることを確認しています。

#### ASGを作成する
ASGをあらかじめ作成しておきます。
作成時点では特に特別なパラメータは必要ありません。

#### Private EndpointにASGを割り当てる
Private Endpointのリソースから「アプリケーションセキュリティグループ」を選択して、先程作成したASGを割り当てます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/49e73a72-cb7d-7a2c-bc28-13bc1e3f059b.png)
今回は2つエンドポイントがあるので両方に割り当てを行います。

#### NSGに対して受信ルールを設定する
今回はエンドポイントが含まれた二つのサブネットを制御するNSGに対して、ASG内のNICを宛先とするすべてのHTTPS通信を拒否します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/d79ca452-1fc7-7e6d-b1cc-f24d583266f8.png)

#### サブネットに対してプライベート エンドポイントのネットワーク ポリシーを有効にする
忘れがちなポイントとして、プライベートエンドポイントが含まれたサブネットでネットワークポリシーを有効化しないとNSGでの制御はできません。
※これはASGだけではなく単体のプライベートエンドポイントに対してNSGで制御する際も同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/6ac3753a-980d-aaa0-e751-de6464d824e1.png)

https://learn.microsoft.com/en-us/azure/private-link/disable-private-endpoint-network-policy?tabs=network-policy-portal

### 結果確認
結果確認用のVMからEdgeなどでWebAppにアクセスし、アクセスできなければ成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/41776829-52ad-404e-979e-dc3b9532b303.png)

### 参考
https://learn.microsoft.com/en-us/azure/private-link/configure-asg-private-endpoint?tabs=portal
[vue3] Composition APIでrefを取得する方法

## 結論
vue3の場合は以下の書き方でできる。
js側の変数名とhtml側でrefの定義名を同じにするだけ。

```vue
<script setup>
import { ref } from "vue";
const title = ref()
</script>

<template>
  <div ref="title">タイトル</h1>
</template>
```

## 参考
https://pg-log.com/vue3-ref
スマホでHTML5のバリデーション時に該当箇所にスクロールしない問題への対処方法

HTML5のフォームバリデーション、便利ですよね。

だけど、スマホだとエラー箇所にスクロールしてくれないんですよ。

色々探し回ってみたけど、jQueryでのバリデーションばっかりだったんですが、ピュアなJavaScriptでも結構簡単に解決できたのでここに残しておきます。

```js
document.addEventListener("DOMContentLoaded", () => {
    const form = document.querySelector("form");
    form.addEventListener("submit", (event) => {
        const elements = form.elements;
        for (const element of elements) {
            if (!element.validity.valid) {
                element.scrollIntoView();
                element.reportValidity();
                return false;
            }
        }
    
        form.submit();
    });
});
```

HTML5のバリデーションはJavaScriptからは呼べないと勝手に思いこんでたんですが、ちゃんとできるんですね。

便利だなぁ。
VBAにおけるエラーハンドリングのテンプレート

## VBAにおけるエラーハンドリングのテンプレート

①まず頭で「On Error GoTo ERROR_HANDLER」しておく

②メインの処理(main)から呼び出されるプロシージャで値のチェックなどを実施

③チェックの結果ダメならエラーを発生させてmainにスロー（OKならそのまま処理続行）

④スローされたらエラー用のラベル（ERROR_HANDLER）に飛ぶのでエラー用メッセージを表示

⑤「GoTo EXIT_RUN」して後処理（EXIT_RUNラベル内の処理）を行う

⑥後処理の最後にExit Sub でmainを抜ける

-------------------------------------------------------------------------------------------------
上記が基本の構成です。

下記にサンプルを載せます

```vb
Public Sub main()

    Dim errMessage As String

On Error GoTo ERROR_HANDLER
    '処理
    Call sample

EXIT_RUN:
    '後処理
    Exit Sub

ERROR_HANDLER:
    'エラー時の処理
    errMessage = "エラー番号：" & Err.Number & vbCrLf & Err.Description
    
    If Err.Number >= 50001 And Err.Number <= 50100 Then
        Call MsgBox(Prompt:=errMessage, Buttons:=vbExclamation, Title:="規定エラー")
    Else
        Call MsgBox(Prompt:=errMessage, Buttons:=vbCritical, Title:="想定外エラー")
    End If
    
    GoTo EXIT_RUN

End Sub


'------------------------------------------------------------------------------------
'mainから呼び出されるプロシージャ
Private Sub sample()

    '何かをチェックしてダメならエラーを発生させる
    If True Then
        Call Err.Raise(Number:=50001, Description:="エラー１発生")
    End If

End Sub

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/9b0cbbcf-51ed-35ed-241c-eba79effce37.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734868/ccd3be81-2e01-ceff-e870-394e91bd8286.png)

想定できるエラーはエラー番号を独自に振っておきます。
(Excel側で用意してるエラー番号と被らないものを使う)
ドキュメントで自分で振ったエラー番号ごとの情報をまとめておけば、
エラー発生問い合わせ時に原因の特定の助けになります。

想定外のエラーと想定できるものを分けたいときは、エラー番号の数値の範囲で
エラー種別を振り分けるのが今のところ私が使っている手法です。
たとえば今回は50001~50100のエラー番号を独自で使うと決め、
エラー発生時にErr.Numberを調べて、
自分で使うと決めた50001~50100の範囲のエラー番号であれば想定されるエラー
そうでなければ想定外のエラーとして処理するという形です。

このやり方であればエラーの分類はもっと細かく分けることも可能です。

-------------------------------------------------------------------------------------------------

あとここでは割愛してますが、エラー番号の範囲の数値などのマジックナンバー的なものは
定数としてモジュールレベルで宣言しておきます。

最後に後処理でエラー起きた時ハンドリングできないので注意です。
複雑な処理は入れないでおきましょう。
Python + Tkinter - マイル→キロメートルへ単位換算するアプリ

## マイル→キロメートルへ単位換算するアプリ

Tkinter学習の一環でマイル→キロメートルへ単位を換算するアプリを制作しました。

### コード

```python
from tkinter import *
from tkinter import font

#ウィンドウのタイトル+サイズ
window = Tk()
window.title("Mile to Kilometer")
window.minsize(width=400, height=300)
window.config(padx=50, pady=20)

myfont = font.Font(family='Helvetica', size=16, weight='bold')
myfont_result = font.Font(family='Helvetica', size=24, weight='bold')
myfont_h1 = font.Font(family='Helvetica', size=28, weight='bold')

def miles_to_km():
    miles = float(miles_input.get())
    km = round(miles * 1.609, 2)
    kilometer_result_label.config(text=f"{km}")

#タイトル
title_label = Label(text="Mile to Kilometer", font=myfont_h1)
title_label .grid(column=0, row=0, columnspan=3, pady=20)

#マイルを入力
miles_input = Entry(width=20, font=myfont, justify=RIGHT)
miles_input.grid(column=0, row=1, columnspan=2)

miles_label = Label(text="  Miles", font=myfont)
miles_label.grid(column=2, row=1)

#キロへの換算値を出力
equals_label = Label(text="equals to", font=myfont)
equals_label .grid(column=0, row=2)

kilometer_result_label = Label(text="0",font=myfont_result)
kilometer_result_label.grid(column=1, row=2)

kilometer_label = Label(text="km", font=myfont, pady=20)
kilometer_label.grid(column=2, row=2)

#ボタンでマイル→キロへ換算
calculate_button = Button(text="Calculate", command=miles_to_km, width=20, height=3, pady=5)
calculate_button.grid(column=1, row=3)

#メインループを実行
window.mainloop()
```

![スクリーンショット 2023-01-31 003324.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/4fae5a57-6954-0e49-de86-8ec30c0bf334.png)

TKinterで使えそうな実用的なアプリとして、単位系全体を換算するアプリや統計的な調査する際の信用度・必要なサンプル数を計算できるデスクトップアプリを制作したいと考えてます。完成したらまた記事を書きたいと思います。
[Windows×Python] バッチファイルで仮想環境をアクティベートしてPythonファイルを実行する

# 試したこと
以下では、仮想環境をアクティベートした時点でコマンド実行が終了しています。


```python.bat

cd "パス"
venv\Scripts\activate
python "パス\python_file.py"

```

# 解決策

callを使って仮想環境をアクティベートする

```python.bat

cd "パス"
call venv\Scripts\activate
python "パス\python_file.py"
```

これで、コマンドプロンプトを開いて、１ライナーでPythonファイルを実行できます！

実行例
```cmd
python.bat
```

# 参考
https://www.javadrive.jp/command/bat/index1.html
Rails7のローカル開発環境をhttps接続させる

# 概要
Rails7のローカル開発環境をhttpsで接続させる方法について調べたのでメモとして記載
調べるといくつか方法はあるが、今回は`https-portal`を使ってアクセスできるようにしてみた

以下の記事をなぞりつつ、途中でつまづいた部分を記録
https://zenn.dev/dragonarrow/articles/1f3c34e31d0acc

# 前提
* local環境のdockerでRails7が動く

# local環境
* M1 Mac 
* OS:Monterey

# 流れ

## /etc/hostsにドメインを追加
local環境で`/etc/hosts`ファイルに以下を追加

```hosts
127.0.0.1 devsite.local
```

## docker-compose.ymlにhttps-portalを追加
environmentのDOMAINSにhostsで指定したものと同じものを指定

```docker-compose.yml
:
:
  https-portal:
    image: steveltn/https-portal:1
    ports:
      - '80:80'
      - '443:443'
    links:
      - web
    restart: always
    environment:
      DOMAINS: 'devsite.local -> http://web:3000'
      STAGE: 'local'
    volumes:
      - ./https-portal:/var/lib/https-portal
```


## config/environments/development.rb

許可するホストにDOMAINSにhostsで指定したものと同じものを指定

```
:
:
  config.hosts << "devsite.local"
```

## docker-compose buildとdocker-compose up -d
ビルドしてコンテナを起動させる

```
docker-compose build
docker-compose up -d
```

### 以下のエラーが出た場合

```
Error response from daemon: Ports are not available: exposing port TCP 0.0.0.0:80 -> 0.0.0.0:0: listen tcp 0.0.0.0:80: bind: address already in use
```

localで既にPort80が利用されているので、開発中は一時的に停止させるようにする

* portの状況確認
```
$ sudo lsof -i -P | grep "LISTEN"
httpd       138           root    4u  IPv6 0x6e905bbde2bd865d      0t0    TCP *:80 (LISTEN)
httpd       401           _www    4u  IPv6 0x6e905bbde2bd865d      0t0    TCP *:80 (LISTEN)
：
：
```

* localで動いているapacheの一時停止

```
$ sudo apachectl stop
```

* 再度コンテナを起動させてみる

```
docker-compose up -d
```

## httpsでアクセス

`https://devsite.local/`でアクセスし、railsの画面が表示されるかを確認

![スクリーンショット 2023-01-31 0.14.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248644/3c0533b1-e25d-870e-beb6-6fe4d4ffc483.png)
`micromamba` じゃ長すぎるので `umamba` で使えるようにしたときのメモ

# `micromamba` タイポしがち

何度も `micromamba` と入力していると結構タイポしてしまいます。
micromamba, micromabma, mciromamba, micromamab, micromamba...



```bash: $ micromamba

                                           __
          __  ______ ___  ____ _____ ___  / /_  ____ _
         / / / / __ `__ \/ __ `/ __ `__ \/ __ \/ __ `/
        / /_/ / / / / / / /_/ / / / / / / /_/ / /_/ /
       / .___/_/ /_/ /_/\__,_/_/ /_/ /_/_.___/\__,_/
      /_/

Version: 1.2.0
```

`micromamba` を実行すると表示されるロゴ「μmamba」
μ（マイクロ）ってよく「u」で代用されるし、というか micromamba のソースの中では umamba と省略されていますし、 `umamba` で実行できてもよいのでは？と思いました。
`umamba` なら短いうえに、 `u` の後に `mamba` を入力するようなタイピングになるので変なタイポも減りそうな気がします。

## `umamba` で使えるようにする

まずは `micromamba shell init` して `micromamba` を使えるようにします。
そうするとシェルをフックするためのスクリプトが作成されるのでそれを編集します。

### bash

bash（Git bash）から `umamba` で使えるようにするには、
`$MAMBA_ROOT_PREFIX/etc/profile.d/micromamba.sh` に設定を追記をします。
`umamba` が `micromamba` のエイリアスとなるようにすればよいので

```sh
umamba() {
    micromamba "$@"
}
```

この3行を適当な場所に挿入してください。
↓こんな感じにすればOKです。

```sh: micromamba.sh

__mamba_exe() (
    "$MAMBA_EXE" "$@"
)

__mamba_hashr() {
    ...
}

__mamba_activate() {
    ...
}

__mamba_reactivate() {
    ...
}

micromamba() {
    ...
}

umamba() {
    micromamba "$@"
}

if [ -z "${CONDA_SHLVL+x}" ]; then
    ...
fi
```

手元にMacがないのでzshは確認できてません。

### コマンドプロンプト

コマンドプロンプトでは `.bat` ファイルを呼び出して `micromamba` を実行しています。
`%MAMBA_ROOT_PREFIX%\micromamba\condabin\mamba_hook.bat` の中に `.bat` を呼び出せるようにマクロを割り当てている部分があるのでそこに `umamba` の設定を追加します。

```batch: mamba_hook.bat
@IF DEFINED CONDA_SHLVL GOTO :EOF

@FOR %%F in ("%~dp0") do @SET "__mambabin_dir=%%~dpF"
@SET "__mambabin_dir=%__mambabin_dir:~0,-1%"
@SET "PATH=%__mambabin_dir%;%PATH%"
@SET "MAMBA_BAT=%__mambabin_dir%\micromamba.bat"
@FOR %%F in ("%__mambabin_dir%") do @SET "__mamba_root=%%~dpF"
@SET "MAMBA_EXE=F:\micromamba\_micromamba_bin\micromamba.exe"
@SET __mambabin_dir=
@SET __mamba_root=

@DOSKEY micromamba="%MAMBA_BAT%" $*
@DOSKEY umamba="%MAMBA_BAT%" $*

@SET CONDA_SHLVL=0
```

`@DOSKEY umamba="%MAMBA_BAT%" $*` を追記するだけでOKです。

PowerShellは割愛

***

最近また新しい対応コマンドも追加で実装されたみたいですね。（`micromamba env create` とか）
バイナリをダウンロードして `micromamba shell init` するだけで使えるようになるし、 (base)環境のこともあまり気にしなくてよいので、 `micromamba` いいですよね。
Amplify.ymlに記載されている「amplifyPush --simple」が何者か調査した結果

サンプルや公式マニュアルのAmplify.ymlに「amplifyPush --simple」が記述されていますが、よくわからなかったため調査してみました。


## 公式マニュアル

公式マニュアルには、以下の通り記載があります。

>amplifyPushこのコマンドは、バックエンドのデプロイに役立つヘルパースクリプトです。以下のビルド設定によって、現在のブランチにデプロイする上で適切なバックエンド環境が自動的に判別されます。

https://docs.aws.amazon.com/ja_jp/amplify/latest/userguide/build-settings.html

## Classmethodさんの記事

みんなが参考にするClassmethodさんの記事にも以下の通り記載があります。

>ビルド設定を修正すれば良いようなので、AWS管理コンソールのAmplifyコンソールを開いて「アプリの設定 > ビルドの設定」からamplify.ymlを修正します。修正箇所はfrontend.phases.build.commandsの箇所です。
>
>以下のようにamplifyPush --simpleを追加します。

https://dev.classmethod.jp/articles/add-amplify-auth-to-angular-app/

## Amplify Docs

しかし、不思議なのは、以下のAmplify Docsに全く説明がないことです。

https://docs.amplify.aws/

## GitHub

GitHubを確認したところ、現在は、中身が空っぽのスクリプトとなっていました。
以前のブランチを見ると、いろいろな処理をしていたようですが。

```bash:amplifyPush.sh
# This script has been deprecated. Please refer to https://docs.amplify.aws/cli/usage/headless/ to run headless scripts in your build system.
```

https://github.com/aws-amplify/amplify-hosting/blob/main/scripts/amplifyPush.sh

以下のスクリプトを使用するようにとのことです。

https://docs.amplify.aws/cli/usage/headless/
アルゴリズムについて

# アルゴリズムの概要
アルゴリズムとは「目的の達成にいたるまでの処理の一連の流れ」のこと。

例）プログラム（自動販売機）の場合
投入された金額を表示　→ 購入できる飲み物のボタンを点灯　→ 押されたボタンの飲み物を排出　→お釣りがある場合はお釣りを排出

↑
上記流れがアルゴリズム

# アルゴリズムの3つの基本構造
アルゴリズムが「処理の流れ」である以上、そこには「流れの向き」がある。
アルゴリズムには、流れを規定する3つの基本的な構造がある。

・順次実行：決まった順番に処理を行うこと
・条件分岐：条件によって処理を切り替えること
・繰り返し：処理を繰り返すこと、ループ処理ともいう

これらを一般的に「制御構造」と呼ぶ。
【NestJS】【JEST】【RabbitMQ】単体試験入門

# 前提
- RabbitMqを使った単体試験を検討している方向け

# はじめに
省略

# 参考
略

### テストソース
```TS
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from '../app.module';
import client, { Connection, Channel, ConsumeMessage } from 'amqplib';
import { TestService } from './test.service';

let app: INestApplication;

const queue: string = 'km-queue';

describe('InquiriesController with DB initialize', () => {
  //DBのセットアップを伴うテスト

  beforeEach(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    //await app.init();
  }, 30000);

  it('001: ', async () => {
    const connection: Connection = await client.connect(
      'amqp://guest:guest@localhost:5672'
    );
    const channel: Channel = await connection.createChannel();
    await channel.assertQueue(queue);

    channel.sendToQueue(queue, Buffer.from('message!!!'));

    const sleep = (waitTime) =>
      new Promise((resolve) => setTimeout(resolve, waitTime));
    console.log('sleep前');
    await sleep(25000); //ポイントはここ、ちゃんと時間を開ける必要がある
    console.log('sleep後');

    const testService = new TestService();
    await testService.queueTest();
    console.log('終わり');
  }, 40000);
});

```
### ソース
```TS
import { Injectable, OnModuleInit } from '@nestjs/common';
import client, { Connection, Channel, ConsumeMessage, connect } from 'amqplib';

const queue: string = 'km-queue';

@Injectable()
export class TestService implements OnModuleInit {
  onModuleInit() {
    this.queueTest();
  }
  constructor() {}

  public async queueTest(): Promise<void> {
    console.log('queueTest スタート');
    const consumer =
      (channel: Channel) =>
      (msg: ConsumeMessage | null): void => {
        if (msg) {
          console.log(msg.content.toString());
          channel.ack(msg);
        }
      };
    const connection: Connection = await client.connect(
      'amqp://guest:guest@localhost:5672'
    );
    const channel: Channel = await connection.createChannel();
    await channel.consume(queue, consumer(channel));
  }
}

```

# おわりに
手探りで考えている最中の備忘です。
bootstrapモーダル

## jsf bootstrapモーダルの部品化

```html
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:body>
        <ui:composition>
            <div id="confirm-modal" class="modal" tabindex="-1">
                <div class="modal-dialog">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">確認ダイアログ</h5>
                            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="confirmModalUtil.cancel()"></button>
                        </div>
                        <div class="modal-body">
                            <p id="confirm-modal-message">確認メッセージ</p>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn btn-secondary"  onclick="confirmModalUtil.cancel()">キャンセル</button>
                            <button type="button" class="btn btn-primary" onclick="confirmModalUtil.ok()">OK</button>
                        </div>
                    </div>
                </div>
            </div>
            <script type="text/javascript">
                var confirmModalUtil = {
                    _callback: null,
                    open: function (message, callback) {
                        this._callback = callback;
                        $("#confirm-modal-message").text(message);
                        $('#confirm-modal').show();
                    },
                    ok: function () {
                        this._callback();
                        $('#confirm-modal').hide();
                    },
                    cancel: function () {
                        $('#confirm-modal').hide();
                    }
                };
            </script>
        </ui:composition>
    </h:body>
</html>
```

## モーダルの表示

```js
confirmModalUtil.open("確認ダイアログてすと", function(){
  console.log('あいうえお');
});
```
Macのsedコマンドで上書きする方法

## はじめに

Macで以下のように`sed`コマンドを実行するとエラーとなります。  

```terminal
$ cat sample.txt
sample
sample
sample
sample
sample
$ sed -i 's/sample/EXAMPLE/' sample.txt
sed: 1: "sample.txt": unterminated substitute pattern
```

これを回避する方法について記載します。  

## 上書きする方法

以下のように実行することで上書きできます。

```terminal
sed -i '' 's/sample/EXAMPLE/' sample.txt
```

### `GNU sed`をインストール

上記のコマンド以外に`GNU sed`をインストールすることでエラーを回避できます。  

```terminal
brew install gnu-sed
```

インストール後に以下のように実行すると上書きできます。  

```terminal
gsed -i 's/sample/EXAMPLE/' sample.txt
```

`gsed`コマンドを`sed`コマンドとして使用したい場合には`~/.zshrc`に以下を追記します。  

```~/.zshrc
alias sed='gsed'
```
vue-select(v-select)の描画が更新されなかった件

## 環境
- Nuxt 3.0.0
- vue-select 4.0.0-beta.5

## 内容
#### やりたかったこと
複数選択可能で`taggable`にしている`vue-select` に対して、v-modelの分解バージョン(値の流し込み(props)と更新イベントの発火(input))を設定したかった。

#### やったこと

```vue
<v-select
    :value="ゔぉげゔぉげ"
    @input="ほげほげ"
    taggable
    multiple
    :options="state.lists"
    label="name"
    ..
    ..
    >
```

#### 起きたこと
v-selectの描画が更新されなくて、選択値が画面にでてこない

#### 原因
結局、[これ](https://v3.ja.vuejs.org/guide/migration/v-model.html)でした。
vue3では`:value`とかは廃止になって、`:model-value`っていう書き方になったんですね。  

確かにそうだったなと思うのですが、vue2の書き方で慣れていたし、パッとみた感じvue-selectのドキュメントもまだ更新されていないようだしで、ハマりました。

### 備考
自分ももうアラフォーエンジニアとなってるし、新しい書き方を覚えてられなくなってきたのかな。。
若いエンジニアたちはこんなにハマらないかも。
Docker初心者のメモ書き

# 概要
Docker初心者の自分は調べる事が多いですが、その中でもこれはメモしておきたいなと思った内容を簡単にメモに残しておきたいと思います。
Docker初心者の方が調べる前に一旦ここを見ようと思って頂けるようにしたいです。
が、あくまでメモです。
※ 都度更新していきたいと思います

# 内容
## docker-compose.yml更新時の反映方法
docker-compose upに以下のオプションを足す
※ -dは無くても良いかも？

`docker-compose up -d --build`
Azure Private Link 経由でWebAppにアクセスする

## Azure Private Linkとは
Azure Private Link を使用すると、仮想ネットワーク内のプライベート エンドポイント経由で Azure PaaS サービス (Azure Storage、SQL Database など) と Azure でホストされているサービスにアクセスできます。
仮想ネットワークとサービスの間のトラフィックは、Microsoft のバックボーン ネットワークを経由して、パブリック インターネットからの公開を排除します。
※[公式ドキュメントより](https://learn.microsoft.com/ja-jp/azure/private-link/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/df93087f-0a23-0b0e-8331-153067f912d9.png)

## 構築してみた

### 環境構築

#### 仮想ネットワークの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/4d4d045f-aa8b-6898-b565-bc1c1d61f2e5.png)

#### サブネットの作成
今回はvNetを作成した時にデフォルトで用意されるものを使用します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/b49945bb-7530-3cf4-4d23-ac24c895e651.png)

#### 結果確認用のVMを作成
デフォルトサブネット内にVMを作成します。
閉域環境を実現するためにパブリックアクセスは無効にし、パブリックIPも割り当てません。
この後WebAppの画面をブラウザで確認できるようにWindows Serverで作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/512c008d-36d9-0c72-66de-d0dce2f9bdc0.png)

#### WebAppを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/e233a326-55ec-5da7-90a3-4fb0cbb91b00.png)

ランタイムは何でもよいですが、Private Endpointを利用するにはBasic以上である必要があります（Freeはダメ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/9f69b631-df42-457f-b7fa-1752863728bf.png)

パブリックネットワークアクセスは無効にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/5dc03339-beed-4203-f9b2-520991c0e41d.png)

#### プライベートエンドポイントの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/d6826409-1a4e-a8fc-9c1d-8b38a9a5b21f.png)

WebAppの「ネットワーク」から「プライベートエンドポイント」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/5b543757-54f2-0d02-a275-d41c29791f7a.png)

先程作成したvNetとサブネットを選択
プライベートDNSゾーンはネットワーク内でWebAppのアクセス時にプライベートIPで名前解決するために必須です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/037a40d9-99f5-5a90-605c-30713ad05bfb.png)

これでリソースグループ内にプライベートエンドポイントのサービスとプライベートIPをもったNICが作成されます。
プライベートDNSゾーンも作成され、自動的にWebAppのホストとプライベートIPがマッピングされていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/35c767ef-7e4d-5716-6c7e-fc6a11dc52a5.png)

### アクセスしてみよう
作成したVMにログインします（方法は何でも大丈夫ですが今回はBastionで接続します）

EdgeでWebAppアクセスし、10.4.0.5でアクセスできていれば成功です。
（DeveloperツールはCtrl + Shift + i）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/d7bf4b1a-ad51-ddc8-8e48-c2aafa46629f.png)
コードの共通化について数名に聞いてみた

皆様の考えをコメントなどで聞かせていただけるとありがたいです｡

# 注意
* 自分用のまとめ
* 文章力皆無
slackでの履歴が消えてしまうまえにまとめておこうと思った｡

# ことの始まり
自分でコードを書いている時に以下のようなことを経験した
* 共通化したら複雑化させてしまった｡
* 共通化しよう-> やっぱりやめよう -> やっぱり共通化しようと繰り返した｡

共通化するしないはどうすればよいのかと思い調べ以下のサイトにたどりついた

https://jp.quora.com/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%8A%E3%81%84%E3%81%A6%E5%85%B1%E9%80%9A%E5%8C%96%E3%81%99%E3%81%B9%E3%81%8D%E3%82%B1%E3%83%BC%E3%82%B9%E3%81%A8%E3%81%9D%E3%81%86

そして､所属しているコミュニティでも同じ質問をしてみた｡


# 参考サイトの軽いまとめ
コミュニティでの回答の前に参考サイトのいくつかのサイトを軽くまとめる

## 回答者1
**共通化することで得られるメリットと、共通化によって生ずるデメリットを予想を含めて比較し、得すると思われる方を選ぶ。**

メリットの量は呼び出し箇所に比例して増大する｡
仕様変更やバグによるコード修正の可能性がなければ縮小される｡
共通化切り出しをしやすいように、メリットが引き出せデメリットが顕在化しにくいように、普段から設計なりコーディングなり技術選択の工夫をしておくことが重要｡

#### メリット
* バグや仕様変更があったときの修正の一元化
* 似て非なるコードが複数あることで、なにかにつけ目を皿のように比較しなければならなくなることを避ける
* コード削減

#### デメリット
* 将来の状況変化、未知の事実の発見により、本当は共通ではないことが判明したとき分岐が複雑化する。もしくは手戻り。
* パラメータ化による複雑さの増加。テストバリエーション組み合わせ的増加、カバレッジ低下
    * 汎用性が高く、機能が多ければ、インターフェースの複雑さは増す。この3つはトリレンマの関係にある。
* 複数のモジュールから使われるなにかの配置場所は自明ではない。util,common?方針を決めておかないと乱雑になる。
* 名前の付け方に迷う。
* 依存性の複雑化。
* 修正の影響が読みきれなくなる可能性。
* いろいろな箇所から呼べるように汎用性を高めたくなるが、それに引っ張られすぎると無駄な工数になる。

## 回答者2
**経験と勘で共通化するかどうかを決める**


どんなものでも再利用にはコストがかかる｡
適用できるかどうかはどうやって判断するのか
個人でも沢山あると戸惑うのにグループだとさらに困難になる､そして管理を他人にも合わせる必要がある｡
プログラムは文章であり､ただでさえ個人の属性が大きいのに他人にあわせるとさらにストレスが貯まる。
他人の思想を理解するにはその人と沢山話す必要があり｡
アジャイルのみえない効率の良さはここら辺も発揮される。

トップダウンで大上段にやるより
* 個人や対面できるグループ程度でフォルダ分け
* コメントをひっかっける
* プロセスくらいはわかるタグをつける
それくらいで共通化へのリソースはあきらめ、拾えたらラッキー程度に留めとくのが吉

## 回答者3
**テストドリブンで進めるのであれば同じ処理が複数現れるかどうかで決める**

ただし､システムの規模やメンバー､費用､言語､将来改修していくのか作り直す可能性などいろいろ考慮する点が多い。
やり過ぎるとシステムを複雑にして新メンバーが理解するのに時間がかかりトラブルシューティングするのに時間がかかる。

共通化するということは汎用性もしいられるので、通常よりも考慮する部分が多くなる。
拡張性も考えておかないと､似たような共通モジュールが沢山できてしまうので事前に検討して方針を決めておく必要はある。

# コミュニティでの回答
3名の方に回答していただけた

## miさん
共通化＝設計の成果物のルールの作りのキモかなと思っているので、共通化の基礎は大事にしている。

## inさん
**基準としては仕様変更の多さとか再利用性の高さの必要さ（利用パターンが増えそうか）や想定される利用頻度とかがある｡**

一般的にはテストやCSSのスタイルなどについては共通化しすぎないほうが良いというのは言われている

初めての機能でまだ再利用するかも怪しい段階や共通化して作るか迷った場合は、変にDRYを意識しすぎずにYAGNIとしてできるだけシンプルに（単一責任は厳守して）作ってしまい、2~3個似たような要件が出来てからはじめて共通化を『リファクタリング』として後から考えたほうが良いケースが多い

## ikさん
**単一責任の原則**を守る

達人プログラマーに以下のようなことが書かれている。
>DRY原則は「知識」や「意図」の二重化についての原則です。つまり、異なった場所(おそらくはまったく異なった場所)に同じことを表現するという問題を避けるための原則です。

※この方は別サイトで解説しているので以下のサイトをみた方がわかりやすい

https://jp.quora.com/%E6%9C%80%E8%BF%91-DRY%E5%8E%9F%E5%89%87%E3%81%AE%E3%82%84%E3%82%8A%E3%81%99%E3%81%8E%E3%82%84%E5%AE%89%E6%98%93%E3%81%AA%E5%85%B1%E9%80%9A%E5%8C%96%E3%81%AF%E8%89%AF%E3%81%8F%E3%81%AA%E3%81%84%E3%81%A8%E8%81%9E/answers/397245134

# 駄文(おまけ)
#### 自分自身の考え
私も結局､なれや経験からしか判断ができないと思う｡
ぼくのかんがえたさいきょうのArduinoを作る/①構想編

Arduinoを扱っていると「こんなボードがあったらいいのになぁ」と思うことが多々あります。

そこで、ズバリ **"ぼくのかんがえたさいきょうのあるどぅぃーの"** を作ろう！という企画を気長にやって行こうかな〜と思います。

# アイデアを整理
まずは脳内で渦巻く ***卍最強卍*** たるアイデアを整理します。

- MCUはCortex-M7
- USBポートはTypeC
- 既存OSSの資産を活用可能

大まかな柱はこの辺でしょうか。

オリジナルとは言っても、全くのゼロから始めるのも骨が折れるので、せっかく偉大な先人様方が切り拓いてくれた既存の資産は活かしたいものです。

そして、僕が今まで扱ってきたボードのうち [ItsyBitsy M4](https://www.adafruit.com/product/3800) や [Trinket M0](https://www.adafruit.com/product/3500) など、Adafruit社のMicrochip ATSAM MCUに馴染みが深いので、そちらに寄せて行く感じになりのかな、とふんわり思っています。

あと自分のユースケースを振り返ったとき、ボードから音を出したりアナログデバイスを接続したりと、今までMCU内蔵DACを使用する頻度が割と多かったので、DACも欲しいところです。
(ATSAMにはDACが内蔵されています)

「最強MCUならESP32があるじゃん」という声が聞こえてきそうですが、僕は ***卍Cortex-M原理主義卍*** なので宗教上の理由でNGです😩

# 構成
アイデアも出揃ったところで、実際に具体的なところを考えていきたいと思います。

## MCU
まず頭脳となるMCUですが、これはCortex-M7とATSAMを条件とすると、自ずと導き出せます。

- [SAM Family - Microchip](https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus/sam-32-bit-mcus)

![](https://media-s3-us-east-1.ceros.com/microchip-technology/images/2022/01/31/37c89e8be054b22043cc4cce58ac4c04/220127-mc32-sam-mcu-overview-9x5-5in.jpg)

このマトリクスを見てもらえれば一目瞭然ですが、つまり候補は以下の2つに絞れます。

- ATSAMS70
- ATSAME70

V70は車載アプリケーション用途なので除外するとして、S70とE70はどちらも汎用で一見すると似通ったスペックですが、実は細かいところが違います。

![](https://www.microchip.com/en-us/products/microcontrollers-and-microprocessors/32-bit-mcus/sam-32-bit-mcus/sam-e/_jcr_content/root/responsivegrid/container_2034953330/image_55496342.coreimg.jpeg/1646110575297/170516-mc32-diag-sam-e70-7x5.jpeg)

ベースとなるのはS70で、それに加えてCAN通信とEthernet通信、つまるところネットワーク周りが追加されたものがE70となります。

大は小を兼ねるということで、使用するのは **E70** で良い気がします。

## ボード
ボードについては、第一に既存のエコシステムへしれっと溶け込めることが目的となります。
つまり寸法やピンアサインなどのフォームファクタをなるべく揃えたいです。

そこで白羽の矢が立つのは [Adafruit Feather](https://www.adafruit.com/category/943) です。
実際に、Featherはエコシステムとして充分な程に成熟しており周辺機器も多いですし、僕自身も普段ありがたく使わせてもらっています。

そして何より、幸いなことにFeatherはCADデータが公開されているため、拝借して改造できれば越したことはありません。

## ブートローダー
実はこれが今回のプロジェクトにおいて最大の壁かもしれません。

既にどこかしらの製品として搭載された実績のあるMCUであれば、ブートローダーは基本的に流用可能です。
現にATSAMD21は公式からサードパーティまで様々なボードに採用されているため、各メーカーが公開しているファームウェアを使用することができます。

しかし2023/01現在、僕が調べた限りではATSAME70/S70を搭載したボードはありませんでした。

まじかぁ...と思いましたが、一縷の希望が現れました。

- [adafruit/uf2-samdx1 - GitHub](https://github.com/adafruit/uf2-samdx1)

もうAdafruit様々ですね、今後も御布施していきます🙇

これはAdafruit社製のATSAM系ボードに搭載されているブートローダーです。
元々はMicrosoftのIoTプロジェクト「PlatformIO」が起原となります。
それをAdafruitがフォークし自社製ボードへカスタマイズしたものとなります。

ではなぜこれが希望かというと、元々このブートローダーはATSAMD21しか対応していませんでした。
しかしATSAMD51/E54などの高性能なMCUが入手しやすくなり、それらを搭載したボードが登場するにつれ、当然ながらブートローダーも改良されていきました。
D21はCortex-M0+でD51/E54はM4Fです。

つまりこれは、ATSAMファミリー内であれば、ある程度は流用できることを意味しており、E70も行けるんじゃないか！？と淡い期待を抱いたわけです。

# 次回「半導体不足ってレベルじゃねーぞ」
さて、とりあえず方向性はざっくり決まったので、まずは部品を注文するところから始めたいと思います。

...

![20230130_231726.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253070/05e667d1-0bfa-8d34-b07a-e0f3a6eb3714.jpeg)

![](https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSmD2RmpkrV4Y0q4F4DBubAseZTEOine-91tw)

次回へ続く...!
SES with App Runner で TimeoutError

# 背景
App Runner が VPC に対応してからストレージへのスマートなアクセスが可能になりました。
VPCコネクターを PrivateSubnet 内に設定して RDS への接続に成功。
ついでに SES でメール送信もできるようにしておきたいということで早速 `TimeoutError`で躓くわけです。

# 課題
App Runner の送信向けのネットワーキングで、PrivateSubnet を設定しているので、当然外部への経路がありません。
そのため、メール送信先に接続できずにタイムアウトとなります。

さて、ここで先人の知恵をお借りします。

[ASP.NET Core + Amazon SES な Web システムを App Runner でホスティングし、ネットワークパターンごとにメール送信してみた](https://dev.classmethod.jp/articles/app-runner-asp-net-core-outbound-smtp-ses/)

ふむふむ。
NatGatewayは料金的にもやや心配な面もあるのでVPCエンドポイントを設定してみます。

しかし、ここで新たな問題に直面します。

```
hostname: 'email.ap-northeast-1.amazonaws.com',
...
Error: connect ETIMEDOUT xxx.xxx.xxx.xxx:443
```

VPCエンドポイントは間違い無く正しく設定したはずなのですが、接続できません。
他にも原因があるようです。



# 解決
調査を進めていくと、VPCエンドポイントのプライベートDNS名に目が行きました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22939/7cd9cb02-f60e-f83c-7275-94ed51f10283.png)


**!!!**
あなたは気が付いたでしょうか。
エラーログのFQDNとプライベートDNS名が異なることに。

はい、ここでやっと答えが分かりました。

:::note warn
VPCエンドポイントは、SMTPエンドポイント用しか無い！
:::

というわけで、VPCエンドポイントを使いたければSMTPエンドポイント（SMTP認証）を使ってメール送信しましょう。
或いは、APIエンドポイントを使いたければ、NatGateway を使いましょう。



# 追加解説
SES でメール送信する方法は２つあります。
1. SMTPエンドポイントを利用して送信
1. APIエンドポイントを利用して送信

SMTPエンドポイントを利用する場合、SMTP認証での送信になるのでIAMユーザーのアクセスキーが必要になります。
その反面、APIエンドポイントは利用するリソースにロールを設定すれば送信できるのでセキュリティ的には圧倒的に後者の方が良いのです。

流出したときのダメージが大きいので、アクセスキーの発行は可能な限り避けたいところですね。

# 一言
`email-smtp.ap-northeast-1.amazonaws.com` と `email.ap-northeast-1.amazonaws.com` の違いに気が付けたのは良い勉強になりました。