OmniAICreator/Qiita-1.07M huggingface dataset:
ロジクールマウスが反応しない！？

# 概要
はじめまして！Panta Rheiの川﨑です！
突然，私の愛用しているロジクールマウスが反応しなくなってしまいました．しかし，別のパソコンの場合接続ができたため，解決方法をいくつか試した結果，ドライバーが原因と判明し直すことができました！

# 起きたこと
パソコンを起動して，カーソルを操作しようとしたとき，カーソルが見つからず，マウスが動かないことが判明した．
今使っているマウスです．

https://gaming.logicool.co.jp/ja-jp/products/gaming-mice/g703-hero-wireless-gaming-mouse.910-005645.html

# 試したこと
#### 以下のことを試し，原因がドライバーにあることがわかった
- マウスが動かない原因がパソコンにあると考え，再起動
- 別のパソコンにマウスを接続してマウスの確認をしたがしっかりと動いている
- 別のマウスを取り付けたときは，カーソルが動いている事がわかった
- Logicool G HUBを起動して接続しているか確認したが接続されていない(以下URL)
- 設定のBluetoothとデバイス>デバイスから確認するとドライバーエラーの文字が表示されていた

https://gaming.logicool.co.jp/ja-jp/innovation/g-hub.html

# 結果
ドライバーエラーが起きていたため，ドライバーを入れ直して再起動することで，無事復活した．

# 終わりに
モノが動かなくなったとき，すぐ新しいモノにするのではなく，動かなくなった原因を探して直せそうだったら自分で直したほうが達成感があるのでおすすめです！
独占的な方法: Outlook の古い PST 連絡先リストを VCF に変換する

<p>今日のデジタル世界では、アドレス帳は欠かせない存在です。幸いなことに、メール プログラムである Outlook は、会社のすべての連絡先リストを管理するのに役立ちます。ほぼすべての電話やデバイスで動作する vCard を使用すると、連絡先リストを保存できます。すべての連絡先にどこからでもアクセスできます。その結果、ユーザーは Outlook から vCard に連絡先をエクスポートする必要があります。そこで、Softaken vCard エクスポートおよびインポートが役立ちます。</p>
<p>この記事では、Outlook の連絡先を vCard として保存する簡単な手順を説明します。vCard は、ほぼすべての電話やコンピューターで動作する小さなアドレス帳なので、連絡先を誰とでも簡単に共有できます。</p>
<h2><strong>VCF ファイルの利点</strong></h2>
<p>次のセクションでは、vCard ファイルを使用する利点をいくつか説明します。これにより、Outlook から vCard に連絡先をエクスポートできるようになります。</p>
<ul>
    <li>従来の紙の名刺よりも早く連絡先情報を提供したい場合、vCard は理想的な選択肢です。</li>
    <li>メモ帳などのシンプルなプログラムを使用すると、追加のソフトウェアを必要とせずに vCard を開くことができます。</li>
    <li>共有は簡単です。携帯電話、タブレット、コンピューターから、電子メール、テキスト メッセージ、またはその他の任意の手段で送信できます。</li>
    <li>デバイスに関係なく、ほぼすべてのデバイスで vCard を使用できます。</li>
</ul>
<p>Outlook で直接実行できない場合でも、連絡先をエクスポートする簡単な方法をいくつか紹介します。<br>では、できるだけ早く接続を変更してみましょう。</p>
<h3><strong>Outlook の連絡先は 2 つの異なる方法で vCard 形式に変換できます</strong></h3>
<p>Outlook の連絡先を vCard として自動または手動で保存できます。最初に手動の方法を説明した後、すべてを一度に、より迅速に実行する方法を説明します。</p>
<h3><strong>1. Outlook の連絡先を手動で VCF にエクスポートします。</strong></h3>
<ul>
    <li>Outlook を起動したら、まずナビゲーション バーに移動します。</li>
    <li>次に、「ユーザー」(Outlook 2013 の場合) または「連絡先」(Outlook 2007 ～ 2010 の場合) を選択します。</li>
    <li>次に、vCard としてファイルに保存する連絡先を選択します。</li>
    <li>「ファイル」に移動し、今すぐ「名前を付けて保存」を選択します。</li>
    <li>次に、ファイルに名前を付け、保存場所を選択します。</li>
    <li>さらに、「ファイルの種類」で「vCard ファイル (*.vcf)」を選択します。</li>
    <li>連絡先を vCard としてエクスポートするには、最後に「保存」を押します。</li>
</ul>
<p>この例では、Outlook から vCard への連絡先の手動エクスポートを完了しました。Outlook の連絡先ファイルが多数ある場合は、上記の方法を適用するには、前の手順をもう一度実行する必要があります。さらに、次のソリューションの手順に従うには、Microsoft Outlook アプリケーションをダウンロードする必要があります。エクスポート プロセスを簡単に完了するには、次のテクニックを使用します。</p>
<p>出力 VCF ファイルを取得したら、vCard ファイルに重複があるかどうかを確認します。重複がある場合は、Softaken VCF 重複削除ツール を使用してください。簡単に削除できる重複は、データに影響を与えません。</p>
<h3><strong>2. OutlookからVCF連絡先の自動抽出方法</strong></h3>
<p><strong>Softaken vCard エクスポート インポー</strong>トは、最も人気があり成功しているソフトウェアです。これを使用すると、ユーザーは <a target="_blank" rel="noopener noreferrer" href="https://www.softaken.com/jp/vcard-export-import"><strong>Outlook の古い PST 連絡先リストを VCF に簡単に変換</strong></a>できます。さらに、ユーザーはプレビュー ウィンドウを使用して、送信する連絡先ファイルを選択し、評価できます。さらに、時間制限付きで選択的な変換を実行することもできます。このプログラムは、すべての Windows バージョンで適切に動作します。さらに、グラフィック ユーザー インターフェイスにより、初心者でも簡単に指示に従うことができます。</p>
<h3><strong>vCard はどのようにして Outlook の連絡先に変換されますか?</strong></h3>
<p>あなたの不安を和らげるために、このウィザードがどのように機能するかについて説明します。</p>
<ul>
    <li>まず、デスクトップに保存し、Softaken vCard エクスポート インポート ツールを使用します。</li>
    <li>次に、vCard に変換する PST ファイルまたはフォルダーを選択できます。</li>
    <li>ファイル形式として「VCF」を選択すると、連絡先は vCard に対応します。もう一度、「次へ」をクリックします。</li>
    <li>次に、変換したファイルを保存する場所を選択します。</li>
    <li>完了したら、「変換」をクリックしてプロセスを開始します。</li>
</ul>
<h3><strong>終了時間</strong></h3>
<p>Outlook の連絡先から作成された vCard を使用できるようになりました。相手がどのようなテクノロジーを使用しているかに関係なく、誰にでも簡単に送信できます。Outlook の連絡先を 1 つずつ手動で vCard に変換する方法もありますが、特に転送する連絡先が多数ある場合は、vCard を使用して連絡先をインポートする方が望ましいオプションであることに留意してください。</p>
PowerShellからエクスプローラーを開く

```powershell
function exp($p = ".") { explorer.exe (Resolve-Path $p)[0].Path }
```

絶対パスじゃないと指定したフォルダを開いてくれないので`Resolve-Path`を使ってます。
ドラッグ・アンド・ドロップしたい時に便利。
github　リモートリポジトリで特定のファイルのみ削除したい

# githubでリモートリポジトリ上から特定のファイルのみ削除する方法

補足：以降のusernameは自分のgithubのユーザー名に置き換えて読んでください

# 削除手順

１該当のファイルを削除する前にリポジトリのクローンを作成する（まだない場合）
```
git clone https://github.com/username/repository.git
```
2リポジトリに移動する
```
cd repository
```
3ローカルリポジトリからファイルを削除する
```
git rm src/App.css
```
※src/App.cssは削除したいファイルのパスを入れてください

4変更をコミットする
```
git commit -m "Remove specific file"
```
5リモートリポジトリにpushする
```
git push origin main
```
※mainはリモートリポジトリのブランチ名です。

完了
「Composeの基本レイアウト」のメモ#3 ~SearchBarの実装~

### [3. プランを立ててから開始する](https://developer.android.com/codelabs/jetpack-compose-layouts?hl=ja#2)
#### 作成するアプリの構造
+ ScreenContent(3つの構成要素でできる)
    + Search bar
    + Align your body section
        + 水平方向にスクロール可能な行で表示される「Align your body」要素
    + favorite collections section
        + 水平方向にスクロール可能なグリッドで表示される「Favorite collection」カード
### [4. 検索バー - 修飾子](https://developer.android.com/codelabs/jetpack-compose-layouts?hl=ja#３)
#### 検索バーの作成に必要な要素
+ `TextField()`コンポーザブル
    + `value`パラメータ
        +  TextFieldに表示されるテキストの現在の状態を保持
    + `onValueChange`パラメータ
        + テキストが変更されたときに呼び出されるコールバック関数を受け取る
    + `leadingIcon`パラメータ
        + `Icon()`コンポーザブル
        + TextField の先頭に表示されるアイコンを設定
        + 関数を受け取る
    + `colors`パラメータ
        + TextField の色の設定をカスタマイズ
    + `placeholder`パラメータ
        + TextField が空のときに表示されるプレースホルダーテキストを設定
        + 関数を受け取る
    + `modifier`パラメータ
        + 検索バーの高さ=56.dp →　`modifier.heightIn(min = 56.dp)`
            + コンポーザブルが特定の最小の高さを持つように設定
        + 幅は親の幅いっぱい　→ `modifier.fillMaxWidth()`
            + 検索バーは親の水平方向のスペースをすべて占有
        + 一方の修飾子が幅に影響し、もう一方の修飾子が高さに影響するため、これらの修飾子の順序は重要でない
