OmniAICreator/Qiita-1.07M huggingface dataset:
RDSマネージドローテーションキーでカスタムユーザーの値に変更できるのか

SecretsManagerを利用している際に、各サービスでマネージドなローテーションキーを提供していることを確認しました。
今回はこのシークレット情報を変更できるのか検証してみました。

## マネージドローテーションとは？
RDS作成/変更時にRDSのコンソール上で設定可能なSecretsManagerになります。
特徴としては、ローテーション用の間数が不要であり、SecretsManagerの値が以下画像のように「rds!」から始まるものになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/2f2ebcf2-7a09-6863-aed8-f3833ba61f58.png)

ローテーション構成はいかのようになります。上記でも記載しましたがローテーション間数へのリンクもないので、**間数なしでローテーションできる**ことも大きな特徴になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/9d19fb96-bdf8-76b0-7892-4c60accbd0e4.png)


https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/rotate-secrets_managed.html

RDS以外のサービスでも、マネージドローテーションキーを提供しているため、詳しくは以下を参考に。

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/service-linked-secrets.html


## 検証前 予想
検証前の予想なのですが、上記ドキュメントを見ても「マスターユーザーパスワード」の記載が多く、更にはCLIでもオプション`--rotate-master-user-password`や`--manage-master-user-password`などのオプションがあるので、一見するとマスターユーザー以外は設定できないんじゃないかと見られます。
さらにはマネジメントコンソール上でも以下のような内容が記述されているため、おそらくは設定できないものかと。
> このシークレットは Amazon RDS (rds) によって作成されました。
> このシークレットは Amazon RDS (rds) によって管理されるため、シークレット値を変更することはできません。ただし、シークレットは他の方法で変更できる場合があります。

但し、シークレットを確認するとusernameとpasswordがシークレットキーとして置いているのでここのキー値だけを見ているのなら、カスタムユーザー値に書き換えればワンチャンいけるんじゃないかという予想です。


https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/rds-secrets-manager.html#rds-secrets-manager-rotate-db-instance


## 検証

以下のリンクに則ってDBユーザーnew_master_user1を作成します。

```bash
MariaDB [(none)]> CREATE USER 'new_master_user1'@'%' IDENTIFIED BY 'password';

MariaDB [(none)]> GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD, PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER ON *.* TO 'new_master_user1'@'%' WITH GRANT OPTION;
```

https://repost.aws/ja/knowledge-center/duplicate-master-user-mysql

その後、以下のように「rds!」から始まるシークレットに先ほど作成したユーザー情報に記載を変更しました。　

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/21228861-e94e-1721-1d65-7b7ed5d7e60c.png)

保存ボタンを押下すると以下のようにエラー。どうやら手動での変更は受け付けてないそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/872532/5bf11e97-c1d5-4bd3-b610-e1184e3f6081.png)


そのため、カスタムユーザーのシークレット情報のローテーションを設定したいというのなら、従来のようにSecretsManagerから作成してローテする必要があるかと。。

## 終わりに
今回は短いですが、RDS上で指定しているユーザーでのみ、マネージドローテーションは提供できない。更には別ユーザーに変更できないと言ったことがわかりました。

色々手を動かしてみて初めてわかることもある。。
SPAJAMに数年連続出場したら得られた経験と今

## はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/630810/cd47f4b7-0991-f84b-8801-1412c7401532.png)


皆さんは職場でPC業務を行い、帰宅してもパソコンを開きますか？
僕は一切開かずにゲームしてるかジムで筋トレをする一般的(?)な社会人でした笑

そこから気づけば、帰宅後ほぼ必ずパソコンを開きスマホアプリやwebシステムを開発する様になったきっかけが
`SPAJAM`です

## なぜ毎年出場していたか

新卒で入った会社の同期にめちゃくちゃ技術が好きなZさんがいて、
「一緒に出よう！」と声をかけてくれたことがきっかけです。

最初の1,2年は来年こそ予選突破！と思っていたのですが途中から、
その年に新卒で入った子たちにチームで開発をすることの楽しさを伝えたいなというのが目的になってきました(笑)

なので技術力も役割もバラバラで大会への出場経験も毎回リセットしつつも
なんだかんだ楽しいと感じてくれるみんながいるおかげで毎年出場できていました。

出場を初めて2,3年目には僕は会社を辞めてフリーランスとして活動していたのですが、
それでも唯一社外の人間である僕を受け入れてくれたことは今でも感謝しています。

## 予選結果

全て予選落ちです笑笑

ただの言い訳になってしまいますが、僕のような会社に入ってようやく頑張り出した人間と、これまで趣味として技術に触れハッカソンに出ている人との差は圧倒的でした笑
あとはチームビルディングやエンジニア以外の人（デザイナーやプレゼンに強い人）を見つけられたら変わっていたかもしれませんね笑

ただ僕らはそもそも勝てると思っていなかったので少々受けを狙ったプレゼンをしていて、
他の参加者や審査員が笑えば勝ちと捉えて楽しんでいましたｗ

Twitter界隈では有名なMicrosoftのち◯まどさんに「面白かったですw」と感想をいただいた時にはもうこれで満足・・・と考えそうでしたが予選惨敗なので思えませんでした。（めちゃくちゃ嬉しかったのですぐ周りに自慢した）


## 出場して得られたモノ

「予選惨敗して結果残せてないじゃん」
そう思ったあなた言っていることは合っています。でも刺さるから言うな。

ですがSPAJAMという大会に数年出場したからこそ、
・技術力向上/プレゼン力向上
・後輩たちのモチベーションアップ
・Zさんの社内評価向上（元々高かった。のちの最年少技術役職者に就任）
・人前でボケる技術の習得

など様々な経験を得られました。

個人的には「サービスを一貫して作る経験」に何度も触れることができたのと、
SPAJAMのために継続して勉強していたからこそここ数年、企業の相談やリードエンジニアとしての役割を任せていただいているのだと思います。

## さいごに

社会人になって一番感謝している存在が度々名前の出てきているZさんです。
僕をSPAJAMに誘ってくれてありがとう。もしこの記事見てたら久々連絡してくれ👍
そしてSPAJAMさんも素敵なハッカソンを毎年開催していただいてありがとうございます。

最近は子育てでバタバタしていますがこれからも機会があればハッカソンなどの大会に出てみたいなと思います。
興味ある方はお声がけください笑

最後まで読んでいただきありがとうございました！


（SPAJAM）
https://www.spajam.jp/

（ReactNativeで作ったもの）
https://www.konoyubitomare.app/

## あとがき

Zさんから記事見たよと連絡が来ました笑
僕が出場していない期間に予選での最優秀賞受賞を果たしたそうです👏さすがすぎます笑
Raspberry Pi Pico Wでタイマーを利用して周期的にメソッドを実行する

### 概要

タイマーを利用して1秒ごとに基盤上のLEDをON/OFFするプログラムで、以下の部分がポイント。

* callbackで指定する関数の第一引数はTimerオブジェクトが入る
* callbackで指定する関数に引数を渡すことはできないので、グローバル変数を利用する
* プログラムを停止した時にタイマーを初期化しないとシリアル接続が中断される
* callbackで呼び出された処理の中でエラーが発生してもメインプログラムは動き続けるし、timerも動き続ける（callbackで呼び出された処理でグローバル変数を変更したりして、メインプログラムに影響を与えない限りは）


```python:main.py
from machine import Pin, Timer
import machine
from utime import sleep, localtime


pin = Pin('LED', Pin.OUT)

def callback(timer):
    pin.toggle()
    print(localtime(), pin.value())
    
timer = Timer()
timer.init(mode=machine.Timer.PERIODIC, period=1000, callback=callback)

try:
    while True:
        sleep(1)
except KeyboardInterrupt:
    timer.deinit()
```
【アニメーション】AfterEffectsで背景が透過したgifアニメーションを綺麗に書き出す方法

## はじめに
<!-- ここには、前段を書く　・　Qiitanアニメーションで綺麗に書き出せなかった話 ・ gifアニメーションの話 -->
先日Qiitaでは、記事投稿が完了したあとに、記事投稿を労うModalを表示するようにアップデートしました。
そのモーダルでは、以下のような :qiitan: Qiitanのアニメーションが表示されます。

|![anime-qiitan-default.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/e5fec0bf-2889-b916-713c-89a4bfd12fec.gif)|![anime-qiitan-balloon.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/a424d008-3ba4-c023-b3fd-9366777cc660.gif)|
|----|----|
|デフォルト|ふうせん|

<font color="gray"> *※ Qiitanかわいい〜* </font>

このQiitanアニメーションを作成するにあたり、背景が透過したgifを綺麗に描き出せずに苦労しました。

そのためこの記事では、綺麗に描き出せない原因と
AfterEffectsで作った背景が透過したアニメーションを綺麗にgif書き出す方法を紹介します。