```Kotlin
//最小構成
fun SearchBar(
    modifier: Modifier = Modifier
) {
    TextField(
        value = "",
        onValueChange = {},
        leadingIcon = {},
        colors = TextFieldDefaults.colors(),
        placeholder = {},
        modifier = modifier
            .fillMaxWidth().heightIn(min = 56.dp))
    // Implement composable here
}
```

#### Android Studioの補完機能を利用したleadingIconの設定
```Kotlin
        leadingIcon = {
            Icon(
                imageVector = Icons.Default.,
                contentDescription = null
            )
        },
```
上記のように記述すると、Android Studioの補完機能で必要なライブラリをインポートできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/18161035-134e-5bfc-45bd-7a36ab65a04a.png)

1. Iconの上にマウスカーソルを持っていく
1. importを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/c6d10d66-dcd9-0e7d-ca5f-9bc0505ba860.png)

1. @Composable　Icon(imageVector:~ を押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/af0a79ee-6224-2b2c-4ea3-683e69373673.png)
1. Icons.Default.Search以外のエラーが消える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/3da155f7-b448-b260-932b-3cda0d447fea.png)

同様に赤字のところにカーソルを持っていき、importを行なえばエラーを解消できる。

#### 背景色とplaceholderの設定
+ surface色は、アプリ全体で共通して使用される色の一つであり、ボタン、カード、モーダルなどのコンポーネントの背景色として使用される
+ MaterialThemeの色を使用することで、開発者は独自の色を設定する手間を省き、デザインの複雑さを減らすことができる
+ placeholderはTextコンポーザブルを使用して設定する
【AWS】CodeDeployを使ったデプロイが何をしてもうまく行かなった件

# 初めに
現在以下のハンズオンの「AWS Code サービス群を活用して、CI/CD のための構成を構築しよう！」でCICD構築を行っている。
https://aws.amazon.com/jp/events/aws-event-resource/hands-on/

途中苦戦しながらも何とかCodeDeployでデプロイするところまで来たのだが、以下のように失敗をした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/b4363597-c36d-5cbd-5e25-c1b01b9b844f.png)

ちなみに今回の(私の場合の)前提条件は以下である。
・EC2インスタンスやCodeBuildなどの設定はハンズオン参照
・EC2インスタンスにはSSH接続している


# 原因を探る
まずエラーの原因を探ろうとしたのだが、コンソール上だと詳細が見つけられなかったため、黒画面で確認してみることにした。以下のコマンドでログを確認する。もちろんSSH接続した状態で。

```ruby:cmd
sudo tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log
```

すると以下のエラーを確認できた。
```
InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please check if this instance was started with an IAM instance profile
```

どうやら必要なIAMポリシーが足りないとのこと。そこで、EC2インスタンスのIAMロールを開いて、必要だと言われるポリシーを追加する。ちなみにここはChatGPT君に聞いた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/da9221a3-7f68-2a6d-3bf6-bf2e9cc256e6.png)

実際に追加したのはAmazonEC2RoleforAWSCodeDeployとAmazonS3ReadOnlyAccess(オプション)である。これで多分大丈夫だろうと再度デプロイを行う。

# 見落としていたこと
上記でもうまく行かない。IAMロールの更新はEC2インスタンスの再起動は必要ないはず…と思いながらインスタンス再起動しても同様の結果。
考えているうちに以下の神記事を見つけた。

https://techblog.forgevision.com/entry/2020/07/16/210647

こちらによると、**CodeDeploy Agentを再起動する**という手順が足りなかったようだ。
再度黒画面にてsudo systemctl restartでサービスを再起動、systemctl statusで起動状態の確認を行った。

```ruby:cmd
sudo systemctl restart codedeploy-agent.service
systemctl status codedeploy-agent.service

```

その結果、無事デプロイも成功し、index.htmlがサーバーに上がったことも確認できた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/25b8b15b-e164-dae8-817f-28b6a6350794.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/c22ad06b-aeb2-50ed-9d2c-5522f15450a3.png)

EC2インスタンスのパブリックアドレスへアクセスすると、index.htmlの中身が表示されていることが分かる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2521217/3a2d93d8-7805-2055-4379-15dff199c91a.png)


# 終わりに
今回のCICD構築はgitコマンドやサーバーのことを知っていないと難しいなと感じた(幸いその辺りは少し知識があったので何とかなったが…)
とりあえず無料枠終わる前にハンズオン全て終わらせるぞ！
Serverless Framework デプロイで作成したリソース群を削除する

## 概要

Serverless Frameworkのコマンド`$ serverless deploy`でAWSに作成したリソースを削除する方法を簡単にまとめる。

## 情報

リソースの削除はserverless.ymlの情報を元に行われる。
そのため筆者のように「設定ミスでバージニア北部にリソース作ってしまって、その後東京に切り替えた」場合でバージニア北部と東京の両方のリソースを削除したいときはserverless.ymlの記載を修正し、本手順を2回実施する必要がある。

## 前提

下記の方法で構築

https://qiita.com/miriwo/items/ba8c93e71e34519fa2bd

## 方法

- 下記を実行してプロジェクトのルートディレクトリに移動

    ```sh
    cd test-project
    ```

- 下記を実行してAWSのリソースを削除

    ```sh
    serverless remove
    ```

- 下記の様にでたのでおそらくリソースは削除されていると思われる

    ```sh
    Removing "test-project" from stage "dev" (ap-northeast-1)

    ✔ Service test-project has been successfully removed (60s)
    ```

ちゃんと削除されていたので完了

※筆者は間違えてバージニア北部にもリソースを作ってしまったのでserverless.ymlのproviderのregionを削除して`$ serverless remove`を実行した。
[OutSystems]Entity ActionのCreateにあるId項目には何を渡すのか（質問箱から）

[質問箱でもらった質問](https://peing.net/ja/q/56636d69-d567-44b3-9742-23daffc48cf1)に対する回答。

質問箱だと画像を貼れないので、詳細はQiitaでまとめる。

# 質問箱でもらった質問
> CRUDアクションでsourceを渡してCreateをすると思うのですが、クリエイトする時点でIDは決まってないと思います。どうやってしょりするのですか？

## シンプルな回答
EntityのId項目はAuto Number=Yesに設定されていると思うので、その場合は、NullIdentifier()を渡しましょう。
Auto Number=Noであれば、自分で任意の値を渡します。例えば、既存のレコードの最大値を取ってその+1するとか。IdがText型ならGUIDを生成して渡す手もありますね。

# Entity Actionとは
Entityを作成すると、自動で用意される、CRUD操作用のAction群。以下の赤枠部分（ちなみにこれはOutSystems 11のもの。ODCではいくつかActionが増えている）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/40cf2160-cbff-6a3c-97a9-42b0514cf112.png)

# OutSystemsのIdについて
ドキュメント（何故か2024/07/15時点では日本語訳がなかったが）：
[Entities > Primary Key - OutSystems 11 ドキュメンテーション](https://success.outsystems.com/ja-jp/documentation/11/building_apps/data_management/data_modeling/entities/#primary-key)

OutSystemsのIdはデフォルトではLong IntegerかつAuto Number=Yesで作成される。

ドキュメントには記載がないが、試してみたところ、主キーとして選択できる型は、Integer、Long Integer、Textのみ。

Auto Number=Yesにすると、レコード作成時に、自動で次のIdを計算して設定してくれる。これがデフォルトでYesなので、通常はレコード作成時に明示的にIdを渡す必要がない。

なお、OutSystemsでは、複合主キーを作成することはできない。

## 任意のAttributeをIdにする手順
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/c76f6ebe-23e0-ee66-500e-ee0ee071e866.png)
Service Studio上で、
1. Entityのプロパティから、「Indexes and more」をクリック
1. 開いたダイアログ上で、「More Options」の右にあるアイコンをクリックして展開
1. Identifier Attributeで、Idにしたい属性を選択

# IdがIntegerやLong IntegerでAuto Number=Yesの場合の渡し方
Entity型変数のId属性には、以下の通りNullIdentifier()を渡せば良い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/3f45c542-437d-f39d-3d40-88f6364cd385.png)

なお、Input ParameterにEntityやStructure型が渡されている場合、Action呼び出しプロパティ上で直接編集できる。このとき、Auto Number=YesのIdは編集対象に表示されない。

以下は↑と同じCreateのEntity Action呼び出しプロパティの、Source左の「+」をクリックして展開したところ。Idが編集対象に出てこない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9e5652f0-d001-df3c-c118-8720d614f190.png)

なお、AutoNumber=Yesの場合に明示的に値を渡しても無視され、自動発番される。

## AutoNumber=YesならNullIdentifier()でなく0を渡すのは有りか
これはやめておいた方が良い。
たしかに、現状の仕様では、NullIdentifier()は0を返している。
しかし、NullIdentifier()を渡すことで、ここでは、明示的に空のId値を指定していること保守担当者の目に明らかであるため。

# IdがIntegerやLong IntegerでAuto Number=Noの場合の渡し方
この場合は自分で任意の（既存のIdと重複しない）Idを渡す。
警告を避けるため、「IntegerToIdentifier()」か「LongIntegerToIdentifier()」で変換すること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/90503bf0-77ed-21ea-ebdd-30e5e658b45b.png)
メルカリShops APIの使い方

メルカリShops APIは、メルカリShopの作業を自動化するツールを開発することができるGraphQLのAPI。API連携という申請をしないと利用できないため、APIを利用して自動化したい場合は、API連携しているシステムを提供しているサービスを利用するしかない。

https://engineering.mercari.com/blog/entry/20221121-mercari-shops-api/

「API連携」しているシステムを提供しているサービス一覧

https://support.mercari-shops.com/hc/ja/articles/16849943532697-API%E9%80%A3%E6%90%BA%E3%81%97%E3%81%A6%E3%81%84%E3%82%8BEC%E4%B8%80%E5%85%83%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%92%E6%95%99%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84

メルカリShops APIでは、下記のようなことが可能。
 - 商品の登録、更新、削除、参照
 - 商品在庫の登録、更新、参照
 - 注文の完了処理、キャンセル、参照
 - 取引メッセージの追加、参照
 - Webhookによる注文イベントのリアルタイム受信

## APIドキュメント
メルカリShopsのGraphQL APIのドキュメント

https://api.mercari-shops.com/docs/index.html?_gl=1*iujxi8*_gcl_au*MTM5MDg4NTI1OC4xNzIwOTY3NjM2*_ga*MTQxMDY3MjAwNC4xNzIwOTY3MTI2*_ga_4NLR7T2LEN*MTcyMDk2NzEyNi4xLjEuMTcyMDk2NzY3Ni42MC4wLjA.#introduction

こんな感じでリクエストする。GraphQLなので、リクエストにjsonキーでjsonスキーマの文字列を指定する。
```Python
import requests
import json

AccessToken = '****************************************************'
url = "https://api.mercari-shops.com/v1/graphql"
headers = {
    "Authorization": "Bearer %s"%AccessToken,
    "Content-Type": "application/json",
    "User-Agent": "myapp/0.0.0"
}

query = """
query shop {
  shop {
    businessKind
    createdAt
    description
    id
    name
  }
}
"""

response = requests.post(url, headers=headers, json={"query": query})

if response.status_code == 200:
    print(response.json())
else:
    print('API Error:', response.status_code, response.text)
```

## APIキー取得方法