## 綺麗に描き出せないgif
<!-- 原因をまとめる ・ 解決法一緒になるかも、描きながら決める -->
### 気になるところ
AffterEffectsで作ったアニメーションをMedia Encoderでgifに書き出すとはこんな感じになっています。
![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/ea220eb7-57bc-bfd7-35db-f9e159c8cb8b.gif)
このgifアニメーション　で気になるポイントは以下の2点です。

- Qiitanの周りに白い枠線が出ること
- 風船部分の色のノイズがあること

### 原因
**【Qiitanの周りに白い枠線が出ること】**
Qiitanの周りの部分の白い枠線は、Gifが256色しか保存できないことが原因です。
背景を透過されるアニメーションでは、alpha(透明度)を含めて、256色になるため、圧倒的に色がたらなくなります。
そのため、1色（白）のグラデーションで表現をするため、枠線が白くなってしまうということです。

**【風船部分の色飛びが出ること】**
色飛びをする原因は、Media Encoderでの書き出しの仕様だと思います。
Media Encoderがgifでの書き出しが得意ではないのかもしれません。

https://community.adobe.com/t5/premiere-pro%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A9%E3%83%A0-discussions/premier-pro-gif%E3%83%8E%E3%82%A4%E3%82%BA/m-p/12227960?profile.language=ja


## 解決法
<!-- photoshopでの書き出し方 ・ Animation PNG -->
これらの原因を解決するためには、以下のようにGIFにします。

1. AfterEffectsから、movファイルで書き出す。
1. PhotoShopでmovファイルをgifへ書き出す。

### ① AfterEffectsから、movファイルで書き出す
AfterEffectsで作成したアニメーションをmovファイルへ書き出すのは、透明度のある動画ファイルを作成できるからです。
なおかつ、綺麗に描き出せない原因を解決するため、PhotoShopで色を調整する必要があるため、PhotoShopで読み込める動画形式のmovファイルで書き出します。

以下の画像のように、ビデオ出力のチャンネルを`RGB + アルファ`で書き出してください。
![スクリーンショット 2023-09-13 19.16.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/a3af7e62-786e-1157-67f6-9fe49abbf7f4.png)
※ movファイルへ書き出す方法は、Media Encoderでも、レンダラーキューでもどちらでも大丈夫です。

### ② PhotoShopでmovファイルをgifへ書き出す
次に①で作成したmovファイルをPhotoShopでgifへ書き出します。

まずは、PhotoShopをひらき、movファイルをひらきます。
次に、「ファイル > 書き出し > web用に保存（従来）」で書き出します。
![スクリーンショット 2023-09-13 19.33.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/16133800-f25a-4e02-ef4f-d366d7516f8d.png)

書き出しのモーダルから、「マット」をなしに設定して書き出して完成です。
![スクリーンショット 2023-09-13 19.49.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390720/4935b4b2-c3f3-b2c4-114a-062c43d9462d.png)


## まとめ
この記事では、AfterEffectsで背景が透過したgifアニメーションを綺麗に書き出す方法を紹介しました。

gifが綺麗に描き出せないという方は、ぜひこの方法をおためしください。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaに記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
リパース ポイントを作る

# はじめに
Windowsで使われているファイル システムのNTFSではリパースポイント(再解析ポイント)をサポートしています。
実際には存在しない場所にあたかもファイルやディレクトリがあるように配置することができます。

https://learn.microsoft.com/ja-jp/windows/win32/fileio/reparse-points

# ジャンクション
対象: ディレクトリのみ
例えば **C:\Users\All Users** は **C:\ProgramData** へのジャンクションです。

## 作成方法
コマンド プロンプト

```
MKLINK /J 作成先ディレクトリ名 リンク元ディレクトリ
```

# シンボリックリンク
対象: ファイルとディレクトリ、ネットワークの共有フォルダへのリンクも作成可能、相対パス設定可

## 作成方法 (ファイルの場合)
管理者権限 もしくは開発者モード コマンド プロンプト

```
MKLINK 作成先ファイル名 リンク元ファイル
```

## 作成方法 (ディレクトリの場合)
管理者権限 もしくは開発者モード コマンド プロンプト

```
MKLINK /D 作成先ディレクトリ名 リンク元ディレクトリ
```

# ハードリンク (リパースポイントではない)
対象: 同じ物理パーティション内のファイルのみ

## 作成方法
コマンド プロンプト

```
fsutil hardlink create 作成先ファイル名 リンク元ファイル
```

# 何に使うの？

## シンボリックリンク
ディレクトリを固定しておきたいけど、中身は動的に変えたい。
例えば、**C:\Application** というディレクトリに **1.00** **1.20** **2.00** **3.10** のようなディレクトリがあるとして、**Latest** という名前のシンボリックリンクを作成してショートカットを作成しておけば、
新しいバージョンのディレクトリを作成したらそこへのリンクを **Latest** に作り直すだけで、
**C:\Application\Latest\Application.exe** は常に最新のアプリケーションを指す、という仕掛けを作ることができます。

## ハードリンク
**C:\Application\bin\Release\Application.exe** というファイルがあるとします。
これを **C:\Applications\Application.exe** にリンクしておけば、
**C:\Application\bin\Release\Application.exe** をビルドし直すだけで **C:\Applications\Application.exe** も最新になる、という仕掛けを作ることができます。

:::note warn
ハードリンクは一度削除してしまうとリンクが切れます。
例えばVisual Studioでアプリケーションを"ビルド"で作成した場合は問題ありませんが、"リビルド"をすると一度ファイルが削除されてしまうので、新しくビルドされたファイルはリンク先とは異なる中身になります。

但しリンク元が削除されてもリンク先が消滅するわけではなく、消滅した瞬間にリンク先がリンク解除直前のリンク元と同じものになるという特殊な振る舞いをします。

リンクされた状態では複数のファイルが同じものを指すため、リンク個数分のディスク領域を消費することがありません。
:::

:::note info
ジャンクションはディレクトリのシンボリックリンクとほぼ同じ振る舞いなので現在ではあまり使い道はありません。
(ジャンクションはWindows 2000からサポート、シンボリックリンクはWindows Vistaからサポート)
:::

# リンクの削除
リンク先を削除すると、リンク元に影響を与えずに削除することができます。

# 便利なツール
コマンドを入力するのが得意な人には良いかもしれませんが、Windowsはエクスプローラのようなシェルを使うのが一般的です。
エクスプローラのコンテキスト メニューからリンクを作成する機能を呼び出すには、以下のようなツールを使うのが便利です。

[Link Shell Extension - Gerhild's & Hermann's Site](https://schinagl.priv.at/)

ファイルやディレクトリをエクスプローラで右ドラッグ、作成したディレクトリやその背景でボタンを離すと、**ここにリンクを作成...** → **ハードリンク** / **シンボリック リンク** のメニューが現れます。

:::note warn
ご利用は自己責任でお願いします
:::

# 濫用は禁物
紹介しておきながらですが、リパースポイントやハードリンクは別の場所のディレクトリやファイルをリンクしますが、別の場所を利用するという目的だけで濫用すべきではありません。

あくまでアプリケーションやバッチファイル等のプログラムに対して柔軟な動作させるのには向いていますが、  
特にユーザーに対して別の場所のものを提供するだけであればこれらのリンクではなくショートカットの方が適しています。

特にハードリンクはほぼコピーと同じような振る舞いを与える事ができますが、リンク関係の把握や通常のファイルとの区別、リンク切れの管理がしにくいため使いどころは限られます。

:::note info
リパースポイントもハードリンクも、エクスプローラからファイルのプロパティを開く事でリンクを確認することができます。
:::

:::note warn
ジャンクションやシンボリックリンクは、上位のディレクトリへリンクする事で無限ループの階層を作成することも出来てしまいます。
:::
AWS Terraform – Lambda と SNS の連携で トリガーができない 

# 公式

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission

# 問題

TerraformでLambdaとSNSを連携させた

SNSのサブスクリプションにはLambdaが登録されているように見えるのに、
逆にLambdaのトリガーの画面にSNSが現れない


# 解決

aws_sns_topic_subscription に Lambda の ARN を設定するだけではなく
SNS に Lambda の実行パーミッションを付ける必要があるようだ

```tf
resource "aws_sns_topic" "example" {
  name = "example"
}

resource "aws_sns_topic_subscription" "example" {
  topic_arn = aws_sns_topic.example.arn
  protocol  = "lambda"
  endpoint  = aws_lambda_function.example.arn
}


resource "aws_lambda_permission" "with_sns" {
  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.example.function_name
  principal     = "sns.amazonaws.com"
  source_arn    = aws_sns_topic.example.arn
}

```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
人事からPMOへ② 〜想像してた業務と違った？〜

こんにちは☀️

今日は、実際の業務や1日のスケジュールなどpmoをイメージしやすいように、いろいろ書いていこうと思います。

【実際どんな業務をしているの？】
今のプロジェクトでは、主に下記のような業務をやっています。
■議事録作成
《作業内容》各全体会議の議事録作成、展開

■議事録チェック
《作業内容》形式通りに記入されているかチェックする。

■手順書作成
《作業内容》新規運用の手順書作成、既存の手順書の修正。

■成果物チェック
《概要》タスクが完了した際に、成果物が所定のフォルダに格納されているか確認する。
《作業内容》チェックリスト項目をツールにて出力。それをもとにサマリを作成。全体朝会にて、不備があるチームに是正依頼する。

■搬入、搬出作業
　《概要》搬入とは、セキュリティが高い場所へ資産移動する。搬出はその逆。
　《作業内容》　搬入もしくは搬出されたファイルの資料をチェックする。不備がある場合は、是正依頼する。

■各申請管理
　《作業内容》休日、夜間申請書の管理・チェックする。客先に申請する。

■ファシリテーター
《作業内容》朝会の資料作成、朝会の進行

■WBS、課題管理　
《作業内容》WBSの申請変更内容をチェックして、不備がないことを確認する。
　　　　　　　　　　　　

【どのように1日作業しているの？】
　9:00　　　朝会　（議事録作成）
　9:30　　　搬入作業
　　　−休憩−　　　
　13:00　　手順書作成
　16:00　　PMO進捗会議
　17:00　　成果物チェック

これらのタスクはどちらかというと思考するというより事務作業に近いですよね。思考してる時間は、短いかもしれないです。

最初のPMOのイメージでは、課題を見つけ、具体的な解決策を提示するような仕事って思ってました。とても難しそう、、。私にできるのかなって感じてました。

実際は、事務作業に近いタスクが多いので、覚えれば、誰でもできる作業は多いと感じました。
（もちろん、参画するプロジェクトやポジションによります。）

もし、自分には、絶対無理と諦めている方がいれば、未経験オッケーのプロジェクトは、ハードルはそんな高くないと思うので、チャレンジしてみてほしいです。
pmoの経験は、今後のキャリアを広げていけると思います！


次回は、pmoの将来性やキャリアパスについて書いていこうと思います。
1Password CLIでAPIシークレットキーなどのアイテムを保存する方法

1Password CLIを使用してAPIシークレットキーなどのアイテムを保存、管理する方法について説明します。これにより、パスワードやAPIキーなどのクレデンシャルを一元的に安全に管理することができます。

## 基本コマンド

最初に基本となるコマンドを見てみましょう。

```shell
op item create \
  --category "API Credential" \
  --vault "ボルト名" \
  --title "タイトル" \
  "credential=APIのキーなど"
```

このコマンドの各部分を詳しく説明します。

- `op item create` は1Passwordで新しいアイテムを作成するコマンドです。
- `--category "API Credential"` で、作成するアイテムのカテゴリを "API Credential" に指定しています。
- `--vault "ボルト名"` で、保存するボルト（セキュアな保管箱）の名前を指定します。
- `--title "タイトル"` でアイテムのタイトルを指定します。
- `"credential=APIのキーなど"` で保存するキーの情報を指定します。

続いて具体的な使用例を見てみましょう。

## 使用例: PrivateボルトにGitHubのトークンを保存する

次のコマンドは、Privateという名前のボルトに "github-personal-access-token" というタイトルでGitHubのトークンを保存します。

```shell
op item create \
  --category "API Credential" \
  --vault "Private" \
  --title "github-personal-access-token" \
  "credential=1234567890abcdef1234567890abcdef"
```

1Password CLIを使用すれば、このように様々なクレデンシャルを簡単に保存し、取り出すことができます。パスワードやトークンの管理を効率化し、セキュリティに配慮した操作を行うために活用してみてください。
Javaで「乱数を生成する」の動作を確認してみた

# 概要

Javaで「乱数を生成する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/math/index8.html

# 実装

以下のファイルを作成しました。
```JSample8_1.java
class JSample8_1{
  public static void main(String[] args){
    for (int i = 0 ; i < 10; i++){
      System.out.println((int)Math.ceil(Math.random() * 5) + 5);
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample8_1.java 
$ java JSample8_1 
6
10
9
8
7
10
6
7
7
8
```

# まとめ

何かの役に立てばと。
Errorで「It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default.」って怒られた

useStateを使おうとしたら怒られました…。
理由は、クライアントコンポーネントだけで使えるuseStateをサーバーサイドコンポーネントで使おうとしている。
というものです。

私は子コンポーネントでuseStateで利用していました。
するとエラーが発生しました。

この記事ではその解決方法を提示します！

## 解決方法
親コンポーネントで`'use client';`を1行目で定義することで解決しました。

## なぜ発生したのか？
個人としてはこれまで通りコンポーネントでは特殊なことはしていません。
それでもエラーは出ました、これはNext.jsの環境設定の際に「App Router」を利用することをyesとした場合に発生すると推測されます。

https://nextjs.org/docs/app

「App Router」にしているとデフォルトではサーバーサイドコンポーネントとしてレンダリングしようとするらしいです。
なので`use client`を記述しておくとクライアントコンポーネントであることを伝えることでエラーが消えます！

:::note warn
`use client`は定義したコンポーネントはもちろん、定義したコンポーネントで呼び出されている子コンポーネントでも設定が有効になるので注意してください！
:::

正直まだわかっていない部分が多いですが、お役に立てると幸いです。
CDK と CloudFormation の 概念（Concept） の関係図

CDK で運用するならスナップショットテストはちゃんとやったほうがいいということを学びました。スナップショットテストが検出する 差分 のことはなんと呼べばいいんでしょうか？呼び名はない？ということを、全体を整理しながらぼんやり考えてたら怪文書（怪図？）が出来上がったのでここに放流します。

![CDK での開発プロセスにおけるリソースの相変化の呼び名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37466/076c8c80-efa2-ebc4-1334-571543640f27.png)

CloudFormation の範囲だけなら概念の整理のドキュメントが公式にしっかりあるけど CDK とあわせた一貫性のある（なくてもいいけど）やつはあまり見かけないですね。
※ 上記図は私が触れる慣用の範囲のメンタルモデルであって正確さや厳密さはないので目を細めて眺めるくらいにとどめてください。

- 参考： [AWS CloudFormation の概念 - AWS CloudFormation](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html)

で、本題はこれが聞きたかったんですが、だいぶ横道にそれてしまいました。

![CDK での開発プロセスにおけるリソースの相変化の呼び名_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37466/daaaa457-3767-8482-ee0a-89d8701170be.png)
canvas要素の全消去


canvas要素の内容を全消去したい場合、clearRectで全範囲を指定する方法をよく見かける。

```:JavaScript
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
```

canvasのサイズを同じ値に指定し直すことでも全消去できる。

```:JavaScript
const canvas = document.getElementById('canvas');
canvas.width = canvas.width;

// または
// canvas.height = canvas.height;
```
Moya.MultipartFormData

### 大分前に書いたコードだけどQiitaみたら誰も記事にしてなかったので、参考になればと思い記事にしてみました。
自分は以下の様に実装してファイルアップロードを対応しました。多分同じところではまってる人はこれみれば何をすればいいかわかると思いますし、興味ない人は細かく書いてもみないと思うので、自分が実装したコードを載せておきます。

ファイルフォーマットが変わっても対象箇所を同じ様に設定してあげればアップロードされるとこまで確認してます。

```
import Moya
import Foundation
import UIKit

extension Api {
    struct UploadFiles: ApiTargetType {
        typealias Response = ApiResponse.File
        
        var method: Moya.Method {
            return .post
        }
        var path: String {
            let pathString = "resource_files"
            return pathString
        }
        
        var task: Task {
            let formData: [Moya.MultipartFormData] = [Moya.MultipartFormData(provider: .data(fileData), name: "file", fileName: self.fileName, mimeType: self.mimeType)]
            return .uploadMultipart(formData)
        }
        
        
        var fileData: Data
        var fileName: String
        var mimeType: String
        
        init(fileData: Data, fileName: String = "name", mimeType: String = "text/plain") {
            self.fileData = fileData
            self.fileName = fileName
            self.mimeType = mimeType
        }
    }
}
AWS SSM PortforwardコマンドとIAMポリシー

# はじめに
AWSのVPC内にあるWindowsインスタンスにローカルPCからSSM PortforwardをしようとしたらコマンドとIAMポリシーにつまづいたので記録として残しておきます。

# 環境
接続先はVPC内Windowsサーバ(3389のRDPポートにつなぎたい)
接続元OSはWindows

Windowsサーバには適切なIAMロール(AmazonSSMManagedInstanceCore)とNetwork設定、SSMAgentがインストールされている前提です。


# AWS CLIのコマンド
ドキュメント等を参考にコマンドを用意したが以下はNG
(コマンドプロンプトかpowershellからはNG)
```
aws ssm start-session --target i-xxxxxxxxx --document-name AWS-StartPortForwardingSession --parameters '{"portNumber":["3389"],"localPortNumber":["50001"]}' --region ap-northeast-1
```

コマンドプロンプトかpowershellでは以下がOKのコマンド。
--parametersの括弧内のダブルクォーテーションをエスケープする必要がありました。
```
aws ssm start-session --target i-xxxxxxxxx --document-name AWS-StartPortForwardingSession --parameters="{\"portNumber\":[\"3389\"],\"localPortNumber\":[\"50001\"]}" --region ap-northeast-1
```

上記コマンドが通った後、ローカルPCからRDPクライアントでlocalhost:50001に接続することになります。

# ローカルPCへ入れるクレデンシャルのIAMポリシー
AWS CLIを利用してSSMポートフォワードするには、
ローカルPCへはIAMユーザを作成しクレデンシャルを登録する必要があります。

ポートフォワード先を制限したいときのIAMポリシー例を以下に残しておきます。

※arn:aws:ssm:ap-northeast-1::document/AWS-StartPortForwardingSessionにはAWSアカウント番号を入れないのがポイントのようです。


```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssm:StartSession"
            ],
            "Resource": [
                "arn:aws:ec2:ap-northeast-1:99999999:instance/i-XXXXXXXXXXXX",
                "arn:aws:ssm:ap-northeast-1::document/AWS-StartPortForwardingSession"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:TerminateSession",
                "ssm:ResumeSession"
            ],
            "Resource": [
                "arn:aws:ssm:*:*:session/${aws:username}-*"
            ]
        }
    ]
}
```

99999999は自身のAWSアカウント番号に置き換えて下さい。
i-XXXXXXXXXXXXは接続したい(それだけに絞りたい)インスタンスIDに置き換えてください。
ビルド時にgit cloneするイメージの軽量化（マルチステージビルドの復習）

Dockerを触り始めた頃、巨大なリポジトリをcloneしてきて必要なファイル群をコピーしたりchownしたりといった操作を一つのステージでまとめて行ってしまっていたことがありました。これによって5GB近いサイズのイメージが出来上がっていた訳ですが、Dockerfileをマルチステージな構成を活かせる形に書き換えることで、イメージサイズを半分以下にまで落とすことができました。

この仕組みを調べたことがDockerの理解に役立ったため、当時の自分やDockerを触り始めたばかりの方に向けてまとめてみようと思います。今回行った最適化のポイントは、**マルチステージビルドの活用**と**COPY時の—chownオプションの活用**の二つになります。

# マルチステージビルドの活用

### イメージサイズ肥大化への対処

Dockerのイメージは、ベースイメージのファイルシステムに対する一連の操作の重ね合わせとして認識されます。ビルドの際は、RUN, COPY, ADDなどの各操作が行われる度に新しいレイヤが作られ、それらのレイヤはスタックのようにベースイメージの上に重ねられて、最終的なイメージを形成します。

そのため、何も考えずにイメージをビルドすると、

- ビルドツールと依存ライブラリ（コンパイラやビルドツール）
- ビルド前のソースコードファイル
- テストコードやテストツール

などの本番では必要のないファイル群が混ざってしまうことになります。

この問題に対処するために、昔は中間イメージを作成する手法が一般的だったようです。必要なファイルの入った中間イメージをもとにコンテナを起動してビルドなどの作業を行い、その生成物を本番のイメージにコピーすることでサイズを抑えていました（参考: [docker docs マルチステージビルドの利用](https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/#before-multi-stage-builds)）。この手法は依然として有効ですが、マルチステージビルドはこのプロセスをよりシンプルにし、ビルドプロセスを1つのDockerfileに統合することを可能にします。

### Dockerfileのマルチステージ化

今回のリファクタでは、次のようなDockerfileを

```docker
FROM php:7.4-fpm-alpine
...
RUN git clone -b master https://github.com/sampleorg/bigrepo.git /homedir
...
RUN cp -r /homedir /var/www/app
RUN chown -R php.php /var/www/app
```

以下のように書き直しました。

```docker
FROM alpine:3.13 as build
...
RUN git clone -b master https://github.com/sampleorg/bigrepo.git /homedir
...
FROM php:7.4-fpm-alpine
...
COPY --from=build --chown=php:php /homedir /var/www/app
```

もとのDockerfileでは、cloneしてきたリポジトリのコピー・所有権の変更を全て本番ステージで行っていました。操作の度にレイヤが生成されるため、影響を受けるファイルの数やサイズが大きい操作が積み重なることで、イメージサイズは2倍3倍と肥大して行ってしまいます。

リファクタ後のDockerfileでは、cloneやその後の処理はビルドステージで行い、必要なファイル群のみを本番ステージに持ってくるようにしました。

マルチステージビルドの際にビルドステージで生成されるイメージは、実際にはDockerのローカルストレージ（一般的にはDockerホストのファイルシステム内）に一時的に保存され、後続のステージから参照できるようになります。本番ステージで`COPY —from=build`のような命令を使用することで、この一時的に保存されたビルドステージのイメージからファイルをコピーすることができるようになります。

ビルドが完全に終了すると、これらの最終イメージの作成のみに用いられる中間イメージはその後は不要なため通常は削除されます。このような仕組みによって、最終的に生成されるイメージのサイズを小さく抑えることができるようになりました。

```bash
REPOSITORY       TAG       IMAGE ID       CREATED         SIZE
before           latest    8aabe296d57e   2 hours ago     4.87GB
after            latest    72fc81f23bc1   2 hours ago     1.88GB
```

# **COPY時の—chownオプションの活用**

### chownすると差分にカウントされる

リファクタ後のDockerfileについて、本番ステージの記述は以下のようにすることもできます。

```docker
FROM php:7.4-fpm-alpine
...
# COPY --from=build --chown=php:php /homedir /var/www/app
COPY --from=build /homedir /var/www/app
RUN chown -R php:php /var/www/app
```

しかしこの場合、生成されるイメージは大きなままとなってしまっています。

```bash
REPOSITORY       TAG       IMAGE ID       CREATED          SIZE
after            latest    72fc81f23bc1   2 hours ago      1.88GB
after-chmod      latest    fbe148476f5b   16 minutes ago   3.36GB
```

これは、chown対象のディレクトリごと、前のレイヤの状態に対する差分として扱われてしまうためだと考えられます。DockerfileのADD/COPY操作において--chownを使用することで、ADD/COPYの一連のステップの中で操作対象ファイルの所有者を変更することができるため、こちらも不要なレイヤを増やさないという観点からイメージサイズの抑制に有効そうでした。

# まとめ

ここまで、**マルチステージビルドの活用**と**COPY時の—chownオプションの活用**の二つのポイントを通してイメージサイズの軽量化について説明しながら、イメージがどのように構成されているかなどのDockerの基本的なところも合わせて復習して来ました。この先の理解の助けになれば幸いです。
Vuetify3のv-date-pickerに標準搭載されているボタンに関数を仕込み、表示非表示を切り替える方法

# はじめに
Vuetifyは手軽にリッチなUIを作成することができますが、現時点でVuetify3のバージョンのv-date-pickerに関する公式ドキュメントは少ないです。

この記事では、v-date-pickerという非常に使いやすい日付選択コンポーネントを利用し、v-date-pickerのキャンセルボタンをクリックした際にダイアログを非表示にする方法を説明します。

## 前提条件
■Vuetify3をプロジェクトで導入していること
    https://github.com/vuetifyjs
■Vue3のCompositionAPIを用いて開発していること

## 実装手順
### 結論
結論から申しますと以下のコードになります。
```vuejs
<template>
  <v-card-title class="d-flex align-center justify-center" style="font-size: 16px" color="grey-darken-2">
    日付
  </v-card-title>
  <v-card-subtitle class="d-flex align-center justify-center">
    <v-text-field
      @click="handleClick"
      label="日付を選択"
      outlined
      readonly
    ></v-text-field>
  </v-card-subtitle>
  <v-row justify="center">
    <v-dialog
      v-if="menu"
      v-model="menu"
      :close-on-content-click="false"
      full-screen
    >
      <v-card class="d-flex justify-center align-center">
        <v-date-picker
          @click:cancel="handleCancel"
        ></v-date-picker>
      </v-card>
    </v-dialog>
  </v-row>