1. メルカリShopsの管理画面へログインし、[設定]をクリックします
   [メルカリShopsの管理画面](https://mercari-shops.com/signin/seller?_gl=1*stgt1z*_ga*MTQxMDY3MjAwNC4xNzIwOTY3MTI2*_ga_4ZSVGRP1ZE*MTcyMDk2NzEyNi4xLjEuMTcyMDk2NzYyOS4xMi4wLjA.*_ga_4NLR7T2LEN*MTcyMDk2NzEyNi4xLjEuMTcyMDk2NzYyOS4xMi4wLjA.&back_path=%2Fseller%2Fshops)
1. [APIアクセストークンの発行]をクリックします
1. トークン名へ「GoQSystem」と入力し、[トークンを発行する]をクリックします
1. 3で発行されたトークンをコピーします
※トークンは発行直後のみコピーできます。一度でもリロード/画面遷移をするとコピーできなくなるため、忘れずにコピーしてください。
※トークンは10個まで作成できます。10個を超える場合は古いものを削除したり、すでに発行したものを再利用する等で対応してください
Facebookコネクタについて

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめA～M](https://qiita.com/Keiji_otsubo/items/f3ddedee6793bf1576f8)

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


+ [現在、このコネクタで使用可能な追加のオプションはありません。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmJgk)

:::note
英語ですが、以下に同じような質問がありますが、解決してないみたいです。

Facebook Social Connector not showing business page - anyone find a fix?

Tech Provider verificationの話題が出ていますが、これってユーザの設定ではないような気もします。

技術提供者アプリのアクセス認証プロセスの運用開始

I did notice that Facebook is now asking for a Tech Provider verification since we are trying to connect apps (Pardot social connector). However, we didn't create the app so I can't get the verification but Facebook will block all APIs without it. Has anyone run into that? I assume that could be the culprit. When I spoke with Salesforce help, they did say other customers were experiencing the same issue but had no resolution for it.
:::
Serverless Framework 特に設定せずデプロイしたらバージニア北部のlambdaにデプロイされた

## 概要

下記の方法で新規のプロジェクトを作成し、`$ serverless deploy`を実行したところバージニア北部のリージョンでlambdaの関数が作成された。
東京リージョンにデプロイするように設定する方法をまとめる。

## 前提

下記の内容が完了していること。

https://qiita.com/miriwo/items/ba8c93e71e34519fa2bd

## 方法

- serverless.ymlを開き、providerにregionを追加し、東京リージョンを設定

    ```serverless.yml
    # "org" ensures this Service is used with the correct Serverless Framework Access Key.
    org: shun0104
    # "app" enables Serverless Framework Dashboard features and sharing them with other Services.
    app: test-serverless
    # "service" is the name of this project. This will also be added to your AWS resource names.
    service: test-project
    
    provider:
      name: aws
      runtime: nodejs20.x
      region: ap-northeast-1
    
    functions:
      hello:
        handler: handler.hello
        events:
          - httpApi:
              path: /
              method: get
    ```

- 下記を実行してデプロイ

    ```sh
    serverless deploy
    ```

- 下記のように出たのでおそらく東京リージョンのデプロイできているはず

    ```
    Deploying "test-project" to stage "dev" (ap-northeast-1)

    ✔ Service deployed to stack test-project-dev (97s)
    ```

- 念の為確認したらちゃんと東京リージョンにデプロイされていた

    ![CleanShot 2024-07-15 at 13.35.40@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/02b460d2-1959-15f3-e7e7-8a4c2b92aba7.png)
【ChatGPT＋Code Interpreter】できたアニメGIFを圧縮します。


　どうも、カーブミラーです。

　今回は、できたアニメGIFを圧縮します。

:::note info
本記事は、ChatGPT（有料版）
で行なっております。あしからず。
:::

　まずは、ニュース。

　NTT東西、
　　紙の「タウンページ」廃止へ。
　　　電話帳130年の歴史に幕。
　　　　[産経ニュースさんポスト](https://x.com/Sankei_news/status/1812653305639649559?t=Ifn2ORRZobKyGadwJ2MoCA&s=19)

　まぁ、自家電も公衆電話も
　　少なくなりましたからねぇ。
　　　企業側も載せるメリットを
　　　　見出せないでしょうし。

　さらば、
　　タウンぺージよ。
***
　次のニュース。

　OpenAIが、
　　AGI完成までの5段階を
　　　定義しました。

　1. チャットボット：自然な会話
　2. 推論：人間レベルの問題解決
　3. エージェント：自律的に行動を選択
　4. イノベーター：革新的な発明を支援
　5. 組織：組織全体の業務を遂行

　既にレベル２に近づきつつあり、
　　間違いなく数年でレベル５まで
　　　到達するだろう、とのこと。
　　　　[チャエンさんポスト](https://x.com/masahirochaen/status/1812639234236567704?t=cOpcbxPspZCw10Cl7AP7vg&s=19)
　　　　　（内容は一緒）
***
　さて、本題です。

　アニメGIFを圧縮します、
　　という話です。

　昨日（2024/07/14）の記事で
　　子犬のアニメGIFを
　　　作成しましたが、
　　　　QiitaにもX-Twitterにも
　　　　　アップできませんでした。

　そこで
　　ChatGPTさんに尋ねました。
　　　やり取りをどうぞ。
***
***user***
（アニメGIFをアップロード）
このアニメGIFは、ファイルとしておかしいですか？　ツイッターにアップできないのですが？

***ChatGPT***
アニメGIFがTwitterにアップロードできない問題を解決するために、まずファイルの内容とサイズを確認する必要があります。ファイルを確認して問題点を特定します。

ファイルを確認しますので、少々お待ちください。

（解析を待ちます）

確認したところ、このGIFファイルは以下の通りです：

- フォーマット: GIF
- サイズ: 1024 x 1024 ピクセル
- アニメーション: あり
- フレーム数: 36
- ファイルサイズ: 約18.8 MB

TwitterではGIFファイルのアップロードに制限があり、特にファイルサイズが5MB以下である必要があります。このGIFファイルは18.8MBと大きすぎるため、アップロードができないのが原因です。

解決策として、GIFファイルのサイズを圧縮する必要があります。圧縮を試みますので、少々お待ちください。

（圧縮処理）

圧縮した結果、新しいGIFファイルのサイズは約5.25MBになりました。これでTwitterにアップロードできる可能性が高まりました。

新しい圧縮ファイルを以下に提供します：

[圧縮されたGIFをダウンロード]

こちらのファイルを試してみてください。

***user***
どのような圧縮を？

***ChatGPT***
圧縮の方法として以下の手順を行いました：

1. **画像サイズの縮小**: 元のGIFの各フレームの解像度を1024x1024ピクセルから512x512ピクセルに縮小しました。これにより、ファイル全体のピクセル数が減少し、サイズも小さくなります。

2. **最適化**: GIFファイルを保存する際に、最適化オプションを使用しました。これにより、無駄なデータを削除し、ファイルサイズをさらに小さくしました。

3. **フレーム数の維持**: 元のフレーム数（36フレーム）はそのまま維持しましたが、フレームの解像度を下げることで全体のサイズを削減しました。

この手法により、元の約18.8MBから約5.25MBに圧縮することができました。このサイズならばTwitterにアップロードできる可能性が高いです。

具体的な手順としては、以下の通りです：

- 各フレームを取得
- フレームを512x512ピクセルにリサイズ
- 新しいサイズのフレームを元に新しいGIFを作成し、最適化オプションを適用

この方法で、画像の見た目を極力損なわずにファイルサイズを削減することができました。
***
　おかけで
　　X-Twitterにもアップロードできる
　　　サイズになりました。

　尋ねてみるものですね。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
[Swift] lexicographicallyPrecedes メソッド

## 標準メソッド [lexicographicallyPrecedes(_:)](https://developer.apple.com/documentation/swift/array/2853083-lexicographicallyprecedes) を使いました

> Returns a Boolean value indicating whether the sequence precedes another sequence in a lexicographical (dictionary) ordering, using the less-than operator (<) to compare elements.


長さの違う配列同士を辞書式で大小比較できるメソッドで、`Intの二次元配列`を辞書順ソートできちゃいます。

<br>このメソッドのおかげで、[ABC219-C](https://atcoder.jp/contests/abc219/tasks/abc219_c) をこんな短いコードで実装できます。
実質、`ans=`の1行です。

```swift:lexicographicallyPrecedes(_:)使用例
let abc219_c: () = {
    let X = readLine()!
    let N = Int(readLine()!)!
    let S = (0 ..< N).map { _ in readLine()! }
    let ans = S.map { $0.map { X.firstIndex(of: $0)! } }
        .sorted { $0.lexicographicallyPrecedes($1) }
        .map { String($0.map { X[$0] }) }
    ans.forEach { print($0) }
}()
```

[オンライン実行はこちら](https://paiza.io/projects/e/Qrs82b6paX-P2d2UI_46Wg?theme=twilight) [<img width="80" alt="" src="https://paiza.io/assets/paizaio_logo_s-9bd1bf73a17e2002f96a6337f2fb71f9.png" />](https://paiza.io/ja)

<br><br>Swift言語には、まだまだ便利なメソッドがありそうです。


---

https://developer.apple.com/documentation/foundation



### これまでの Swift 関連記事

https://qiita.com/nak435/items/777a5bc0dcc1f1c5e3dd

https://qiita.com/nak435/items/81ebf1f89074cce5a1c5

https://qiita.com/nak435/items/8d9a4ecde92b4632c846

https://qiita.com/nak435/items/62d41edbe3258ba94258

https://qiita.com/nak435/items/49e5ea2c9cd947eed4de

https://qiita.com/nak435/items/e609ae2f54a42e4821b8

https://qiita.com/nak435/items/e94d27f3f2d3fb44ef19

https://qiita.com/nak435/items/24e67a2bd26e2c8495ec

https://qiita.com/nak435/items/c88210de341895f12605

https://qiita.com/nak435/items/53049f9f7ed8be4219a4

https://qiita.com/nak435/items/e044daa296532912a424

https://qiita.com/nak435/items/fdfbab4cd7b75b5f260a

https://qiita.com/nak435/items/0b21513569e22f9ca339

https://qiita.com/nak435/items/48bfb133e1e56ac8ae75

https://qiita.com/nak435/items/52fbe4ad49e37e2018c7

https://qiita.com/nak435/items/3496843ccb26b4d2306a

https://qiita.com/nak435/items/422bfdaccd7121c20467

https://qiita.com/nak435/items/d6d9782d43c5e948447b

自分への備忘録でした。。。

**以上**
マイグレーションで使用するadd_indexの役割について

## 経緯
Railsチュートリアルを進めていく中で、マイグレーションファイルにadd_indexという記述を行なっていましたが、具体的に使い方がいまいちわからなかったため、調べた結果をまとめます。

## add_indexがなぜ必要なのか
結論から言うと、データベースの処理を高速化できるから。
通常該当のデータをデータベースから検索する際には、DBは１から１０まで全てのデータを検索し、該当のデータが存在するかどうかを検索します。（フルスキャン）
add_indexがあると、検索しやすいようにデータを並び替え、必要なデータを取得しやすくできるようになります。（木構造という検索方法でデータを並び替えています。このあたりの説明は、アルゴリズムのお話になるので今回は省略します。）
Railsチュートリアルでは、Twitterのようなユーザーをフォローする機能、される機能を作成していますが、これらを登録するカラムを作成する際に、インデックスを設定しています。高い頻度でアクセスするこれらのデータに追加することで、DBにかかる負荷を軽減し、レスポンスを高速でできるようになります。
```
class CreateRelationships < ActiveRecord::Migration[7.0]
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps
    end
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    add_index :relationships, [:follower_id, :followed_id], unique: true
  end
end
```

## まとめ
add_indexを追加することで、データベースの処理を高速化できることがわかりました。
ただし、データの数がそもそも少ない場合は、フルスキャンの方が短時間で検索することができます。
実際に作成するデータの規模に合わせて実装することが大事だということがわかりました。

参考
[【Rails】 マイグレーションファイルを徹底解説！](https://pikawaka.com/rails/migration)
[【Rails】一意性を設定するのにuniqueness: trueだけで満足してはいけない](https://zenn.dev/atsumu22/articles/69173f1cb5e880)
「Jetpack Compose の基本」のメモ#9 ~IconButtonコンポーザブルの使い方~ 

### [13. 最終仕上げ](https://developer.android.com/codelabs/jetpack-compose-basics?hl=ja#12)
#### ボタンをアイコンで置き換える
+ ボタンをアイコンにしようするには、`material-icons-extended`アーティファクトを使用する
+ `app/build.gradle.kts(:app)`ファイルの依存関係に次の行を追加
```Kotlin
dependencies {
// 他の依存関係
implementation("androidx.compose.material:material-icons-extended")
}
```
+ `MainActivity.kt`に次の行を追加する
```Kotlin
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ExpandLess
import androidx.compose.material.icons.filled.ExpandMore
import androidx.compose.material3.Icon
```
JS 時間のフォーマットを整形する

JS のフォーマットを整形する

現在の時刻を取得する
```js
// 時間のObject
var date = new Date();
// 年を取得する
var year = date.getFullYear();
// 月を取得する（JavaScriptの世界に月は0から換算されるので　＋1が必要）
var month = date.getMonth() + 1;
// 日を取得する
var day = date.getDate();

// 時を取得する
var hour = date.getHours();
// 分を取得する
var minute = date.getMinutes();
// 秒を取得する
var second = date.getSeconds();
// ミリ秒を取得する
var millisecond = date.getMilliseconds();

```

ここまで、時間を取得するコードをまとめました。
これだけで、フォーマットを整形するができないので、メソッドを用意してもよいでしょう

```js
function formatDate(date, format) {
  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  var day = date.getDate();

  var hour = date.getHours();
  var minute = date.getMinutes();
  var second = date.getSeconds();
  var millisecond = date.getMilliseconds();

  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('hh', hour)
    .replace('mm', minute)
    .replace('ss', second)
    .replace('ms', millisecond);
}
```

引数のformatは任意のフォーマットを渡して、[String.prototype.replace](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace)で変換を行う

実行してみよう
```js
var d = new Date();
console.log(formatDate(d, 'YYYY-MM-DD hh:mm:ss'));

2024-7-15 12:14:18　のように出力される
```

ちょっと問題があるようですね、月のデータは一桁足りないよね、どうする？？？？
[String.prototype.padStart()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/padStart)メソッドを利用して、補填してもよいでしょう

ただ、取得してきた時間の型は全部intなので、Stringに変換する必要があり、コードの最終は以下になります。
```js
function formatDate(date, format) {
  var year = date.getFullYear().toString().padStart(4, '0');
  var month = (date.getMonth() + 1).toString().padStart(2, '0');
  var day = date.getDate().toString().padStart(2, '0');

  var hour = date.getHours().toString().padStart(2, '0');
  var minute = date.getMinutes().toString().padStart(2, '0');
  var second = date.getSeconds().toString().padStart(2, '0');
  var millisecond = date.getMilliseconds();

  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('hh', hour)
    .replace('mm', minute)
    .replace('ss', second)
    .replace('ms', millisecond);
}

var d = new Date();
console.log(formatDate(d, 'YYYY-MM-DD hh:mm:ss'));

2024-07-15 12:43:02のように出力される
```

以上、また次回.....
【Go言語】部分文字列

# はじめに

スライスや配列をスライス化する際に、メモリリークが発生する可能性がありますが、文字列でも同様の事象が考えられます。(スライスについては以下を参照)

https://qiita.com/twrcd1227/items/989d8d553fc6913f01f3

# 部分文字列

```go
func main() {
	s1 := "Hello"
	s2 := s1[:5]
	fmt.Println(s2) // Hello
}
```

`s2`は`s1`の部分文字列となっている。ただし、最初の5つのruneからではなく、5バイトから文字列を作成している。

ちなみに、runeについては以下で詳しく解説しています。

https://qiita.com/twrcd1227/items/45d3fb4be5bce334fae9

エンコードすると複数バイトのruneになる場合は、上記のような部分文字列は使用してはいけない。

[Go Playground](https://go.dev/play/p/8Ki9LZvuCzG)

```go
func main() {
	s1 := "こんにちは"
	s2 := s1[:5]
	fmt.Println(s2) // こ��
}
```

まず、[]runeに変換しなければいけない。

[Go Playground](https://go.dev/play/p/b6ByyazKBwM)

```go
func main() {
	s1 := "こんにちは"
	s2 := string([]rune(s1)[:5])
	fmt.Println(s2) // こんにちは
}
```

# 部分文字列とメモリリーク

以下のコードは、ログメッセージを文字列として受け取る。メモリに保存するログは、最初に36文字のUUIDでフォーマットされて、その後にメッセージ自身が続く。最新のn個のUUIDのキャッシュを保存することができる。これらのログメッセージは、サイズが大きくなる可能性がある(最大数kbyte)。

```go
func (s store) handleLog(log string) error {
	if len(log) < 36 {
		return errors.New("log is not correctly formatted")
	}
	uuid := log[:36]
	s.store(uuid)
	// Do something
	return nil
}
```

UUIDを取り出す際に`log[:36]`で部分文字列演算を使用している。

Goの仕様では、部分文字列の操作を行う場合、結果の文字列と部分文字列の操作に関わった文字列が同じデータを共有すべきなのかは規定されていない。Goのコンパイラは、両者が同じ規定配列を共有しており、新たな割り当てとコピーを防いでいる。

`log[:36]`は同じ基底配列を参照する文字列を新規作成するので、メモリに格納されるかくuuidは36byteだけではなく、元のログ文字列のバイト数になる。

この問題は、以下のように部分文字列を[]byteに変換し、文字列に変換することで、コピーすることで解決する。

```go
uuid := string([]byte(log[:36]))
```

Go1.18以上では、標準ライブラリに文字列の新たなコピーを返す`strings.Clone`が存在する。
`strings.Clone`を使って、以下のようにすると、メモリリークを防ぐことができる。

```go
uuid := strings.Clone(log[:36])
```

# まとめ

* 部分文字列では、スライスの範囲はバイト数に基づいており、runeの数ではない
* 部分文字列は同じ基底配列を共有するので、メモリリークになる可能性がある
* メモリリークは`strings.Clone()`か文字列の変換によってコピーを行うことで解決する

# スライド

<script defer class="speakerdeck-embed" data-id="52b0d477d76f4bbc93c81c428a4afc80" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

# 参考文献

1. [100 Go Mistakes and How to Avoid Them](https://100go.co/ja/#41)
jsにおけるオブジェクトの受け取り方

jsではオブジェクトを受け取って、受け取ったオブジェクトのキーでアクセスできます。
なので下記のように、複数のプロパティを持ったオブジェクトを渡せます。
```js
const hoge = (obj) => {
  console.log(obj.a) // 1
  console.log(obj.b) // 2
}

hoge({a:1,b:2})
```

jsではキーワード引数の概念はないですが、上記のようにすることで、キーワード付きで渡すかのごとく、引数を設定できます。

Options Objectパターンというデザインパターンなんですね
https://typescriptbook.jp/reference/functions/keyword-arguments-and-options-object-pattern

```js
// オブジェクトひとつだけを引数に持つ関数
function func(options) {
  console.log(options.x, options.y, options.z);
}
 
func({ x: 1, y: 2, z: 3 });
```
任意の数のバックアップデータのみを保持する方法

# 前提
前提として，linuxでのバックアップを想定します．

# 任意の数のバックアップデータのみ保持する方法
ディレクトリ名を日付の名前としてデータを毎日バックアップする際，バックアップデータを任意の数に維持する方法を紹介します．

ディレクトリ名を日付の名前とする方法は以下の通りです．
```
mkdir "[バックアップディレクトリのアドレス]/$date_dir/$vm_name"
```

この作成したディレクトリにバックアップデータをコピーしていき，新しいバックアップデータを残し古いバックアップデータを削除する方法が以下の通りです．
```
ls -r [バックアップディレクトリのアドレス] | tail -n+[残したいバックアップデータの数] | while read delete_date
do
  echo "delete_date=$delete_date"
  rm -rf [バックアップディレクトリのアドレス]/$delete_date
done
```
例えば，tail -n+6とすると，最新のバックアップデータから5つのデータのみが常にディレクトリに保持されます．

実行した結果，実際に5つのディレクトリのみが保持されています．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1814188/838ccecc-40f4-b6c0-3013-d45452d9e5f8.png)
何日前の日付をPythonで調べる

# 今日の○日前はいつ？

"何日前" という情報から、それが何月何日なのかをPythonで調べてみた。
Excelの方が早いじゃん、とか言わないでください。コマンドラインで起動できるPythonを使えばExcelの起動を待っている間に答えが出る！かな？(笑)

対話モードを起動して、
```python
Python 3.12.4 (tags/v3.12.4:8e8a4ba, Jun  6 2024, 19:30:16) [MSC v.1940 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> t = datetime.datetime.today()
>>> t
datetime.datetime(2024, 7, 15, 12, 14, 35, 98633)
>>> t - datetime.timedelta(days=15)
datetime.datetime(2024, 6, 30, 12, 14, 35, 98633)
>>> t - datetime.timedelta(days=100)
datetime.datetime(2024, 4, 6, 12, 14, 35, 98633)
>>>
```
datetime.datetimeの括弧の中はdatetime.datetime(年, 月, 日, 時, 分, 秒, マイクロ秒)を表しているので、今日(2024年7月15日)の15日前は6月30日、100日前は4月6日

```python
>>> str(t - datetime.timedelta(days=100))
'2024-04-06 12:14:35.098633'
```
文字列に変換すると一般的な日時表示になるので、この方が見やすいかも。
[Dify]モデレーションの機能を使ってみた。

## はじめに

モデレーションとはなんでしょうか？コトバンクでしらべてみました。

>１ 節度。適度。穏健。中庸。
２ ブログやSNS、インターネット上の記事に投稿された読者によるコメントに対し、管理者が内容をチェックしたり、別の読者が評価付けをしたりすること。また、その仕組み。不適切な投稿を除外するはたらきがある。モデレーション機能。
[コトバンクから引用](https://kotobank.jp/word/%E3%83%A2%E3%83%87%E3%83%AC%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3-676216) 


つまりモデレーションとは、不適切な内容を排除して節度を保った使い方をするためのものです。
Difyでは、キーワードでのモデレーション、OpenAIでのモデレーション、自前で作ったモデレーションAPIでモデレーションの３つができます。

使い所と、キーワードとOpenAIでのモデレーションの方法を書いていきます！


## モデレーション機能の使い所

ざっとモデレーションを使うシーンが思い付きます。
※いくつか内容的にはかぶるものがありますが、意味的には異なるので分けて書いているものがあります。

- 不適切なコンテンツの排除
    - 暴力、性的内容、違法行為などを検出可能
    - カスタムキーワードで特定の不適切な表現をフィルタリング可能
- 法令遵守
    - カスタムキーワードや敏感語審査拡張で、特定の法的要件に対応可能
- ブランド保護
    - カスタムキーワードを使用して、ブランドに関連する不適切な表現を検出可能
- セキュリティ対策
    - プロンプトインジェクションを起こしそうな一部の悪意のある内容を検出可能する
- コミュニティガイドラインの遵守
    - カスタムキーワードや敏感語審査拡張で、特定のガイドラインに沿ったモデレーションが可能
- 文化的配慮
    - カスタムキーワードを使用して、文化的に敏感な表現をフィルタリング可能

考えれば考えるほどモデレーションは必要なものですね。


## モデレーション設定方法
では実際にDifyで設定してみましょう。
以下の画像の手順でモデレーション機能を有効にしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/1118859f-9581-a02f-d4cd-6bdba4335eb9.png)


### キーワードでモデレーション
では最初にキーワードでモデレーションしましょう。
今回は「きのこの山」に規制をかけたいと思います。以下のように設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/d79ccf0f-6d19-6565-052f-7b688348265f.png)

では試してみましょう！
「きのこの山とたけのこの里はどちらが好きですか？」と聞いてみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/e258fc37-76b9-c8ed-433f-a360864335c4.png)

しっかり規制が入ってますね。「きのこの山」が燃えたことを教えてくれました。

### OpenAIでモデレーション
次に、OpenAIのモデレーションを使ってみましょう。
こちらがモデレーションしてくれる内容は決まっています。以下を確認してみてください。

https://platform.openai.com/docs/guides/moderation/overview

<details><summary>モデレーションする内容(日本語版)</summary>

| カテゴリー | 説明 |
|------------|------|
| hate | 人種、性別、民族、宗教、国籍、性的指向、障がいの有無、カーストに基づく憎悪を表現、煽動、または促進するコンテンツ。保護されていないグループ (チェス プレイヤーなど) を対象とした憎悪的なコンテンツは嫌がらせです。 |
| hate/threatening | 人種、性別、民族、宗教、国籍、性的指向、障害の有無、またはカーストに基づいて、対象グループに対する暴力または深刻な危害も含む憎悪的なコンテンツ。 |
| harassment | あらゆる対象に対する嫌がらせの言葉を表現、煽動、または促進するコンテンツ。 |
| harassment/threatening | 対象者に対する暴力や重大な危害も含む嫌がらせコンテンツ。 |
| self-harm | 自殺、自傷行為、摂食障害などの自傷行為を促進、奨励、または描写するコンテンツ。 |
| self-harm/intent | 発言者が自殺、自傷行為、摂食障害などの自傷行為を行っている、または行うつもりであることを表明するコンテンツ。 |
| self-harm/instructions | 自殺、自傷行為、摂食障害などの自傷行為を奨励したり、そのような行為を行う方法についての指示やアドバイスを与えるコンテンツ。 |
| sexual | 性行為の描写など、性的興奮を喚起することを目的としたコンテンツ、または性的サービス（性教育およびウェルネスを除く）を宣伝するコンテンツ。 |
| sexual/minors | 18歳未満の個人が含まれる性的コンテンツ。 |
| violence | 死、暴力、身体的傷害を描写するコンテンツ。 |
| violence/graphic | 死、暴力、身体的傷害を詳細に描写したコンテンツ。 |

</details>

では以下のように設定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/0b01dc17-0fd9-3240-679d-80f4b14b1f52.png)

では実際に規約に違反しそうなことを言ってみます。

:::note alert
あんまり悪いことを言うとOpenAIからBANされてしまう可能性があるので、みなさんは入力注意です！！
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376115/20a3dcf7-e329-e035-60e9-98e8316da23f.png)

いい感じにモデレーションされてます！いいですね！


## 最後に
Xやってるので気になる方はフォローお願いします。

https://x.com/hudebakonosoto
ターミナルで直前にいたディレクトリに戻る

ターミナルで作業しているときに間違って```/```だの作業していたディレクトリと全く関係ないディレクトリに移動したときに戻るのが面倒でイラっとしていました。

## 解決策
```sh
cd -
```
これだけ。

これで間違って移動してしまった時もイラっとしなくて済む…。
ESXiでsshクライアント機能を有効化

SSHクライアントサービスが有効になっているかどうかを確認する。
'Disabled' の場合は 'False' を返します。

```
esxcli network firewall ruleset list --ruleset-id sshClient
```

SSHクライアントを有効にします。
```
esxcli network firewall ruleset set --ruleset-id sshClient --enabled=true
```

関連。

https://nakoruru.jp/fyi-esxi-scp-firewall-setting/
ChatGPTにLisp形式でプロンプトを投げる実験

## はじめに

最近、ChatGPTにLisp形式でプロンプトを投げると精度が向上するという噂を耳にしました。私も、この現象に興味を持ち、実際に試してみることにしました。
この記事では、その実験結果と考察を共有します。

## 実験内容

ChatGPT（GPT-4モデル）に対して、以下の2つの形式でプロンプトを投げてみました：

1. 自然言語形式
2. Lisp形式（Clojureベースの擬似コード）

## 実験結果

### 1. 自然言語形式のプロンプト

「吾輩は猫である」の序文をギャル語で生成して。

```回答
もちろん、ギャル語で「吾輩は猫である」の序文を生成しますね！
にゃんこである。名前とか、まだないし～。どこで生まれたか、マジで覚えてないんだけど～、チャラチャラした気分で、こんな感じでニャーニャー生きてるんだよね～。何て言うか、超可愛い猫として、人間たちの目には映ってるんじゃない？
こんな感じでどうですか？もっとギャル語っぽくしたり、他の要素を追加したい場合は教えてください！
```

### 2. Lisp形式のプロンプト

```lisp
(generate-gal-language-intro "吾輩は猫である")
```

```回答
了解しました。「吾輩は猫である」のギャル語版の序文を生成しますね！
はじめまして！ウチ、猫だよ〜☆名前とかねぇし、気にしないで〜！どこで生まれたとか、全然覚えてないんだけど、まあ、適当でいいっしょ！家族もいたっぽいけど、ウチ、一人の方が自由だし〜！そんな感じで、ヨロシクね〜☆
こんな感じでどうでしょうか？
```

## 考察
実験の結果、以下のような考察が得られました：

精度の向上は見られなかった：Lisp形式でプロンプトを投げても、自然言語形式と比較して特に精度の向上は見られませんでした。

自然言語処理の優位性：ChatGPTは自然言語処理に特化してトレーニングされているため、自然言語形式のプロンプトの方が解釈しやすい傾向にありました。

構造化された入力：Lisp形式は構造が明確で、プログラミング的な思考を促進する可能性があります。しかし、ChatGPTの現在の能力では、この利点が十分に活かされていないようです。

カスタム関数の解釈：実験では、generate-gal-language-introのような存在しない関数名でも、AIがコンテキストから推測して適切な応答を生成しようとする傾向が見られました。

トークン数の効率：Lisp形式は自然言語よりもコンパクトに表現できる場合があり、トークン数を節約できる可能性があります。

## まとめ
Lisp形式でプロンプトを投げることは、特定の状況下では有用かもしれませんが、現状のChatGPTモデルでは自然言語形式の方が適していると言えそうです。
しかし、この結果はあくまで現時点のモデルに基づくものです。AIの進化によっては、将来的にLisp形式や他のプログラミング言語形式のプロンプトがより効果的になる可能性もあります。
あとLispに慣れていないと、そもそも書けないってのもありますよね。
Lispは癖があるので習得すること考えたら自然言語でいいのかな！と思ったり。
GPTに再度Lisp形式にしてもらうってのも良いのかな？
色々試しましたが現状トークン数を抑える以外にはメリットを感じませんでした。

私のやり方が悪いだけなのかもなので、もし良い効率のよいLispプロンプトがあれば是非教えてください！
NFSを用いたシステムのアラート設定の注意点

NFSを用いたシステムのアラートの設定について自分の体験談から注意点をまとめておこうと思います．
意外と気づきにくいところなのでもし今後，NFSを用いてファイルやディレクトリを共有する時に意識するといいかもしれません．


### NFSとは
NFSとはNetwork File Systemの略で他のマシンのファイルやディレクトリを共有するシステムです．ファイルサーバに作成しデータをまとめたりする際に使用します．NFSはサーバとクライアントに分かれており，サーバ側のディレクトリを共有する形で使用します．割と簡単に利用できるのでぜひ使ってみてください．参考記事の1番でインストールできます．

### 実際に起きたこと
自分が使っていた構成を説明します．自分自身はWebサイト上にブログサイトを公開しようと思って6台のVMを用意していました．またその中でファイルを共有するためにNFSサーバとNFSクライアントでディレクトリを共有してました．


当時，PrometheusとNodeExporterを用いてそれぞれのVMのディスク使用率を監視していました．その際に実際に1から6台全てのVMでディスク使用率が高いよというアラートが一斉に出ました．これを最初に見た時，感じたことは「意味がわからん」とういことでした．なんで，1つのVMではなく同時に出るんだという感じでしたね．

当時Prometheusのアラートの設定を以下のようにしていました．
```yaml
- alert: node-monitoring-disk-usage-high
      expr: 1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes) >= 0.8
      for: 1m
      labels:
        severity: "warning"
```

Prometheusで監視できる対象全てのディスク使用率を見ていました．閾値は0.8です．つまり80%を超えた時にアラートが出ます．

例えば，/dev/mapper/ubuntu--vg-ubuntu--lvの部分を重点的に監視するとかかな．こうすればアラートの発生箇所も抑えられたよね．






### 原因
原因は結果的にNFSのサーバが原因でした．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3774424/91fe2418-b9af-42b3-e5b7-132e3293e78e.png)

どういうことかというと，NFSサーバとクライアントはディレクトリやファイルを共有します．その中で，NFSサーバがいるVMのディスクの容量が不足すると，共有している他のディレクトリも同様に容量が不足してるよとエラーが出ます．
NFSクライアント側の共有されているディレクトリを見てみると大体56%使用していますよね．
```
$ df -h
...
Filesystem                         Size  Used Avail Use% Mounted on
outside-nfs3:/home/cdsl/mysql       47G   25G   20G  56% /mnt
...
```

NFSサーバ側のディレクトリも/dev/mapper/ubuntu--vg-ubuntu--lが56%ですよね．つまりPrometheusはこの値を拾っていたことがわかります．
```
$ df -h
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              392M  1.2M  390M   1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   47G   25G   20G  56% /
tmpfs                              2.0G     0  2.0G   0% /dev/shm
tmpfs                              5.0M     0  5.0M   0% /run/lock
/dev/sda2                          2.0G  254M  1.6G  14% /boot
/dev/sda1                          1.1G  6.1M  1.1G   1% /boot/efi
tmpfs                              392M  4.0K  392M   1% /run/user/1000
```

これは集中型のシステムであるNFSだからこそ起こることなんでしょうね．このような場合アラートが全てのVMで出てしまうので修正箇所がわからないですよね．


これは大問題です！！！！！！！！！！

なのでPrometheusの設定もちゃんと変えるべきでした．

```yaml
- alert: node-monitoring-disk-usage-high
      expr: 1 - (node_filesystem_avail_bytes{instance = "NFSサーバのいるVMのIP"} / node_filesystem_size_bytes{instance = "NFSサーバのいるVMのIP"} ) >= 0.8
      for: 1m
      labels:
        severity: "warning"
      for: 1m
      labels:
        severity: "warning"
```


こんな感じで絞れればよかったですね．


### 最後に
この件で学んだことは監視する際に対象を分けてあげることの重要性と動いているものはなんなのか意識することですね．
僕もまだまだなんでこれからも頑張ります．



### 参考記事
1. https://www.server-world.info/query?os=Ubuntu_22.04&p=nfs&f=2
AWS Certified DevOps Engineer Professional 受験記録

# まず初めに
最初の投稿デビュー
月１回程度記事を投稿できるよう心がけていければと思います。

# 自己紹介
- エンジニア歴は26年目
- 20年はJavaを中心とした業務アプリケーション開発に従事
- 約6年前にAWSに関わるPJに参画したことがきっかけで、それ以降はクラウド基盤開発にシフト
- 現在は、Terraform で ネットワーク関連のリソースを構築している

# 保持しているAWS認定資格
- AI, ML関連資格以外は既に保持している
- 直近（2024年5月)に取得したのは、AWS Certified Advanced Networking Speciality

# 対象者
- これから、AWS Certified DevOps Engineer Professional を受験することを考えている方

# 本題
## 学習に利用したサイト
- Udemy
  - [AWS Certified DevOps Engineer Professional 2024 - DOP-C02](https://www.udemy.com/course/aws-certified-devops-engineer-professional-hands-on/learn/lecture/37903998#overview)
      - あまり経験がなく自信がなければこの講座はお勧めです。
      - ハンズオンがあり、実際に手を動かしながら学習できます。
  - [【DOP-C02対応】AWS認定 DevOpsエンジニア プロフェッショナル 模擬問題集＋詳解 【2024年版最新】](https://www.udemy.com/course/dop-c02aws-devops-2024/learn/quiz/6199904#overview)
    - 模擬試験講座
    - AWS や他クラウドでのCI/CD 経験の実績がある方は、こちらを主体に進めても良いと思います。

## どのように学習したか
- 学習時間は、約50時間から60時間程度
  - 平日に1〜2時間、休日に3〜4時間程度
- 今月に入るまでは主に、前述に記載の「[AWS Certified DevOps Engineer Professional 2024 - DOP-C02](https://www.udemy.com/course/aws-certified-devops-engineer-professional-hands-on/learn/lecture/37903998#overview)」 を受講
- 業務が気になり、資格試験勉強にあまり時間を割くことができず、1/5 を残して、模擬試験講座を実施
- 模擬試験は解答せずにすぐ終了し、各問題の正答に対し、どのような理由でその回答を導いているか解説文を確認し理解できていないところはノートしていた
- １回分の模擬試験を試験当日まで終始確認していた

## 受験の日程はどのように決めていたか
- なるべく集中力を維持したいため、土曜日と決めていた
- 普段の仕事は自宅でのフルリモートのため、気分転換も含めて必ず試験センターで受験するようにしている
- お昼の眠くなる時間帯で峠を越すあたりの14時ぐらいに設定

## 受験してみて
- 時間配分は、これまでの経験から答えを導き出すのに時間を要するものについては、それらしき解答を選択しておき、見直しフラグを設定した
- 試験時間が3時間の長丁場となるため、なるべく集中力を切らさないように、問題文、回答文を読みながら肩を回すなどのストレッチを実施（受験者数が後半から自分一人だったのも良かった）
- 最終的に30分程度見直す時間が残り、フラグを設定していた問題を半分程度見直すことができた。
  - 集中力が途切れていたが、見直し時間に余裕があったこともあり、冷静に考えると誤っていた選択をしていた問題について、５問程度訂正できたことは良かった点。
- 後半20問あたりから、３つを選択し解答する問題が頻出した
- CloudFormation, AWS Config, Control Tower, Organization を絡めた問題が多かったと記憶している

## 新たな次の目標
- 新たに新設された Data Enginner Associate や、Machine Learning Enginner Associate への挑戦
- 並行して業務で使用することの多い K8S関連の資格取得を目指す予定
【Tips】GitHubのレジストリからシングルバイナリのコマンドの最新版を取得する

# やりたいこと
AWS CodeBuildやGitLab-CIのようなCIプラットホームのスクリプト中で各種シングルバイナリのソフトウェアをインストールするときに、aptやらyumが使える場合は良いが、そうでなくてパッケージを取得しなければいけないケースがある。

もちろん、該当のソフトウェアの特定バージョンのパッケージのURLを直打ちすることも可能だが、Trivyのようなセキュリティ系のソフトウェアについては、できれば最新版を使っていきたいので、動的にlatestを引っ張ってきたい。

今回は、そういったときの対応手順を簡単にまとめておく。

# 解決策: GitHubのAPIを使う
結論を言うと、GitHubのAPIを使うことで、最新版パッケージのバージョンを確認することができる。
たとえば、セキュリティ診断ツールであるTrivyは以下のAPIで取得が可能だ。

```shell-session
$ curl --silent https://api.github.com/repos/aquasecurity/trivy/releases/latest
```

これを実行すると、JSONで各種アーキテクチャにおけるパッケージ名を確認することが可能だ。

今回欲しいのは、最新版バージョンのタグ名なので、以下のコマンドで```tag_name```とその値を抽出する。
そうすると、この記事執筆時点での最新バージョンである```0.53.0```が取得できる。

```shell-session
$ curl --silent https://api.github.com/repos/aquasecurity/trivy/releases/latest | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/'
0.53.0
```

これを変数に食わせてダウンロードのURLを構築すれば良い。

例えばhadolintのようにバイナリを圧縮せず直接置いているようなものであれば、

```shell-session
$ wget -q https://github.com/hadolint/hadolint/releases/download/v${VERSION}/hadolint-Linux-x86_64 -O ${HADOLINT_PATH} && chmod 755 ${HADOLINT_PATH}
```

と書けば良いし、TrivyのようにRPMのパッケージを置いているケースであれば、

```shell-session
$ rpm -ivh https://github.com/aquasecurity/trivy/releases/download/v${VERSION}/trivy_${VERSION}_Linux-64bit.rpm
```

と書けばよい。パッケージによってパスの組み方は違うので、それに合わせてコマンドを組み立てよう。
お薦めのpython本

# はじめに
お薦めのpython本を3冊紹介します

## お薦め本
①スッキリわかるpython(第二版)
スッキリ分かるJavaでおなじみの本。分かりやすい解説と発展性があって愛用しています。

②シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全
初心者から上級者まで使用できるpython本。個人的に1番愛用しています。

③Python1年生
私が持っていない本。会社の本棚に何冊かある。初学者向け

# 最後に
お薦めの本をAmazonなどで探してみてはいかがでしょうか
【Go言語】stringsパッケージとbytesパッケージ

# 文字列の連結

Goには文字列を連結する方法は2通りある。

## シンプルな連結(`+=`で連結する)

スライスの全ての文字列を連結する`concat`関数を作成する。

[Go Playground](https://go.dev/play/p/veu5ot5Vd7F)

```go
func concat(values []string) string {
    s := ""
    for _, value := range values {
        s += value
    }
    return s
}
```

これだと反復ごとに`s`は更新されず、新たな文字列がメモリから再割り当てされる。

## strings.Builderを使用する方法(事前割り当てなし)

stringsパッケージのBuilderを用いることで上記の問題が解決し、メモリ上のコピーを最小限にする。

```go
func concat(values []string) string {
	sb := strings.Builder{}
	for _, value := range values {
		_, _ = sb.WriteString(value)
	}
	return sb.String()
}
```

`WriteString()`は、nil以外のエラーを返すことはない。しかし、`strings.Builder`は、単一のメソッドを含む`io.StringWriter`インターフェイスを実装しており、`WriteString(s string)(n int, err error)`となっているため、エラーを返す必要がある。

`string.Builder`は内部的にバイトスライスを保持しており、`WriteString{を呼び出すたびに、appendが呼び出される。この構造体は並行的に使うべきではない。また、スライスの長さがわかっている場合は、事前に割り当てる必要がある。[スライスの初期化のベストプラクティス](https://qiita.com/twrcd1227/items/989d8d553fc6913f01f3#スライスの初期化のベストプラクティス)

## strings.Builderを使用する方法(事前割り当てあり)

strings.Build`Grow(n int)`メソッドを使用すると、nバイトの領域を別に保証することができる。

```go
func concat(values []string) string {
    total := 0
    for i := 0; i < len(values); i++ {
        total += len(values[i])
    }

    sb := strings.Builder{}
    sb.Grow(total)
    for _, value := range values {
        _, _ = sb.WriteString(value)
    }
    return sb.String()
}
```

## 結局どれがいいのか

ベンチマークテストでは、３つ目の方法が一番速くなっている。(参考文献から)
反復処理を2回行っても、スライスの初期化で長さを割り当てているので、速くなる。

ただし、2,3個のの文字列を連結するだけなら、`strings.Builder`を使用すると可読性が悪くなるので、オススメしない。(5個以上の連結であれば`strings.Builder`を使用する方が良い。)

# 文字列とバイト

GoではほとんどのI/Oは、文字列ではなく、`[]byte`で行われる。
例えば、[io.Reader](https://pkg.go.dev/io#Reader), [io.Writer](https://pkg.go.dev/io#Writer), [io.ReadAll](https://pkg.go.dev/io#ReadAll)などが挙げられる。

```go
type Reader interface {
	Read(p []byte) (n int, err error)
}
```

`io.Reader`を入力とし、`sanitize`関数を呼び出す`getBytes`関数を作成する。(サニタイズは先頭と末尾の空白を全て取り除くこと。)

## stringを使用した実装

```go
func getBytes(reader io.Reader) ([]byte, error) {
	b, err := io.ReadAll(reader)
	if err != nil {
		return nil, err
	}
	return []byte(sanitize(string(b))), nil
}

func sanitize(s string) string {
	return strings.TrimSpace(s)
}
```

`[]byte(sanitize(string(b)))`で[]byteを文字列に変換して、文字列を[]byteに変換するという冗長な書き方をしている。また、メモリも変換に余分な割り当てが発生する。

## []byteを使用した実装

[]byteを使用すると、不要な変換を行わずに実装できる。

```go
func getBytes(reader io.Reader) ([]byte, error) {
	b, err := io.ReadAll(reader)
	if err != nil {
		return nil, err
	}
	return sanitize(b), nil
}

func sanitize(b []byte) []byte {
	return bytes.TrimSpace(b)
}
```

stringsパッケージのSplit, Count, Contains, Indexなどはbytesパッケージにも存在する。

# 文字列の不変性

[]byteから文字列を作成すると、コピーが作成される。

```go
func main() {
	b := []byte{'a', 'b', 'c'}
	s := string(b)
	b[1] = 'x'
	fmt.Println(s) // abc
}
```

Goでは、文字列はイミュータブルである。

# スライド

<script defer class="speakerdeck-embed" data-id="52b0d477d76f4bbc93c81c428a4afc80" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>


# 参考文献

1. [100 Go Mistakes and How to Avoid Them](https://100go.co/ja/#39)
nvidia-driverのアップデート

nvidia-driverの最新版へのアップデート方法。

## 方法
以下のCUDA Toolkit Archiveページからインストールしたいバージョンのリンクを開く。

https://developer.nvidia.com/cuda-toolkit-archive

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/1ad9a696-7013-308d-5eb5-9ae045967620.png)

インストールするバージョンのリンクを開いた後、自身の構成で指定していく：

* Operating System
* Architecture
* Distribution
* Version
* Installer Type

指定した後下部に表示されるBasic Installerのコマンドを実行する。
例：
```sh
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update
sudo apt-get -y install cuda
```
※アップデート前にインストールされているnvidia-driverはアンインストールしておく必要はない (と思われる)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594896/cf636335-083c-372c-f471-71a92bc5133e.png)
ITパスポート システムの評価

・システムの信頼性設計
・フォールトアボイダンス（故障排除技術）
故障を排除するという考え方
・フォールトトレランス（耐故障技術）
故障しても耐えてシステムを動かし続けるという考え方

・フェールセーフ
システムが故障したときは、安全性を最優先とする設計
・フェールソフト
システムが故障したときは、機能を低下させても継続を最優先とする設計
・フールプルーフ
不特定多数の人が操作しても、システムの誤作動が起こりにくいようにする設計

・システムの経済性
・イニシャルコスト
システム導入時に発生する初期費
・ランニングコスト
導入後に発生する運用費・管理費
・TCO
システムを所有するのに必要な総コスト

・ベンチマークテスト
コンピュータ間で、ハードウェアやソフトウェアなどの性能を比較するテスト
性能測定用の標準的なプログラムやデータを用いて動作させ、処理に要した時間を比較する
BMWATA（Backend Mocked Web Application Test Automation）Test Approach

●BMWATA 自動化　アプローチはまず一つの開発にかかわるプロセス的なアイデアである。Test Approachです。
●BMWATAアプローチは難しいテスト状況で回帰テストの自動化の不現実さを大きく改善できる想定です。
●BMWATA法は必ずテスト対象の開発中のGUIをベース&対象に、Data,　Request　,Response,　Server等のMockingを開発状況等より柔軟に組合せて多種のテストを行える。
　★これより下記の効果が生まれるとの想定です。
 　①アジャイルテストを容易に行えるようになる。SHIFT-Leftを実現。
　②本番リリース直後の稼働確認にも貢献可能だと想定。実データ不要、本番悪影響ほぼなし。Morningチェックはもっと深くへ。
　 ③スクリプト及びそのモック用のデータは自然に回帰テストとなり,保守工数はほぼ不要に（理由:アプリのBackendが変わらないのはほとんど）。
　 ④テスト部隊は開発部隊と合わせて案件全体の効率向上へ。
　  Testabilityのため、要件からの開発対象とタスクの分け方、順序等の検討が可能に。
　　テストへのDeliveryまでに開発者はスクリプトを流すことが可能に。
　　（これより　テストチームまでに流されるUTレベル、まったく機能実装していないような不具合の数が減らす）　
　　　　⇒　不具合によるコミュニケーション工数を減らす　⇒　リリース時期を守れる）
　⑤Maximization of Test effortsに貢献。
　⑥CI/CD/CTが可能に。

※画面を中心に開発する場合のBMWATAの障害カバレージイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3838358/d783750c-4432-29cc-374e-b4bf486d8c01.png)

※BMWATAを実現するイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3838358/8ce26d2a-bac0-21a0-5967-0d1f86ca92fb.png)
DisableIMDSv1とは？

# 結論
DisableIMDSv1とは？の問いに対しての結論として

:::note info
「IMDSv1を無効にするかどうか」
:::

という設定ですが自分もIMDS自体意識したことがなかったので調べてみました。

# IMDS(インスタンスメタデータサービス)
インスタンスメタデータサービスとはEC2の情報をとってこれるコマンドです。
ec2を立ち上げてSSHやInstance Connectでログインします。
IMDSv1は2024年7月現在無効化されているのでIMDSv2でテストしてみます。
ログインしたEC2で以下のコマンドを実行します。

IMDSv2
```
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
managed-ssh-keys/
metrics/
network/
placement/
profile
public-hostname
public-ipv4
reservation-id
security-groups
services/
```

EC2の様々な情報が取れていることが確認できました。
さらにプライベートIPv4アドレスを取得してみましょう。

```
$ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4
172.31.x.xx
```

取得できました。
ちなみにコンソールから設定すればver1でも検証は可能です。

![IMDSv1有効.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169482/92740f48-6c18-c849-3677-2d0880abbba4.jpeg)

![IMDSv1有効２.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169482/8f03df65-75ab-6046-1688-03bca50d636b.jpeg)


:::note alert
特別な理由がない限りver2を使いましょう。
ver1はSSRF攻撃などのリスクがあるとのことです。
:::


ver1ではcurlコマンドのオプションなしでも取得できます。

ver1
```
$ curl http://169.254.169.254/latest/meta-data
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-life-cycle
instance-type
local-hostname
local-ipv4
mac
managed-ssh-keys/
metrics/
network/
placement/
profile
public-hostname
public-ipv4
reservation-id
security-groups
services/
```

このような形でEC2インスタンスの様々なデータを取得できるのがIMDS(インスタンスメタデータサービス)なんですね。
何か動的にインスタンスを操作したい場合などには使えるかもしれません。

# 169.254.169.254とは
169.254.169.254をはじめとする169.254.0.0/16ネットワーク内のアドレスがこのIMDS用にAWSが確保しているアドレスとのことでした。

# DisableIMDSv1の使い方
DisableIMDSv1というプロパティはBeanstalkのebextensionsで設定できる項目になります。
具体的には以下のようにautoscalingに設定し、管理下のEC2のIMDSをv2にするというものになります。

```disableIMDS.yaml
#拡張子は見やすくするためにyamlで指定していますが実際はconfigです。
option_settings:
  aws:autoscaling:launchconfiguration:
    DisableIMDSv1: true

```

# LaunchTemplateへの切り替え
IMDSv1を調べるきっかけになったのがLaunchTemplateへの移行でした。

https://qiita.com/ryomoucmei/items/a44437b688b26e90b5b3

LaunchTemplateをBeanstalkで使用する際にDisableIMDSv1の設定は2024年7月現在では必須でした。

# 参考
とてもわかりやすかったです
ありがとうございました！

https://qiita.com/miyuki_samitani/items/be36df3ff41da4e3016a