</template>
<script setup lang="ts">
  import { ref } from 'vue';
  import { VDatePicker } from 'vuetify/labs/VDatePicker';
  let menu = ref<boolean>(false);

  const handleClick = () => {
    menu.value = true;
  };
  const handleCancel = () => {
    menu.value = false;
  };
</script>
```
### 初期設定
まず、以下のようにテキストフィールドとv-date-pickerとそれを囲むv-dialogを配置します。
```vuejs
<template>
  <v-card-title class="d-flex align-center justify-center" style="font-size: 16px" color="grey-darken-2">
    日付
  </v-card-title>
  <v-card-subtitle class="d-flex align-center justify-center">
    <v-text-field
      @click="handleClick"
      label="日付を選択"
      outlined
      readonly
    ></v-text-field>
  </v-card-subtitle>
  <v-row justify="center">
    <v-dialog
      v-if="menu"
      v-model="menu"
      :close-on-content-click="false"
      full-screen
    >
      <v-card class="d-flex justify-center align-center">
        <v-date-picker
        ></v-date-picker>
      </v-card>
    </v-dialog>
  </v-row>
</template>
```
## キャンセルボタンのイベントをリスニング
v-date-pickerにはデフォルトでキャンセルボタンと保存ボタンがあります。
キャンセルボタンがクリックされた時にイベントをキャッチするには、@click:cancelを使用します。
@click:cancelはVue.jsのデベロッパーツールを確認すると、VDatePickerに標準で搭載されていることが確認できます。
![スクリーンショット 2023-09-21 1.48.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590211/74eaf043-d60e-f15f-3dee-20a36ce5c478.png)

```vue.js
<v-date-picker
  @click:cancel="handleCancel"
></v-date-picker>
```

## イベントハンドラの作成
次に、handleCancel 関数を作成して、menu の値を false に設定します。これにより、ダイアログが閉じられます。
```vue.js
const handleCancel = () => {
  menu.value = false;
};
```
以上で、キャンセルボタンをクリックした際にダイアログが閉じるようになります。

## まとめ
Vuetifyのv-date-pickerの挙動をカスタマイズする際のドキュメントは少ないため、開発者ツールやOSSなどを確認する必要があるかと思いますが、この記事が皆さんの開発に役立てば幸いです。
Next.jsのImageコンポーネントでICCプロファイル付きの画像を取り扱う場合の注意

# 状況

以下のような環境を考える

- Next.js
- Vercel以外でホスティングしている(今回はAWS ECSのNode.jsコンテナ)

# 問題

- デザイナーからICCプロファイル付きの画像を渡された
- Vercel以外でNext.jsをホスティングした場合、最適化後の画像にICCプロファイルが適用されない

# Next.jsのデフォルトのImage Loaderはsquoosh

Next.jsの `npx next start` コマンドで動く productiom モードにおいて、デフォルトのimage loaderとして [squoosh](https://github.com/GoogleChromeLabs/squoosh) が選択される。

squooshは内部的にはWebPコーデックとして libwebp が動いている模様

https://github.com/GoogleChromeLabs/squoosh/tree/dev/codecs/webp

# Sharpを指定する

以下のように
```js:next.config.js
  images: {
    output: 'standalone',
  },
```

libwebpではデフォルトでICCプロファイルが削除される仕様とのこと

https://qiita.com/bosteri_bon/items/48b88f56fb26645a6a66#%E6%9C%AC%E9%A1%8C%E8%89%B2%E5%91%B3%E3%81%8C%E8%90%BD%E3%81%A1%E3%82%8B

それに対して sharp では libvips  が使われている模様

https://github.com/lovell/sharp/blob/main/lib/libvips.js
Discord.pyでモーダルを使用したい。

DiscordにてModal機能を使用したいと思っています。
以下のように入力しましたが、中々解決できません。

≪目指す目標≫
Discord内で必要な情報をmodalで収集して管理したい。

≪流れ≫
/modalでフォーム(モーダル)を呼び出す。
↓
メールアドレス、住所、名前など、指定した項目を入力してもらう
↓
送信
↓
送信されたデータをスプレッドシートで受け取る
※CSVなどでも可

入力したPythonコード
```
import discord
from discord.ext import commands
from discord import Interaction

bot = commands.Bot(command_prefix='.', intents=discord.Intents.all())


class FavoriteFoodModal(discord.ui.Modal):
    def __init__(self):
        super().__init__(
            title="好きな食べ物は何ですか？",
            timeout=None,
        )

        self.food = discord.ui.InputText(
            label="食べ物",
            style=discord.InputTextStyle.short,
            placeholder="おにぎり",
            required=True,
        )
        self.add_item(self.food)

    async def callback(self, interaction: Interaction) -> None:
        await interaction.response.send_message(f"好きな食べ物は{self.food.value}なんだね！")
        return


@bot.command(name="food", description="好きな食べ物を聞きます")
async def food_slash(interaction: Interaction):
    modal = FavoriteFoodModal()
    await interaction.response.send_modal(modal=modal)

bot.run("TOKEN")
```

テストで食べ物の好みを聞くものを作っています。
上手く機能したら、必要な情報を書いてもらうようなものに仕上げる予定でした。
ちなみにスプレッドシートに飛ばす方法もわからないため、今のところ放置状態です。
.foodで起動できるようにしています。
しかしながらコマンドを押してもVisual Studioにエラーが返ってきます。

```
Ignoring exception in command food:
Traceback (most recent call last):
  File "C:\Python311\Lib\site-packages\discord\ext\commands\core.py", line 178, in wrapped
    ret = await coro(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\Desktop\bottest\main.py", line 31, in food_slash
    await interaction.response.send_modal(modal=modal)
          ^^^^^^^^^^^^^^^^^^^^
AttributeError: 'Context' object has no attribute 'response'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Python311\Lib\site-packages\discord\ext\commands\bot.py", line 347, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Python311\Lib\site-packages\discord\ext\commands\core.py", line 950, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Python311\Lib\site-packages\discord\ext\commands\core.py", line 187, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'Context' object has no attribute 'response'
```

全くmodalが出る気配が無く困っていますが、解決方法として何が考えられるでしょうか。
データフレームのデータスライス時に発生するエラー

本記事は個人用のメモ書きである。
あくまで、似たようなエラーで引っかかってしまった初学者の方向けの記事になるので、一般的な内容を期待されている方は回れ右をしていただきたい。

# 事象

今回の発生したエラーは、とある記事通りにコードを実装していた際に発生した次のエラーである。

```python
single_image = pixel_values[1,:].reshape(28, 28)
```
> InvalidIndexError: (1, slice(None, None, None))

このコードでやりたかった処理としては、pixel_valuesというリスト（画像がいっぱい格納されている三次元のイメージ）から、一つ目の画像を引っ張ってこようと1行目のレコードをスライスしようとした形である。
しかし、この初めて見るエラーが出てきたため、面食らってしまった。

# 原因
こんなことを言うのは「お前いくらなんでもいい加減すぎるだろう」と馬鹿にされそうで憚れるのだが、結論原因はデータ理解の不足である。
pixel_valuesをリスト（或いはnumpy系のやつかな～）という認識でいたのだが、実はこのデータはpandasのデータフレームであった。

「まさかデータの種類も知らずにデータスライスするやつがいるとは。。。」と呆れている人もいるだろうが、現にここにいるのである。
データフレームを直接スライスはできないので、ちゃんとpandasの仕様に合わせたスライスの仕方をすることが解決策となる。

# 解決策
```python
single_image = pixel_values.iloc[1,:].values.reshape(28, 28)
```

ここまで書けばもう充分かもしれないが、念のため解決策となるコードも上に記載しておく。
ポイントはilocを使用したデータスライスである。

また、このスライスで取得できるのはデータシリーズのため、直接reshapeができないので、間にしれっとvaluesを挟んでいる。

# 総括
自分が扱っているデータがどの種類でどんな形で保持されているのか理解する。
当たり前だけど、これを怠らないことが大事である。
（本記事が該当エラーで困惑してしまった人の助けに少しでもなれば幸いである。）
npm ERR! Unexpected token '.' の解消方法

## 事象

npmコマンドを実行時に `Unexpected token '.'` が発生した。

```
$ npm update -g  
npm ERR! Unexpected token '.'
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\***\AppData\Local\npm-cache\_logs\2023-09-20T15_29_23_397Z-debug-0.log
```

### 環境

npm 10.1.0
nvm 1.1.7
node.js 16.13.1
OS Windows10


## 原因

nvmとnodeのバージョンの相性が悪いから？と思われる。
npmのバージョンを確認すると警告が出力されるけど関係あるのかな？？

```
$ npm -v
npm WARN cli npm v10.1.0 does not support Node.js v16.13.1. This version of npm supports the following node versions: `^18.17.0 || >=20.5.0`. You can find the latest version at https://nodejs.org/.
10.1.0
```

## 対応方法

出力されたログを参考に使用するnodeのバージョンを切り替えれば解消する。

```
This version of npm supports the following node versions: `^18.17.0 || >=20.5.0`.
```

今回だと `18.17.0` がよいみたい。

```
$ nvm install 18.17.0 
Downloading node.js version 18.17.0 (64-bit)...
Extracting node and npm...
```

バージョン切り替え後、失敗したnpmコマンドを再実行すると正常終了する。

```
$ npm update -g
removed 12 packages, and changed 78 packages in 12s

$ nvm use 18.17.0     
Now using node v18.17.0 (64-bit)
```
DBeaverでテーブルを新規作成したのに、データベースナビゲーターに表示されない

お疲れ様です。
新卒一年目の翔太です！
今回は、DBeaverでデータベースを作成する際に、データベースが反映されなかったという問題が発生したため、調査しました。

## DBeaverでテーブル作成すると、データベースナビゲーターに表示されませんでした
下記画像のように、テーブルを作成しましたが、画像の左側にあるデータベースナビゲーターに表示されませんでした。
![スクリーンショット 2023-09-21 0.33.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/b9b47a7e-1926-088e-fa4e-91751c25fd1a.png)


## 表示されないので、もう一度テーブルを作成してみる
下記画像のように、もう既に存在している旨のエラー(SQLエラー [42P04]: ERROR: database "sample" already exists)となりました。
ということは、「**存在はしているけど反映されていない、または表示されてない**」ということがわかりました。
![スクリーンショット 2023-09-21 0.38.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/ba40d838-9775-9bf4-d804-1c3b0fea2b01.png)

## 対処法
PostgreSQLの設定でテーブルの設定を「Show all databases」にしないと変更が反映されないことがわかりました。
手順としては、以下の通りです。
1.  データベース名で右クリックをし、編集接続をクリックします。(F4キーでもいけるそうです)
![スクリーンショット 2023-09-21 0.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/d585e693-05a0-4665-b4f0-52f162c85a5c.png)

2. 画面左側の接続設定を選択し、PostgreSQLを選択する 
![スクリーンショット 2023-09-21 0.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/a905b6fa-e638-858e-518b-6eb15e185c76.png)



3. Show all databasesのチェックボックスをクリックして、OKを選択します
![スクリーンショット 2023-09-21 0.52.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/757cdfaa-ab5a-c6ed-a855-dabc20986e02.png)

4. 再接続しますか？と出るのでYesを選択します
![スクリーンショット 2023-09-21 0.54.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/104aea97-5449-b147-f2a8-f9402e3a8f61.png)

5. これでデータベースの作成が反映されます。
![スクリーンショット 2023-09-21 0.56.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2005551/0c5c4a08-2e48-9051-7cb2-40681a6bfcf8.png)

## 参考文献
https://github.com/orgs/dbeaver/discussions/15121

## まとめ
Dbeaverの仕様は結構めんどくさいのと、記事を書いてのoutputは大事だなと感じました
GoでWebアプリケーションを作る（8）ーテスト

こんにちは。

今日は「テスト」についてです。

これまで作り上げてきたGyudon型にテストを追加してもらいます。

# Go言語でのテストのやり方

Go言語にはテストをサポートする標準パッケージ [testing](https://pkg.go.dev/testing)があります。 そのためなにかテストフレームワークを使うのではなく、標準のライブラリを使用してテストを行うケースが多いです。

テストは以下のコマンドだけで実行できます。 `./...`でカレントディレクトリ以下のすべてのファイルが対象となります。

```go
$ go test ./...
```

`<機能>.go`というファイルがある時、テストは`<機能>_test.go`という名前のファイルに記述していきます。

テストの関数は下のような書き出しで始めます。

```go
func Test<テスト名>(*testing.T)
```

このような関数のテストを書くときを考えます。

```go
func IsTopping(food string)bool{
	switch food {
	    case "BeniShoga":
		    return true
		
	    case "Egg":
			retuen true
			
    }
	return false
}
```

簡単なテストを書くとこのようになります。 panicしたり、Errorに書き込まれなければテストは成功です。

```go
func TestIsTopping(t *testing){
	food := "BeniShoga"
	
	if got:=IsTopping(food); !got{
		t.Errorf("food = %s , want",got)
    }
}
```

# テストの実行と修正

では、基本的なテストのやり方を知ってもらったので、実際に試してみましょう。
本講義では5章で作った関数Eatにテストを追加する形で進めます。

手始めに関数TestGyudon_EatSimpleをいじってテストの挙動を確認してみましょう。

### 試してみてほしいこと

- `want`と`go`tを比較して、違っていたら`t.Errorf()`にメッセージを表示するように修正する
- テストを実行する
- 文字が一致してテストが成功するパターンを試す
- 文字が一致せずテストが失敗するパターンを試す

```terminal
:# TERMINAL 0
:# WORKPATH /../8_test/test/

$ cd /../8_test/test/
$ <お好きなエディタ> shop/shop_test.go
$ go test ./...
```

- `/../8_test/test/shop/shop_test.go`

```go
func TestGyudon_EatSimple(t *testing.T) {
w := bytes.Buffer{}
r := http.Request{}

gd := NewGyudon()
gd.menu="<入れたい文字列>"
gd.Eat(&w, &r)
/// 関数の結果を格納
got := w.String()

/// 判定処理を書く
}
```

- 結果

```terminal
:# TERMINAL 0
:# WORKPATH /../8_test/test/

$ cd /../8_test/test/
$ <お好きなエディタ> shop/shop_test.go
$ go test ./...
```

- `/../8_test/test/shop/shop_test.go`

```go
if want != got {
    t.Errorf("want = %s, got = %s\n", want, got)
}  
```

# その他のテストの書き方

2で試したテスト関数 TestGyudon_EatSimple のやり方の場合、引きすうごとにテストの関数を追加せねばならず不便です。 そのため、テスト関数 TestGyudon_Eat のように一つの関数内で複数のパターンのテストを記述することもよくあります。 時間に余裕があったり、興味があるひとはテスト関数 TestGyudon_Eat にあるテストパターンの間違いを修正したり、関数 Eat が参照する変数が空の場合のテストケースを追加してみてください。

# 最後に

今回は、Goを知ってもらうために、Goの概要説明、実行やコンパイル、関数や構造体、そして、Goroutineをサクッと追っていきました。
今回紹介しきれていない`interface`や`channel`、`context` 辺りを学習するとよりGo言語が、選択肢としての幅が広がっていくと思います。
もしGo言語をもっと知ってみたいと思っているのであれば、Goが学習できる go tour(日本語) (opens new window)を、まずは一周してみることをお勧めします。
基本的な構文や、Go言語の構造体の説明、先程あげたinterface, channel の説明があります。(執筆時点、contextの説明はありませんでした)


今日は以上です。
ありがとうございました。
Serialization of 'Closure' is not allowedというエラーを理解する



## エラーが起きた経緯
Laravelで以下のようにユーザ登録をしたときにユーザにメール通知を送るようにしていました。

```php
        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        $user->registered($request);
```

registered関数はNotificationクラスを使って通知を送るものです。

今回、通知を非同期処理にしようと思い、Notificationクラスに`implements ShouldQueue`を追記しました。


すると、ジョブは正常にキューに追加できずに
`Serialization of 'Closure' is not allowed`
というエラーが発生しました。

## エラー文の解読

1. **Serializationとは**: 
シリアライズとは、オブジェクトを文字列やバイナリの形式に変換するプロセスのことを指します。Laravelのキューシステムでは、ジョブをキューに追加する際に、ジョブに関連するデータがシリアライズされ、後でデシリアライズされて処理されるそうです。


2. **Closureのシリアライズ**: 
エラーメッセージは、**`Closure`** をシリアライズすることはできないと指摘しています。
一般的に、クロージャ（無名関数）やリソースへの参照（例えばデータベースの接続やファイルハンドルなど）はシリアライズできず、**`Request`** オブジェクトにはそれらが含まれている可能性があります。


###  $requestの中身
実際、ddでリクエストの中身を見てみると、Closureが確認できました![スクリーンショット 2023-09-21 0.38.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730982/5e3e6d25-eb8c-3506-be2d-d4a7cdf59530.png)



## **解決策**: **`$request->all()`** を使用する
冒頭のコードのregistered関数に与える引数を変更しました
```php
        $user->registered($request->all());
```

`$request->all()`は、リクエストの入力データを連想配列として取得できます。この連想配列はシリアライズ可能なので、ジョブのクラスに渡して使用することができます。

要するに、ジョブやイベントをキューに追加する際には、シリアライズ可能なデータのみを渡す必要があるみたいです。ここでも、リクエストオブジェクトそのものを渡すのではなく、必要なデータだけを取り出してジョブに渡す必要があります。


## 補足
メールのフォーマットに渡すデータをオブジェクトではなく連想配列にしたので、その取り出し方の記述も以下のように変えた

```php

//変更前
{{ $user->name }}さん、こんにちは。<br>

//変更後
{{ $user['name'] }}さん、こんにちは。<br>
```
Node-REDのhttp inノードでワイルドカードを使う

# Node-REDのhttp inノードで若干ハマったのでメモ

Node-REDで簡単なWebサーバーを作る場合はhttp inノードを使用します。
以下のような存在しないページに対するアクセスにカスタムの404ページを返す動作を実現する方法がないか調べてみました。
- `/test`へのアクセスには特定のWebページを返す。
- `/test`以外(たとえば`/`とか`/test/123`とか`/hoge`とか)へのアクセスには404ページを返す。

一部のリソースだけは専用の応答を返し、それ以外は全部固定のエラーを返すようなイメージです。
ヘルプには載っていなかったのですが、Node-REDのフォーラムに以下の投稿がありました。

https://discourse.nodered.org/t/wildcard-in-http-in-node-catch-all-mode/14852

http inノードのURLはワイルドカード指定が可能のようです。
以下のようなフローを作ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57609/a300ecc0-da52-8b33-589f-0deff4d4a6fd.png)

`/test`にアクセスすると確かに`/test`のhttp inノードが呼ばれます。ちなみに`/test/`も同様でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57609/9f8944fa-150d-2e05-a4fa-08ec8f95c14b.png)

`/`や`/test/123`、`/hoge`にアクセスするとやはり`/*`のhttp inノードが呼ばれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57609/2bb93698-a7e3-107a-1a54-7af7aa284971.png)

どのhttp inノードが呼ばれるかはURLの最長一致で決まるんでしょうね。

## ワイルドカードのhttp inは最後に置くべし？

これで完璧じゃんと思ったのですが、いろいろいじってみるとさっきと動作が違うことに気づきました。
ためしに`/test`のhttp inノードを削除後すぐに`/test`のhttp inノードを再配置してデプロイしてみます。
そして`/test`を再度呼び出してみると**なんということでしょう**`\*`のhttp inノードが呼び出されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57609/ef7b4ee2-7d0b-cffb-e81e-3927b530c04f.png)

次に`/*`のhttp inノードを削除して同様に再配置してデプロイします。
今度は正常に戻りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57609/a58f209a-b5c4-bdab-4f85-0ae8edb64652.png)

**ノードが配置された順番に待ち受けるパスが先着で決まっていく**ような挙動になっているように見えます。
- すでに`/*`のhttp inノードが存在する場合、`/`以降のパスはすべて予約済みになり、
後から`/test`のhttp inノードが来てもすでに先客がいるから`/test`で待ち受けることはできない。
- 一方で`/*`のhttp inノードをいったん削除したら予約済みだったパスが解放されるので、
`/test`のhttp inノードが待ち受けることができるようになる。

要は**より曖昧なマッチングをするhttp inノードは最後に置け**ということになります。
今回のようなざっくりとしたものではなく、もっと細かく階層ごとにワイルドカード指定するような場合などは気づきにくいので注意が必要ですね。

こういうのってどこかのドキュメントに書いていたりしますかね？もしかして常識？
Rubocop

# 初学者の備忘録
初学者の備忘録です。今回はRubocop編


## Rubocopとは
プロジェクトに記述されているRuby（Rails）のコードがコーディング規約に遵守されているかチェックを行う、静的コード解析ツールです。

コーディング規約とは？
開発をする際にコードをどのように書くのかを規約として設けることで、コードに統一性を持たせることを目的とします。
規約の一例としては命名規則や禁止事項などが挙げられます。

らしいのですが難しいので私はインデントや全角などを検出してくれるものだと認識してます。そのためにはルールを変えなければいけないのですが、チャットGDPとかに聞くとルールのコードを教えてくれます。


## 導入
「Gemfile」のdevelopmentグループに以下の記述を追記します。
```diff_ruby:Gemfile

group :development do

:
:

  +gem 'rubocop', require: false
  +gem 'rubocop-performance', require: false
  +gem 'rubocop-rails', require: false
  +gem 'rubocop-minitest', require: false
  +gem 'rubocop-packaging', require: false
  +gem 'rubocop-rspec'end
```


【２】　インストール
Gemを有効化するためにインストールします。
```ruby:ターミナル
$ bundle install
```


【３】　設定ファイル
設定ファイルを作成していきます。ここの記述でルールが決まります。
```ruby:ターミナル
$ bundle exec rubocop --auto-gen-config
```


【４】　.rubocop.yml編集
.rubocop_todo.ymlと.rubocop.ymlが生成されます。
.rubocop.ymlを次のように編集します。
```ruby:qiita.rb
require:
  - rubocop-minitest
  - rubocop-packaging
  - rubocop-performance
  - rubocop-rails

# 全て
AllCops:
# すべてのCopをデフォルトで無効にする
  Enabled: false 
# インデントに関する指摘を有効にする
Layout/IndentationWidth:
  Enabled: true
Layout/IndentationConsistency:
  Enabled: true
# 全角文字の存在に関する指摘を有効にする
Style/AsciiComments:
  Enabled: true
```


導入は以上です。お疲れ様でした。


## 実装
実際に使用してみましょう。
ターミナルにコマンドを入力します。
このコマンドで全てのファイルを確認し、違反を検出してくれます。
```ruby:ターミナル
$ bundle exec rubocop
```

自動修正コマンド
```ruby:ターミナル
$ bundle exec rubocop -a
```
自動修正コマンドのさらに強いコマンド
```ruby:ターミナル
$ bundle exec rubocop -A
```
ファイル単位
```ruby:ターミナル
$ bundle exec rubocop -a {解析対象ファイル}
```
フォルダ単位
```ruby:ターミナル
$ bundle exec rubocop -a {解析対象フォルダ}
```
差分単位
```ruby:ターミナル
$ bundle exec rubocop -a $(git diff $(git merge-base origin/master HEAD) --diff-filter=d --name-only)
```

＊自動修正は思った修正と違う場合がありますので注意してください。自動修正コマンド実行する前にコミットしておくことをおすすめします。

＊警告が出る場合
```ruby:ターミナル
Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. Please call `DidYouMean.correct_error(error_name, spell_checker)' instead.
```
警告が出ましたら下記のコマンドを入力してください。
```ruby:ターミナル
$ bundle update --bundler
```


以上です。
Spark on k8s 概要と機能

## Spark on k8s 概要と機能

Apache Sparkは、大規模データ処理のためのオープンソースのクラスター分散処理フレームワーク。Spark on Kubernetes（通称Spark-Kubernetes）は、Kubernetes上でSparkアプリケーションを実行するための専用の機能セット。以下にSpark-Kubernetesの概要と主な機能を詳しく説明する。

### Spark-Kubernetesの概要

Spark-Kubernetesは、SparkアプリケーションをKubernetes上で実行するための統合プラットフォームであり、以下のような特徴を持っている。

- クラスターマネージャーの代わりにKubernetesを使用してSparkアプリケーションをデプロイ、管理、スケジュールする。
- Kubernetesのリソースマネージャーとしての機能を利用して、Sparkのタスクスケジューリングとリソース割り当てを行う。
- Kubernetesクラスタ上で複数のSparkアプリケーションを同時に実行し、異なるアプリケーション間でリソースを共有する。

### Spark-Kubernetesの主な機能

1. **エクゼキューターポッド**: Spark-Kubernetesは、各SparkエグゼキューターをKubernetesのポッドとして実行する。これにより、エグゼキューターのスケーリングや障害に対する自動回復が可能になる。

2. **リソースマネージャー**: Kubernetesのリソースマネージャーを使用することで、Spark-Kubernetesはクラスターリソースの効率的な管理と最適なタスクスケジューリングを実現する。

3. **ダイナミックアロケーター**: Spark-Kubernetesは、必要なリソースに基づいてエグゼキューターポッドの数を自動的に調整するダイナミックアロケーターを提供する。これにより、タスクの性能を最適化し、クラスターのリソース使用率を高めることができる。

4. **Sparkアプリケーション管理**: ステータス監視、ログ収集、タスクの再起動など、Sparkアプリケーションの管理に必要な機能を提供する。また、Sparkアプリケーションの再デプロイやスケーリングも容易に行うことができる。

5. **永続ボリュームサポート**: Spark-Kubernetesは永続ボリュームをサポートしており、ストレージにデータを永続化することができる。これにより、Sparkアプリケーションのデータの保持やバックアップなどが容易に行える。

## Kubernetesでの稼働のメリットとデメリット

**メリット:**

1. **スケーラビリティと柔軟性**: Kubernetesは、クラスター全体のリソース管理とスケジューリングを自動化するため、Sparkアプリケーションを柔軟にスケールアウトできる。また、Kubernetesのコンテナ化された環境により、アプリケーションのデプロイや管理が容易になる。

2. **リソース効率と共有**: Kubernetesのリソースマネージャーを使用することで、クラスター内のリソースの効率的な利用が可能になる。また、異なるSparkアプリケーション間でリソースを共有することにより、クラスターの使用率を高めることができる。

3. **クラスター管理の抽象化**: Kubernetesは、クラスターの管理タスクを抽象化するため、開発者や運用チームはクラスターの詳細に関与することなく、Sparkアプリケーションのデプロイとスケーリングに集中できる。

**デメリット:**

1. **学習コスト**: Kubernetesの設定や操作について学習する必要がある。特に初めて利用する場合、学習コストや導入コストが発生する可能性がある。

2. **複雑さ**: Kubernetesは柔軟なシステムであり、機能が豊富ですが、その分操作や設定が複雑になることがあある。適切な知識とリソースが必要となる場合がある。

以上が、Spark-Kubernetesの概要と機能についての情報。

### サンプルコード（Java）

以下は、Javaで記述されたSpark-Kubernetesアプリケーションの簡単なサンプルコード。

```java
import org.apache.spark.api.java.*;
import org.apache.spark.SparkConf;

public class SparkKubernetesExample {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf()
	        .setMaster("k8s://https://<kubernetes-master>")
	        .setAppName("SparkKubernetesExample")
	        .set("spark.kubernetes.namespace", "<kubernetes-namespace>")
	        .set("spark.executor.instances", "2")
	        .set("spark.kubernetes.container.image", "<docker-image>");

	    JavaSparkContext sparkContext = new JavaSparkContext(conf);

	    // Sparkアプリケーションの分散処理

	    sparkContext.stop();
	}
}
```

上記の例では、SparkConfを使用してSparkアプリケーションの設定を行う。`kubernetes-master`と`kubernetes-namespace`には、Kubernetesクラスターのマスターノードの情報と実行するネームスペースが指定される。`spark.executor.instances`にはエグゼキューターの数が指定されます。`docker-image`にはSparkエグゼキューターのDockerイメージ名が指定される。

このサンプルコードは、Spark-Kubernetesの基本的な設定とSparkアプリケーションの実行方法を示しています。アプリケーションの主要な処理は、実際の要件に応じて適切に記述する必要がある。

以上が、Spark-Kubernetesについての概要と主な機能、およびJavaでのサンプルコード。
【積読】驚き最小の原則

### 予想通りのインターフェース
インターフェースは、それを使う人が想像するであろう形に設計します。
つまり、使う人の驚き（意外に思う気持ち）が最小になるように設計するということです。インターフェースの設計では、意味もなく新奇なことをしたり、過度に奇妙なことをしたりすることは避けるようにします。

### 学習コストが低くなる
最も簡単に使えるソフトウェアとは、ユーザーが新しく学ばなければならないことが最も少ないソフトウェアです。つまり、ユーザーが元々持っている知識に、最も効果的に接続できるソフトウェアのことです。ユーザーの思った通りに動作するソフトウェアは、すぐに使え、ストレスなく使えるので、永く使われるソフトウェアになります。

### ユーザーの既知を活用する
予想通りに動作するようなインターフェースを設計するために、以下の点を気を付ける。

##### よく似たソフトウェアのインターフェースをモデルにする
ユーザーがよく使っていて、機能がよく似たソフトウェアのインターフェースを踏襲するようにする。例えば計算のソフトウェアを開発しているなら、電卓のように「＋」はいつでも「加算」という意味にすべき。


##### 想定ユーザーの特徴を理解する
ユーザーのタイプによって、驚きが小さいインターフェースが何かが異なる。


##### 伝統に注意を払う　
プログラミングの世界には「お馴染み」の習慣がある。伝統が築かれたことには、学習を容易にするという理由があります。

##### 「一見似ているが微妙に異なる」ということを避ける
馴染みのあるものは、既知のものという期待を高めるだけに、裏切られた時の失望が大きくなります。ほとんど同じものを作るくらいなら、全く異なるものを作った方が、ユーザーにとっては親切。

----
参考文献
「*プリンシプル オブ プログラミング3年目までに身につけたい一生役立つ101の原理原則*」


https://www.amazon.co.jp/dp/4798046140?ref_=cm_sw_r_cp_ud_dp_0C637KV2ZJAP5TECFEK4_2
GitHubとかでリポジトリに追加するファイル

#### 1. `README.md`

- **目的**: プロジェクトの概要、使い方、インストール方法など、プロジェクトの基本情報を伝える。
- **内容**: プロジェクトの説明、使い方、スクリーンショットやGIF、ライセンス情報など。

#### 2. `.gitignore`

- **目的**: Gitでトラックしたくないファイルやディレクトリを指定する。
- **内容**: 例) ビルド結果、一時ファイル、センシティブな情報など。

#### 3. `LICENSE`

- **目的**: プロジェクトのライセンス情報を明示する。
- **内容**: GPL, MIT, Apacheなど、適切なオープンソースライセンスのテキスト。

#### 4. `CONTRIBUTING.md`

- **目的**: 他の開発者がプロジェクトに貢献する際のガイドラインを提供する。
- **内容**: 貢献の手順、コードのスタイルガイド、テストの実行方法など。

#### 5. `CODE_OF_CONDUCT.md`

- **目的**: コミュニティの行動規範を設定する。
- **内容**: プロジェクトへの参加者間の予期される行動や、不適切な行動への対応策など。

#### 6. `.github/`ディレクトリ

- **目的**: GitHubの特定の機能や設定を管理する。
- **内容**: 
  - `ISSUE_TEMPLATE/`: イシュー作成時のテンプレート。
  - `PULL_REQUEST_TEMPLATE.md`: プルリクエスト作成時のテンプレート。

#### 7. `CHANGELOG.md`

- **目的**: バージョンごとの変更履歴をトラッキングする。
- **内容**: 新機能、変更点、バグ修正、非推奨となった機能のリストなど。

#### 8. `SECURITY.md`

- **目的**: セキュリティ上の問題を報告するためのガイドラインを提供する。
- **内容**: 問題の報告方法、脆弱性への対応策の公表タイミングなど。
Trust Wallet Clone and Exchange Clone Script: A Roadmap to Success

Trust Wallet Clone and Exchange Clone Script requires a multifaceted approach. Start with thorough market research to gain a deep understanding of the cryptocurrency landscape, assessing user needs, analyzing competitors, and staying abreast of industry trends. Ensure your project's objectives are well-defined, establishing clear goals, timelines, and budgetary constraints. Legal compliance is paramount, with the need to navigate complex cryptocurrency regulations that vary by region. Assemble a capable team of developers, designers, and security experts with a solid background in cryptocurrency and blockchain technology. Your choice of technology stack will lay the foundation for the reliability and scalability of your solutions. Security should be a top priority, encompassing the implementation of advanced security protocols, rigorous testing, and periodic security audits to safeguard user assets. Creating an intuitive user interface and seamless user experience is pivotal, enhancing adoption and retention rates. Comprehensive testing, including beta testing, is essential to iron out any issues before the mainnet launch. Marketing and promotion efforts should be designed to create awareness and attract early users through digital marketing, partnerships, and informative content. Post-launch, continuous improvement, customer support, and robust security monitoring will ensure your Trust Wallet Clone and Exchange Clone Script not only survives but thrives in the dynamic cryptocurrency landscape.

Visit Site: https://www.omninos.in/Trust-Crypto-wallet-clone.php
PowerShell でシステム環境変数を設定・削除してみた

# 前提
* PowerShell は管理者モードで起動していることとする。

# 1. バージョン情報
## 1.1. Windows OS Version
~~~
PS C:\Users\Administrator> (Get-CimInstance -ClassName Win32_OperatingSystem).Version
10.0.19045
PS C:\Users\Administrator>
~~~

## 1.2. PowerShell Version
~~~
PS C:\Users\Administrator> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.19041.3031
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.3031
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
PS C:\Users\Administrator>
~~~

# 2. 事前確認
* 何も表示されないのが正。
~~~
PS C:\Users\Administrator> $variableName = "hoge"
PS C:\Users\Administrator> [System.Environment]::GetEnvironmentVariable($variableName, [System.EnvironmentVariableTarget]::Machine)
PS C:\Users\Administrator>
~~~

# 3. システム環境変数の設定
## 3.1. 設定
~~~
PS C:\Users\Administrator> $variableName = "hoge"
PS C:\Users\Administrator> $variableValue = "hogehoge"
PS C:\Users\Administrator> [System.Environment]::SetEnvironmentVariable($variableName, $variableValue, [System.EnvironmentVariableTarget]::Machine)
PS C:\Users\Administrator>
~~~

## 3.2. 確認
~~~
PS C:\Users\Administrator> [System.Environment]::GetEnvironmentVariable($variableName, [System.EnvironmentVariableTarget]::Machine)
hogehoge
PS C:\Users\Administrator>
~~~

# 4. システム環境変数の削除
## 4.1. 削除
~~~
PS C:\Users\Administrator> $variableName = "hoge"
PS C:\Users\Administrator> $variableValue = $null
PS C:\Users\Administrator> [System.Environment]::SetEnvironmentVariable($variableName, $variableValue, [System.EnvironmentVariableTarget]::Machine)
PS C:\Users\Administrator>
~~~

## 4.2. 確認
* 何も表示されないのが正。
~~~
PS C:\Users\Administrator> $variableName = "hoge"
PS C:\Users\Administrator> [System.Environment]::GetEnvironmentVariable($variableName, [System.EnvironmentVariableTarget]::Machine)
PS C:\Users\Administrator>
~~~