OmniAICreator/Qiita-1.07M huggingface dataset:
Vue3.0 + Cropperjs

# はじめに

vueでcropperjsを使用する方法です

# 方法

1.プロジェクトの作成

```
vue create aaaaa
```

2.作成したプロジェクトに入り,`cropperjs`をインストール

```
cd aaaaa
npm install cropperjs
```

3.`src/App.vue`を以下のように変更

```vuejs:src/App.vue
<template>
  <img ref="cropImg" alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

import Cropper from 'cropperjs';
import "cropperjs/dist/cropper.css";

export default {
  name: 'App',
  components: {
    HelloWorld,
  },
  mounted() {
    this.cropper = new Cropper(this.$refs.cropImg, {
      background: false,
      modal: false,
      highlight: false,
      viewMode: 1
    });
  },
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```

4.実行

```
npm run serve
```

5.結果

※クロップ後の画像が欲しい場合は`this.cropper`が持っているのでそこから取得します

![Screenshot from 2021-11-25 18-21-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/84759f40-ba89-baed-46c7-730b73b2cb96.png)

# 参考
vueとcropperjsによる映像クロップ: https://codesandbox.io/s/vue-cropperjs-video-u56xz?file=/src/main.js

# 環境

ubuntu20.04
dockerネットワークについて調べる〜ネットワークの種類

今回のお題
-
[前回](https://qiita.com/keishi04hrikzira/items/02cf242f7b54c907adca)は`docker-compose`を用いて複数のコンテナを同時に作成しましたが、その結果それらの間でも通信ができるようになりました。

これはコンテナ同士がdockerネットワークという同一の入れ物に入っているからであり、docker-composeを用いることでコンテナの作成だけでなくネットワークの整備までもが自動で進むのがdocker-composeのメリットだと言われています。

と、偉そうに言いましたが、docker-composeが自動でやってくれたおかげで私自身dockerネットワークについてはほとんどわかっていません。

ですので、それらについて自分なりに調べた内容をここにメモしておこうと思います。

復習〜Dockerネットワークとは
-
複数のコンテナを連携させるための箱のようなもの。

ほとんどのサービスは複数のコンテナを利用することで成り立っているため、コンテナ同士での通信が必要になる。

コンテナ同士を同一のネットワークに所属させることでそれらの間での通信が容易になり、結果的にサービスの構築が簡単になる。

Dockerネットワークの種類
-
Dockerネットワークには大きく分けて3つのタイプがあり、それぞれ`bridge`, `host`, `null(none)`と呼ばれる。

この分類は、ネットワーク内のコンテナがホストOSの外部とどのようにして通信するのかによって行われている。

ネットワークの種類がnull(none)の場合、コンテナは外部と通信できない。

hostにおいては、ネットワークに所属するコンテナはホストOSのプライベートIPアドレスを使って通信することになる。

bridgeにおいてはコンテナごとにホストOSとは別のIPアドレスが割り当てられ、ホストOSとコンテナのIPアドレスを仮想スイッチと呼ばれる装置が中継(bridge)することで通信が成立している。

作成されたコンテナのネットワーク設定
-
Dockerはデフォルトで3つのネットワークを保有しており、それぞれのネットワーク名やネットワークタイプについては以下のようになっている。

```shell
# 作成済みのネットワークを一覧表示
% docker network ls
NETWORK ID     NAME                              DRIVER    SCOPE
59c6a0c60086   bridge                            bridge    local
efba6f694b6f   host                              host      local
a0d4f5e885f9   none                              null      local
```
`docker run`コマンドで作成されたコンテナについては基本的には上記のbridgeに所属するが、`--net`オプションを付けることで所属するコンテナの指定が可能。

```shell
# これだとbridgeに所属
% docker run -it -d centos:centos7

# hostを指定
% docker run -it -d --net=host centos:centos7

# noneを指定
% docker run -it -d --net=none centos:centos7
```

また、`docker-compose up`コマンドを用いてコンテナを作成した場合には`xxxx_default`という名前のネットワークが新しく作られるが、この際も特に指定がなければdriverはbridgeになる。

また、デフォルトのbridgeであっても新規作成されたbridgeネットワークであっても、コンテナ作成時に自動的にIPアドレスが付与される。

終わりに
-
長くなってしまったので一旦ここまでにします。

次回はbridgeの仕組みについてまとめる予定です。
CloudFront の プロトコル設定

CloudFront のオリジン、ビヘイビアの設定のプロトコルの欄について。

#オリジンの設定

![スクリーンショット 2021-11-25 16.36.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/3eef2476-9ec6-a1f0-bec7-615411960577.png)

CloudFront からオリジンへのアクセスプロトコルを指定する。
選択肢は以下の3つ。
- HTTP のみ
- HTTPS のみ
- マッチビューワー

例えば、HTTPを選択するとクライアントから HTTPS でアクセスが来ても CloudFront からオリジンへのアクセスは HTTP を使用する。
また、マッチビューワーを使用してクライアントのプロトコルに応じた切り替えも可能。

#ビヘイビアの設定
![スクリーンショット 2021-11-25 16.56.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1488939/d46683f6-1305-6e15-c29c-9bc4d86c315f.png)

###ビューワープロトコルポリシー
クライアントからのリクエストを受け付けるプロトコルを指定する。
選択肢は以下の3つ。
- HTTP と HTTPS の両方からのリクエストを受け付ける
- HTTP を　HTTPS にリダイレクトする
- HTTPS のリクエストのみ受け付ける


###許可された HTTP メソッド
受け付ける HTTP メソッドを選択できる。
(僕はここが [GET, HEAD] だったために PUT を受け付けず、ブラウザからWordPressが表示できない、という失敗をした。)

#参考資料
https://qiita.com/SwuBHj8aKGqBKHet/items/5c52ea718ccfd795a048
【リベンジ】寝る催促をLINEにしてもらうように2回分設定。God(・´з`・)ちゃんも一緒に寝たいんだな！

ゲームや映画・アニメ・動画鑑賞、そしてツーリングで行きたい先の調査や思い出の写真を見返す・・・などなど誘惑はたくさんありますよね。
夜更かしして睡眠時間を削りがちの私。次の日に眠くてヤバイ日を過ごすこともしばしば。
それに、約10年間通勤時間が片道10分の職場で勤務していましたが、1か月半前に勤務地変更があり、在宅メイン＆出勤する日は通勤時間が片道2時間半弱になりました。

**生活リズムが崩れまくり、精神面もやばくなってきそうなので、どうにかしたい！！**と思い、アラームで時間を設定してやったこともあるのですが、熱中している最中にアラームが鳴ると、うるさいのですぐに消してしまい、意識する前にアラームが鳴ったことを忘れて意味がなくなっていました。

LINEは頻繁に見るので、LINEに送ってあったら消えないし目に付くし、集約した方が便利だと思ったのでLINEへ通知することにします。
アラームみたいにうるさくないし、アラームみたいに消して終わりということもないから良いかも。
それに、すぐに寝る態勢に入れなくても2回目の通知もあれば**睡眠時間を確保できる**んじゃないかと思っています。
※未読があるのが嫌いなので絶対にLINE画面を開きますし、既読にする場合もトークを見るので必ず目に入ります。

どうしても寝る時間を意識したいので、LINEでお知らせしてもらうことにしました。
<font color="#ff0000">**健康で長生きするために睡眠を意識して生きる！**</font>大げさですかね。笑


#リベンジについて
前回投稿した記事のウェアラブル端末で:boom::fire:<font color="#ff0000">**リベンジ**</font>:fire::boom:しようとしましたが、ウェアラブル端末が破損して試すことができなくなったので、別の方法で:boom::fire:<font color="#ff0000">**リベンジ**</font>:fire::boom:することにしました。

https://qiita.com/yui-kouy/items/9f24fa1d9452d8e9c95f

#概要図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/26c82c62-fd4b-8054-7cf4-26f23921b822.png)

#使うもの
LINE Notifyはログインして、友達追加&通知してほしいグループにメンバー登録しておきます。

https://notify-bot.line.me/ja/

ログインが完了したらIFTTT側に戻ってLINE Notifyを使えるようにしていきます。
IFTTTでLINE Notifyを使う場合は最初に自分のLINEアカウントとリンクさせる必要があります。

https://ifttt.com/home

#寝るよう催促してくるよう設定
IFTTTの中にある **Date & Time** を使っています。

ここではLINEグループで <font color="#ff1493">**God(・´з`・)ちゃん**</font> に教えてもらうようにします。

>God(・´з`・)ちゃんについて
以前投稿した記事で登場して以来、気に入って使っています。
LINE Botという言葉を知らない人に「え？LINE God？」と言われたのが発端で、**LINE God**即採用しました。
そして顔文字も最近のお気に入りなので組み合わせていろんなところで使っています。

https://qiita.com/yui-kouy/items/de477fa539f83e041043

##1回目のLINE通知
だいたい22時くらいになったら寝る準備した方がいいよ。という感じです。

|IF：トリガー|TTT：実行|LINE画面：結果|
|:-:|:-:|:-:|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/c253727c-08a7-2eb9-63b3-a14120367bdc.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/5b3fec4f-f888-4e5b-2a1c-600fa9b6d642.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/55f2eb3c-6582-85e8-ef1f-4feb858f2534.png)|

##2回目のLINE通知
そろそろしっかり寝る態勢に入った方がいいので、ちょっと口調も強めです。

|IF：トリガー|TTT：実行|LINE画面：結果|
|:-:|:-:|:-:|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/f1af7b98-e385-4025-eeb0-06e7adf2f01b.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/3ab88ac5-a06a-9b2a-efce-278d2ffb01e7.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/75ab4475-f519-0440-f77a-e67260d47468.png)|


#寝る時間を意識するようになったか
使ってみて時間を気にするようになり「そろそろ寝る準備しようかな」「もうこんな時間か」と、思うようになったので<font color="#ff0000">**意識は変わった**</font>と思います。
実際に寝ようとすると寝れないことがあるのは別(精神的？&別？)に問題がありそうなので、別角度からも睡眠について考えて、しっかり寝る時間を確保して生きていきたいと思います。

#感想
ノーコードで使いやすいといえば使いやすいんですが、英語で書いてあるからいちいち翻訳しながらやることになり、結構時間がかかりました。つなげる必要もなくて、同じLINEトークに送るという指示を何個も作れば複数の処理ができるのも良いですね。
複雑なことを考えがちですが、簡単にできるものは簡単に！スピード感を意識して作っていきたいです。
人材営業職からエンジニアになってみて

#### 前職の内容
新卒で人材派遣の営業職に就き、３年半は新規開拓営業、マッチング、スタッフフォロー、委託業務管理など人材周りのクライアントサポートを一貫して行っておりました。その後は社内のオープンポジション制度を使い、IT関連のグループ会社（海外拠点）にてオフショア開発の業務進捗管理を担当していました。

#### エンジニアになろうと思ったきっかけ
営業職時代に様々なクライアントと接する機会があり、その中には多くのIT関連企業がありました。担当企業の自由な風土や時代の先端を走る姿にはいつも感化されており、一種の憧れのような気持ちを持っていました。業務経験を重ね、自らの今後のキャリアについて考えた時、今後も業界の成長が見込め、自ら手に職をつけて働けるような職種に就きたい気持ちが強くなり、その時にエンジニア職を意識したのがきっかけです。その後にグループ会社にて実際にエンジニアの方々と仕事する機会があり、彼らのように自分もサービスを作ってみたいと思う気持ちが募り、一念発起でプログラミングを本格的に学ぶことに決めました。

#### エンジニアとして働いてみた感想（前職と比べてどう変わったか）
前職とはまるで方向性が違う働き方ですが、自分の性分には向いていると感じています。営業職は基本的にはクライアントに赴き、企業担当者や担当スタッフと話すということが主な仕事であったと思います。今はフルリモート勤務ということもありますので、他のエンジニアや上司とのコミュニケーションは専らslack上で完結しており、、業務に一点集中できる環境であると思います。また営業職は基本的にはサービスを「売る」ことが仕事ですが、エンジニア職はサービスを「創る」という点において非常にやりがいを感じれる職種だと思います。業務経験が１年とまだまだ未熟ですが、ベンチャー企業ということもあり、フロントエンド・バックエンド開発関係なく、幅広く担当させて頂ける環境もWEB系企業ならではだと思います。

####今後はどんなエンジニアを目指したいか
常に探究心を持って、業務に取り組めるような、そんなエンジニアを目指していきたいと思います。まだ業務経験が浅いので、現在の技術の知見を増やしていく時期であると思っています。ただし１つの技術や言語に固執していては成長が見込めない職種ですので、同時並行的に新しい技術にキャッチアップしていく必要があります。個人的にはインフラの部分はほとんど経験を積めていないので、目先の目標としてこの分野の勉強を進めていく必要があると思っています。
Fortimail経由でのメール送信遅延

具体的にはメール送信用のサーバ（Postfix）からFortimail経由で外部にメール送信できるか検証していた時のこと

Postfixから外部にメールを10通同時に送信して問題なく送信できるか確認したところ、遅延が発生した。
10通の内5通くらいが遅延していて最終的に15分くらいで全てのメールが送信された。

Postfixのログを見ると、
refused to talk to me: 421 4.7.0 Too many concurrent connections
の文字列が

コネクションが多すぎて接続できないようなことを言ってる。
色々調べるとFortimailの設定に最大同時コネクション数の設定があるらしい
【プロファイル＞セッション】のプロファイルを開くと、「クライアント毎の最大同時コネクション数」という項目を発見。
デフォルト値の2から10に変更すると遅延が発生しなくなりました。

同じクライアントから同時にメールが来ることは想定されていないようです。
もし大量にメール送信する必要がある場合はこの設定を変更して送信元IPベースのポリシーで送信元IPを絞ってアタッチしてやればうまいことやれそうですね。
railsで作るURL(ルート)について[超基礎]

#ルータが作るURLは何者？


クライアントとサーバー間でデータ受け渡すために指定された道のり

#具体的に

```
$ rails g model Users name:string
$ rails db:migrate
```

```
$rails g controller Post index create
```
説明のために、UsersテーブルとPostコントローラを作りました

```controller/posts_controller.rb
def index
    user = User.all
end

def create 
    user = User.new
    user.save
end
```
とりあえず、Postsコントローラに簡単な処理を書きました。
超簡単に説明すると、

indexアクションでは、
UserテーブルのDBから、Userテーブルのデータをクライアントに返す処理

createアクションでは、
クライアントから受け取ったデータを、DBのUserテーブルに保存する処理
が書かれています

###ルートを作る

ようやくルートを作ります

```config/routes.rb
get '/posts', to: 'posts#index'
post '/posts', to: 'posts#create'
```
indexアクションとcreateアクションに対応したルーティングを定義してるんです。
すると、下の写真のようなルートが生成されています。

![スクリーンショット 2021-11-18 9.57.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1180539/d30d74d4-392f-f7d7-b05a-04badfcd5209.png)

GETはクライアントがサーバからデータを取得するためのHTTPメソッド
POSTはクライアントがサーバにデータを送るためのHTTPメソッド

つまり、

```
get '/posts', to: 'posts#index'
```
によってできた道のりlocalhost:3000/Postsを通って、
Postsコントトーラのindexアクションの処理により、DBのUserテーブルからデータ取得する
<br>

```
post '/posts', to: 'posts#create'
```
によってできたlocalhost:3000/Postsを通って、
Postsコントトーラのcreateアクションの処理により、DBのUserテーブルにデータを保存する。

ということになります！


#追記


```config/routes.rb
resources :posts, only: [:index, :create]
```
先程のルートはこのようにresourcesを使って省略することもできます。
ポーリングによる状態チェックを軽量化した話

# はじめに

__注・最初っからそうしとけよ、という話です。__

研修で使うようなゲームっぽいプロダクト(ゲームマスター:プレーヤー=1:n)で、双方が行った操作(データ変更)をお互いにある程度リアルタイムで検知するために、ポーリングを用いて定期的にチェックすることで実現していました。

ポーリングを用いたのは下記の理由によります。

* push型が理想だがミドルウェア構成をシンプルにしたかった
* 仕組みも簡単だし確実
* DBの問い合わせも軽そうなので負荷もそれほどではないだろう(甘かった)

# 現実に全力で殴られる

さていざ実戦投入してみると、数十クライアント程度でCPUがパンパンになって、ロードアベレージが100近くまで行きました。

DBを外に出したり、ポーリング間隔をあけたりしましたが、劇的な効果は得られませんでした。

(php-fpmがアイドリングでもなぜかCPUを食いっぱなしになるという現象もあったのでそれも一因かもしれません。これはstraceで真面目に調べようと思ったら突如再現しなくなりました。)

# 反攻に出る

これは根本的に対策せねばなるまいということで、どうするか検討しました。

ポーリングで返しているデータは、ゲームの状態を入れたjsonで、アクセスが来るたびにDBからデータを取ってきてPHPでデータを加工して返していました。

実はこのプロダクトのゲーム状態の変化はせいぜい分速ひと桁程度です。
そしてゲーム状態に変化がなければ当然jsonデータにも変化はなく、アクセスが来るたびにDBにアクセスして作る必要はありません。

ですので変化が起きるタイミングでスタティックなjsonファイルに書き出して、ポーリングはそのファイルにアクセスさせることにしました。これならポーリングのアクセスはnginxの階層のみで動くので、軽くなるはずです。

## 余談

jsonファイルのreadとwriteがバッティングするとまずそうなので、書き込み方法は下記のようにしています。
完璧ではないかも知れませんが、少なくとも同じファイルに読み書きが同時に起こることはないので概ね大丈夫ではないかと思います。

1. tmpファイルにjsonデータを書き出す
1. 現jsonファイルを別の名前にrenameする
1. tmpファイルを正規の名前にrenameする

# さらなる反攻

スタティックなファイルにしてすっきり軽くなりましたが、今度は状態に変化がなくても毎回同じものが転送されるのが無駄に感じます。

ですので更新チェックを入れて、前回のアクセスと変化がない場合は304(Not Modified)を返させてbodyの転送を節約するようにしました。

これは、前回アクセス時のレスポンスの`Etag`ヘッダの値をリクエストの`If-None-Match`ヘッダの値として付けることで実現しました。

# まとめ

* ポーリングが来た時に毎回DBにアクセスしていたら大したアクセス量じゃないのに重すぎた
* 状態が変化する頻度が低いのでファイルに書き出すことにした
* さらに更新チェックを入れて無駄なデータ転送を減らした
何故Zero TrustやMicro-segmentationのような考え方が必要なのか改めて整理してみた

多くの方が"Never trust, always verify"というキャッチフレーズを見聞きする機会が増えてきたのではと推測しています。日本語に訳すと"信頼するな、常に検査せよ"ですが一体何故この考え方が必要になってきたのでしょうか? 改めて整理してみます。

# トレンド
先ず1つ目として<font color="DarkOrange">ApplicationはCloudへシフト</font>していることが挙げられます。これはでは企業内で利用されるApplicationはある企業専用のDatacenter内に開発/配備/運用されていましたが、昨今はIaaS/PaaSのようなCloudプラットフォームに上でApplicationを開発/配備/運用されるのは当たり前になってきました。更に、既に存在しているSaaSを利用することで、Runtime〜HWまでのスタックにまつわる運用負荷をCloudサービス事業者にオフロードしながらより素早くApplicationサービスを立ち上げる方法もデファクトになってきたかたと思います。
<br>
2つ目に<font color="DarkOrange">多様性</font>があると思います。これには2つの観点があって1つめは<font color="Blue">User</font>です。企業内のApplicationを利用するのは正社員だけでなく、外部の協力会社様やパートナー様、派遣社員様や契約社員様等さまざまかと思います。もはや正社員は信用できる、それ以外の方は信用できないといった考え方は通用しなくなりました。もう1つは<font color="Blue">Device</font>です。Userが利用するDeviceは会社から貸与されたPCだけでなく個人所有のSmartPhoneやTabletを利用して企業内のApplicationにアクセスするシーンも多くなってきました。Userと同じで、会社貸与は正、個人所有は悪なんて考え方は意味を成しません。
<br>
3つ目に<font color="DarkOrange">Malware</font>があります。2020年初頭から長らく続く感染症により、多くの方がご自宅からの業務を余儀なくされているかと思います。Microsoft社のナデラCEOをはじめ、多くの著名人が2年分のデジタルシフトが2ヶ月でやってきたと言及しています。同時にMalwareの感染も急拡大してきました。いつもどこかで新しいMalwareがAttackerにより開発/配備され、常に企業の最重要資産であるDataを盗もうと企てています。攻撃手法は進化の一途を辿っているため、これらの攻撃を100%防ぐことは現実的に不可能です。何らかのMalwareに感染していることを前提に企業内のデジタル環境を設計すべきです。"With Malware"ですね。

# ギャップ
トレンドを踏まえて、従来型の境界型セキュリティとのギャップを考えてみます。1つ目は<font color="DarkOrange">Datacenter内に配備されたセキュリティ機能</font>です。これまで多くの企業がDatacenter内にVPNやFirewall等で実装されたセキュリティ機能を配備/運用してきました。しかしながら、トレンドの1つ目で触れたようにApplicationはCloudにシフトしています。Dataは企業内の専用Datacenterだけでなくインターネット上のあらゆる場所に点在しているので、それらを守るセキュリティ機能もあるゆる場所で配備/運用されるべきです。
<br>
2つ目は<font color="DarkOrange">インサイダーの脅威</font>です。トレンドの2つ目で触れたように現代は多様性の時代です。UserもDeviceも様々な属性を持っていてそれらは日々変化します。一概に正社員や会社貸与は正、協力会社や個人所有は悪とみなしていては、インサイダー脅威がリスクに昇華してしまいます。正社員も人の子ですのである日魔が差して悪事を働くかもしれません。アクセスが適正か否か常に検査すべきですね。
<br>
3つ目は<font color="DarkOrange">水平移動の脅威です。</font>境界型のセキュリティはUserがVPNの認証に成功するとネットワークレベルでアクセス権限を付与します。理論上、同一のネットワーク上に存在する全てのApplicationにアクセスできてしまいます。万が一ApplicationがRansomewareに感染してしまったら、同一ネットワーク上に存在するApplicationに水平移動されてしまいその他のApplicationも感染してしまします。必要最低限のApplicationにのみアクセスさせる、Applicationは重要度に応じて細かく区画を分けるべきです。

<br>
<br>
最後までお付き合い頂きありがとうございます。Zero TrustやMicro-segmentationのような考え方が何故誕生したのかをしっくり把握頂ければ幸いです。何年か前に公開された北野武監督の映画の"全員悪人!"のような分かりやすいキャッチフレーズの方が良いかもしれません。
fatal: remote origin already exists 新たにBitbucket上にリポジトリを作成してpushしようとしたらできなかった話。

#Railsチュートリアル３章の序盤で起きた問題

Bitbucket上にリポジトリを作成してpushしようとしたら

```
❶
$ git remote add origin git@bitbucket.org:ユーザー名/sample_app.git
fatal: remote origin already exists
```

```
❷
$ git push -u origin --all  
Please make sure you have the correct access rights
and the repository exists.
```

エラーをコピーしてないので前後にもう少し文があったような気もしますが、こんな感じのエラーが出てきました。

__入れ物作れないしpush出来ないし！__

もうホント手順通りに進めてもうまくいかないんだから困っちゃうよなあw

さてさてブツクサ言っても問題は解決しません。
❶の方に関しては、もうあるみたいなので再度やる必要はないのですが、私はなんでもやってみたいので、一旦 origin を消して入れ直しました。

___消してみる___

```
$ git remote rm origin
```
これで再度

```
$ git remote add origin git@bitbucket.org:ユーザー名/sample_app.git
```

はい解決できました。

逆に___もう一度入力してみると…___

```
$ git remote add origin git@bitbucket.org:ユーザー名/sample_app.git
fatal: remote origin already exists.
```
と言うことだったんですねえ
あるよー！！だってよ


こちらが参考にさせていただいた記事です。

https://www.cloudbees.com/blog/remote-origin-already-exists-error


❷に関しては
調べていくと、細かくは違えど、一貫して書いてあったのは、SSH 接続に問題が起こっている模様。
なので、SSHの公開鍵をもう一度作り、再度```$ git push -u origin --all ```を入力することで解決しました。


https://git-scm.com/book/ja/v2/Git%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC-SSH-%E5%85%AC%E9%96%8B%E9%8D%B5%E3%81%AE%E4%BD%9C%E6%88%90
【gRPC-Web】ネイティブアプリからgRPC-Webは使えるのか？！

## はじめに
深夜にラーメン屋に行くと100%お腹を壊すことがわかりました。ありがとうございます。(最近の出来事)

壊れる繋がりでいうとネイティブアプリからgRPC-Webを呼んでもクラッシュしないか気になりましたので、書いていこうと思います。

## gRPC-Webってjsじゃん、どうやって呼ぶの？
ご安心ください。今回使用するのはReact Nativeなのでそのまま呼べちゃいます。

## いざ検証

### Envoy Proxyを建てる
[ここ](https://qiita.com/taisei_otsuka/items/2a736fc54c3cc98c108c#envoy%E3%81%AE%E8%B5%B7%E5%8B%95)にとてもわかりやすい記事があるので参考にして下さい。

### gRPC-Webのビルドを行う
[ここ](https://qiita.com/taisei_otsuka/items/2a736fc54c3cc98c108c#grpc-web%E3%81%AE%E5%AE%9F%E8%A3%85)にわかりやすい素晴らしい記事があるので参考にして下さい。

### gRPC Serverを用意する
今回は過去にこちらで紹介した僕の彼女(Botアプリ)をServerとして使用します。
https://qiita.com/taisei_otsuka/items/87adaf5f8ed19a8549c5

### React Nativeのアプリを作る

チャットアプリ作ってみました (iPhone エミュレーター)

![qiita1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170923/b47a2039-c630-2ce1-751f-a2a83f5af960.gif)


## あれ...普通にgRPCが呼べる

と、僕もそう思ってたのですがAndroidアプリを作っていた時に事件は起きました。

**500エラーが返ってくる**

なんでだろうと調べていた時に[公式のissues](https://github.com/grpc/grpc-web/issues/383)を発見しました。

[headerにcharset=utf-8がくっついている為](https://github.com/facebook/react-native/issues/14445)とのことです。

> The issue is fixed in 0.60 with 4a80776.

[RNの0.60以降は治ってる](https://github.com/facebook/react-native/commit/4a807761a4aca9e551ff2cee8ca18a2450fb11ca)との話なのですが、自分の環境では同じエラーになりました。

## 結論

iPhoneからgRPC-Webは使える、しかしAndroidで使えない。

なので、別BFFアプリを建てる、もしくはEnvoy Proxyを建てて[gRPC-JSON transcoder](https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/grpc_json_transcoder_filter)でhttpからgRPCにリバースプロキシした方が安牌かなと思います。

## あとがき
[Instagram・Facebook・Discord・Uber Eats・Skype](https://reactnative.dev/showcase)ではReact Nativeが使われています。

今回作ったアプリも10分くらいで作れましたし、この記事を読んだきっかけでReact Nativeファンが増えたらと思ってます！


## 採用PR

大規模サイトので開発やマイクロサービス化・二次元コンテンツに興味がある、もしくはチャレンジしてみたいという方は是非一緒に働きましょう！

https://hrmos.co/pages/eisys/jobs/0000191

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307359/2000f749-3e82-7a47-b1c4-4444e237f79c.png" width=45%>
[Flutter] FCM vs Local Notification

# はじめに
FlutterでAndroidとiOSのアプリを両方開発しているところで、Push Notificationを実装することになりました。
最初はFCMとLocal Notificationの機能に関して紛らわしいことがありましたので、今回はこれに関して整理しようと思います。

# FCM (Firebase Cloud Messaging)
https://firebase.google.com/docs/cloud-messaging?hl=ja
> Firebase Cloud Messaging（FCM）は、メッセージを無料で確実に送信するためのクロスプラットフォーム メッセージング ソリューションです。

Firebaseサイトで定義されてる概念で、Firebaseサーバーを使って簡単にユーザーにメッセージを送信することができるとで理解すれば、大丈夫だと思います。

# FlutterにFCMを適用する方法

https://pub.dev/packages/firebase_messaging/install

Flutterでは、firebase_messagingのパッケージを追加して使用することができます。

注意することはiOSはAPNsキーもしくはAPNs認証書を登録を事前にしなければ、送信できないので、面倒だけどXcodeの方でAPNsの登録を含めてbundle ID設定やProvisioning Profile設定をしましょう。

あと、他のFirebaseパッケージ、例えば、firebase_authやfirebase_coreなどを使うことになったら、バージョンの互換性も考えないとビルドエラーが起こる可能性もあるので気をつけた方がいいです。

# FlutterのLocal Notification
https://pub.dev/packages/flutter_local_notifications

> A cross platform plugin for displaying and scheduling local notifications for Flutter applications with the ability to customise for each platform.

これもFCMみたいにメッセージを送信するためのクロスプラットフォームです。

# FlutterにLocal Notificationを適用する方法
Local Notificationもfirebase_messagingようにflutter_local_notificationsのパッケージを追加すれば使用することができます。

# FCMとLocal Notificationの共通点
- 両方Android,iOSにメッセージを無料で送信することができる
- メッセージの予約可能
- Notification許可ダイアログを出すことができる
(これ以上何かあったら、Feedbackしてください😭）


# FCMとLocal Notificationの相違点
- FCMはiOSの方の追加的な対応が必要(bundle ID, Provisioning Profile, APNsキー, tokenなど)
- FCMはメッセージの中に画像を表示したいなら、Flutter上にObjective-Cで対応しなければならない。<br/>

https://firebase.flutter.dev/docs/messaging/apple-integration/#advanced-optional-allowing-notification-images

- FCMはfirebaseを**データベース**として使用している場合は、クラウド機能を使用してデータベースに加えられた変更をlistenすることができる。
- :pushpin:用語の違い：機能がほぼ同じでFCMとLocal Notificationを話すとき、プッシュ通知もしくはPush Notificationと言われるですが、これは正しくないです。

**Local Notification**はデバイス上にローカルにアプリ自体から送信、予約されたNotificationです。
**Push Notification**はiOSやAndroidのクラウドシステム(APNs,FCMなど)を通じてアプリに送信されたNotificationです。

# まとめ
つまり、用語的にFCMはPush Notification, ローカルで送信する通知はLocal Notificationです。FCMはユーザーのデータベースをもとにAPNsとトークンを通してメッセージを送信、Local Notificationはこれに関係なくてメッセージを送信することができます。もちろん、Push Notificationの方がLocal Notificationより細かい設定や実装が必要です。実装したいことによって、ちゃんと検討して実装した方がいいと思いますね。

## 参考
https://www.quora.com/What-is-the-difference-between-a-local-notification-and-a-push-notification

https://stackoverflow.com/questions/61739288/local-notifications-vs-fcm-which-is-right

#### いつもFeedback歓迎
Feedbackはコメントでお願いします。
では、Happy coding!👋🏻
webpackの使い方

# webpackとは
***webpack***とは、複数のJavaScriptのモジュールをまとめる（***バンドル***）ことのできる***モジュールバンドラ***のこと。これを利用することで、ファイルを分割した開発や依存関係を気にすることなく開発できるなどのメリットがある。

# webpackの使い方
###webpackのインストール
webpackは、Node.jsのパッケージマネージャーである```npm```を使ってインストールすることができる。

```webpackのインストール
$ npm install --save-dev webpack webpack-cli
```
ここで、webpackを使用するためにはwebpackのコマンドラインインターフェースである```webpack-cli```も一緒にインストールしておく。

###webpack.config.jsファイルの作成
webpackを使用するにあたって、```webpack.config.js```ファイルを作成することで、エントリポイントのファイル名や出力ファイル名などを設定することができる。
エントリーポイントと出力ファイル名、フォルダを指定する場合は、以下のように書ける。

```javascript
const path = require("path");

module.exports = {
	// エントリーポイント
	entry: `./src/index.js`,

	// ファイルの出力設定
	output: {
		// バンドルされた出力ファイル名
		filename: "bundle.js",
		//  出力先ディレクトリ名とパス
		path: path.join(__dirname, "dist"),
	},
};
```

ここで、```webpack.config.js```を設定しない場合は以下のデフォルト値が設定されている。
■ entry: ```./src/index.js```
■ output: ```./dist/main.js```

###webpackの実行
webpackは、次のコマンドで実行できる。

```
$ npx webpack
```
なぜ！？テスト範囲を考慮しないのか？

#◆ご挨拶
こんにちは！QA Kooです。
ご覧くださりありがとうございます。
はじめましての方も、いつも見てくださる方もよかったら最後まで見てください。

今回のテーマはなぜテスト範囲を考慮しないのか？について書きたいと思います。
皆さんもテスト範囲として考慮されずに本番環境で障害となるケースはありませんか？

実際私の担当しているタイトルでもテスト範囲が考慮されてなく、障害が発生してしまうことは多々あります。
そんなときテスト設計者に原因を尋ねると、「**仕様書に書いてないので考慮してない**」という回答をもらうことが多々ありました。

今回はそういったテスト設計者の意識やなぜ考慮できなかったのかを分析しお伝えできたらと思っています。

#◆考慮漏れする設計者の意識
下図のようにマインドマップを使って、テスト範囲の考慮が漏れる要因を分析しました。
![テスト範囲が検討できてない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325577/63079423-430c-dfab-0e4a-31495103bea5.png)



分析すると大きく分けて4つの要素になりました。

* 業務範囲外の認識　　　　→　教育不足
* 範囲を洗い出す技術不足　→　教育不足
* 仕様を理解していない　　→　教育不足
* 工数不足　　　　　　　　→　見積もりミス

上記のように、人材の教育が不足していることが主な要因と考えられます。
特に自身の業務範囲外と認識してしまっているケースが私の担当では多く、設計時にテスト範囲を考慮してないことが多く見受けられました。

そのため「**仕様書に書いてないので考慮してない**」という回答が行われるわけです。

#◆改善例
分析結果から教育が必要であることは見えていますが、その教育について具体的な例を一部お伝えします。

* 注意喚起
    * テスト設計にはテスト範囲を考慮する必要があることを認識
* テスト設計フローに追加
    * テスト設計時にテスト範囲を検討するフローを組み込み
* テスト範囲の洗い出し
    * 洗い出し方法はマインドマップを使ったものなど自身にあったものを使用
* テスト範囲のすり合わせ
    * 開発と洗い出したテスト範囲をすり合わせ

このように作業者に認識してもらうのと関係者で範囲の妥当性を確認するのが重要になります。

#◆最後に
テスト範囲についてはテスト設計者自身の能力に依存するため、教育によりテスト設計の業務範囲であることを認識してもらうことと、テスト範囲を洗い出したら、その範囲は正しいか複数人から意見をもらうことで漏れを軽減できると思います。

まだテスト範囲を激的に減らせるまでは至っていませんが、こういった取り組みがどこかで少しでも役に立てたらと思っています。
もし、障害発生時に状況確認をおこなったさい、テスト設計者から**仕様書に書いてないので考慮してない**と言われたら、ぜひ活用してみてください。
TargetSDK 30対応中にハマったこと

# はじめに
CYBIRDエンジニア Advent Calendar 4日目担当の@chikako_ikedaです。
３日目は@kyorokyoroの[アプリの通信回数を減らすためにやったこと](https://qiita.com/kyorokyoro/private/3d357661613a6cb89d3e)でした。
最近は速い通信規格が出てきてあまり気にならないこともありますが、アプリの通信回数はアプリの操作感が変わるので、「回数を減らす」というのは大事ですよね。


# 概要
2021/11/01からGoogle PlayではTargetSDKをAPI Level 30(Android11)へ対応することが必須となりました。
CYBIRDのアプリでも順次対応を進めているところですが、こんなところでハマったよ、ということで、
APKの署名スキーマv2への対応について紹介しようかと思います。
※以下、「TargetSDKをAPI Level 30(Android11)へ対応」は「TargetSDK30対応」と記載します。

# 目次

1. 発端：出来上がったAPKがインストールできない
2. 調査：とりあえず、エラー内容を確認しよう
3. 原因：TargetSDK30から署名スキーマv2への対応が必須に
3. 解決：署名スキーマv2の署名を追加しよう

# APKの署名スキーマv2への対応
## 発端：出来上がったAPKがインストールできない
当社のアプリは全てではないですが、Jenkinsを使ってビルドの自動化を行なっています。
各開発者の環境に左右されず、ビルド後に必要な処理を自動でやることが可能になります。
(例：テスト用バイナリを特定のサーバにバックアップする、とか）

コードを修正して、Jenkinsでのビルドが成功したのち、実機で確認すべくインストールをしようとしました。
ところが、「このアプリはインストールできません」とだけ表示を出し、インストールに失敗しました。
ビルドログを見ても、「Success」と出ている。
色々バージョンを別に確認をしたところ、TargetSDK30対応分のコードでだけ発生していました。

## 調査：とりあえず、エラー内容を確認しよう
古のアンドロイダーである自覚のある私は、こういう時に真っ先にケーブルを繋ぎADBコマンドを叩きます。
※ADBはAndroidの開発ツールです。
　端末の中に入ったり、アプリ内DBの中身を引っこ抜いたりするのに使います。

```
// -r オプションをつけると上書きインストールになります
adb install -r ${APKのパス}
adb: failed to open ${APKのパス}: Operation not permitted
```

許可がない。しかも、「署名が違うから入れられない」というありがちなエラーではない。
署名をしたけれど不正で、どうやら端末には入れられない、とのこと。
この現象に気づいたのが間の悪いことに、テスト開始前夜。
当社のテストは原則として、製品版相当の状態で確認を行うため、テスト担当の方に慌てて一時的にデバッグ版での確認をお願いすることとなりました…

## 原因：TargetSDK30から署名スキーマv2への対応が必須に
ところで、TargetSDK30対応を始める前に事前調査を行っていました。2021年の3月くらいに。
その中に、「署名スキーマv2が必須になる」という記載があったことを思い出しました。
[APK署名スキームv2が必要(下位互換でv1も必要)](https://developer.android.com/about/versions/11/behavior-changes-11?hl=ja#minimum-signature-scheme)

ちなみに、署名スキーマv2って何？　という話なのですが、ものすごく大雑把に言うと、
**いままでのアプリに付与していた開発者(あるいは配信者)の本人確認にプラスした情報が必要になるよ**ということです。
詳細は[こちら](https://source.android.com/security/apksigning/v2?hl=ja)。
この署名スキーマv2は、API Level 24(Android 7.0)から対応していたそうです。

ただし、この問題が起きるのは**AndroidStudioでAPKを作っていない場合**です。
AndroidStudioを使っている場合は、minSdkVersionを見て、自動でこの署名の切り替えをしてくれているそうです。
だからbuild Valiantをreleaseにして実行していた時は、普通に実機で動いたのか…

## 解決：署名スキーマv2の署名を追加しよう
既存のJenkinsのジョブ設定にあるビルドと署名では実機インストールができないので、
対応しなくてはいけません。
ただ、幸運なことにいままで使っていたkeystore (署名のためのファイル)はそのまま使えます。

ちなみに、問題が起きたアプリの下限OSはAPI Level 23(Android 6.0)なので、署名スキーマv1の署名も必要です。
なので、方針としては以下の通りになります。

1. いままで通りのビルド＋署名を行う
2. 署名スキーマv2を追加して署名する

Jenkinsのビルドシェルに、以下のコマンドを追加しました。

```
./apksigner sign -ks ${keystoreのパス} --ks-key-alias ${アプリのエイリアス} --v1-signing-enabled=true --v2-signing-enabled=true ${APKのパス}
```

でも、こんなコマンド1つで本当に、署名できてるの？　と不安になるかと思います。
なので、検証もしてみましょう。

```
apksigner verify --print-certs -v [署名済みのAPKファイル]
```

このコマンドを叩くと、以下のような形で検証結果が出てきます。
v1スキーマとv2スキーマ両方がtrueになっていれば、対応成功です。

```
Verifies
Verified using v1 scheme (JAR signing): true
Verified using v2 scheme (APK Signature Scheme v2): true 
※以下略
```
なお、この署名方法はTargetSDK30対応をしていなくても、特に問題なくインストールできることも確認しました。

## さいごに
実装とか設定にばかり目が行きがちになりますが、ツールへの対応も忘れちゃいけませんね。。。

明日のCYBIRDエンジニア Advent Calendar 2021 5日目は、 @kappysan が担当します。
ありがとうございました。
PostgreSqlにてencode関数を利用したいのに、encode(text, unknown) does not exist とかになっちゃう件


下記テーブルを例にして記載します。

```
create table sampletable (
    name  text,
    birthday date
);
```


下記に様にすると取れそうですがエラーが発生します。

```
SELECT name, birthday, 
ENCODE( CONCAT( '{"name":"', name, '","birthday":"', CAST(birthday AS varchar), '"}'), 'base64') AS jsondata
FROM sampletable;
// 下記エラーが発生する
function encode(text, unknown) does not exist
```



バイナリ型に変換する必要があり、「::bytea」を付ける必要があります。

```
SELECT name, birthday, 
ENCODE( CONCAT( '{"name":"', name, '","birthday":"', CAST(birthday AS varchar), '"}')::bytea , 'base64') AS jsondata
FROM sampletable;
```

これで勝つる！

参考にしたサイト
・[PostgreSQLのテキスト型にBASE64文字列を入れて使うなら便利なこと | Exfield](https://exfield.jp/View/pid:5699/)
CompTIA Security+ SY0-501を受験した話

初めまして。Sky・Secureのキティちゃんと言います。Sky・Secureとは神奈川県警のもとで、セキュリティのボランティア活動をしている団体となります。是非名前だけでも憶えていっていただければと思います。
今回が初投稿で至らぬところもございますが、これから徐々にQiitaの書き方に慣れていければと思います。
それじゃ、さっそく本題に入ろうと思います。
#CompTIA Security+とは
CompTIA Security+とはCompTIAというIT資格の認定を行う団体のセキュリティの内容に特化した資格です。また、Security+はセキュリティエンジニアとしての登竜門となる資格でもあるそうです。

#受験した経緯
セキュリティエンジニアとして、社会人3年目を迎えたのですが、そろそろセキュリティ関連の資格が取りたいと思っていた時期に偶然ネットでCompTIA Security+を見つけました。
難易度も高くなく、セキュリティエンジニアとしての登竜門とのことで、腕試しに受けてみようと思いました。

#勉強方法
勉強方法は以下の4点をひたすらやりました。

- TACが提供しているWeb模試を解く
- Web模試で出てきた用語の確認
- ウェルノンポートの確認
- SY0-601（現在移行中のバージョン）のサンプル問題を解く

合格体験談の記事を探していると、TACが提供しているWeb模試からほとんど出題されている、Web模試のみで合格をしたというものがありました。これを見たら買わないわけがないですね。ただ、心配性な私は、他にも合格体験談の記事を読み漁っていたのですが、ポートを埋める問題が出題されたという記事やWeb模試で出題された用語は復習した方がよいという記事を見つけました。合格者がいうならばやった方がいいと思いました。
また、噂レベルですが、バージョンがSY0-601に移行していることから、SY0-601の問題が出題されるのじゃないかという話を聞き、SY0-601のサンプル問題も漁ったりしました。
*なぜSY0-501を受験したかというと、最新バージョンは教材や情報量が少なかったためです。
*バージョンの違いとしては、試験範囲が異なるところです。詳細はCompTIA Security+で確認してみてください。

#受験当日
Web模試、サンプル問題は満点、ポート番号の穴埋めもでき、模試内の用語も8割は理解した状態で試験に臨みました。大体1週間程度勉強しました。

予約はピアソンVUEから会場、日時を指定します。あとは当日会場に向かうだけです。注意点として、当日身分証を見せる必要がありますので、必要なものをHPで確認しておきましょう。

#受験結果
750点が合格ラインであり、私の得点は758点とかなりギリギリなラインでしたが、合格することはできました。恐らく数問間違えると落ちていたと思われます。
CompTIAの資格はどれも80パーセント以上の正答率が求められますので、気は抜けません。

#受験した感想
Web模試だけで受かると思い込んでいたせいもあり、当日はかなり焦ったのですが、模試からは2~3割程度の出題で、7~8割は初見の問題でした。ただ、元々自分が知っている範囲の問題が出題されたり、問題文を読めば回答が推測できるようなものが多かったので、なんとかなりました。苦手な範囲が出題されたら、落ちていたと思います。過信はいけないですね。かといって、Web模試がなければ解けないような問題もありました。特にパフォーマンスベースドテストという問題はそのまんまの内容でしたので、助かりました。

#最後に
・今回はCompTIA Security+の受験について書きました。今後受験を考えている人のお役に立てれば幸いです。（拙い文章で申し訳ありません。色々記事を書いて慣れていこうと思います）

・次はCompTIA PenTest+もしくはCompTIA CySA+の受験を考えていますが、受験をしたら、また記事を書ければと思います。

#参考文献
・https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%97%E3%83%86%E3%82%A3%E3%82%A2
[EssentialX]プレイヤーが使用できるコマンドの編集

# はじめに
この記事では、Bukkitプラグインの`EssentialsX`の諸設定について書き下しています。
雑記のようなものになりますが、修正リクエストなどは遠慮なく送っていだだけると幸いです

## 実行環境
以下の環境でテストしています。
> OS: Windows 10
src: Paper 1.17.1 #388(記事執筆時点で最新の安定版)

サーバーのセットアップなどの手順は省略します。
今回は「`EssentialsX`を導入してから起動した後」の状態からの説明となります

## 設定ファイルの位置
`EssentialsX`に限ったことではないですが、プラグインの設定ファイルはすべて`plugins/<プラグインの名前>`内に置かれます（これを**データフォルダ**と呼びます）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175091/67f2946f-b4d6-7179-bfe9-1eef43d0a71a.png)

中にはおおよそ`.yml`という拡張子のファイルが入っていると思いますが、これがいわゆる**設定ファイル**です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175091/95d4f07a-46e9-ba5c-f47a-d2ace33bd4b8.png)

プログラム内部の値をいじったりするとき、プラグイン自体の値を都度変更するのは手間になります。
そのため、設定ファイルは利用者が手軽に設定値を変更できるように用いられます

## 使用できるコマンドの追加
試しに`/tp`を一般プレイヤー（OPを持たないプレイヤー）も使えるようにしてみましょう

一般プレイヤーが使えるコマンドの一覧は、`config.yml`内の`player-commands`というリストの中にあります（記事執筆時点では224行目）

```yaml
player-commands:
  - afk
  - afk.auto
  - back
  ...
```

このリストの中に`tp`を追記すればOKです

```yaml
player-commands:
  - tp
  - afk
  - afk.auto
  - back
  ...
```

## Bukkit標準のPermissionをオフにする
これで完成...のように見えますが、デフォルトではこのリストは使われず、**Bukkitが設定したコマンドリスト**が使われています。
特に何も設定せずとも一般プレイヤーが`/ban`などを使用できないのはこのためです

標準のコマンドリストを使うかどうかの設定は、`player-commands`のちょうど下にある`use-bukkit-permissions`で設定ができます

```yaml
use-bukkit-permission: true
```

デフォルトが`true`なので、これを`false`にしておきましょう

```yaml
use-bukkit-permission: false
```

## 確認
実際にサーバーに入って、`/tp`が使えるか確認しましょう。
自身がOPを持っている場合は確認できないので、適宜`/deop`などしておきましょう
![2021-11-25_15.48.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2175091/b0b772ec-58b9-a80e-92c4-ffd1c7e7dee8.png)
しっかり使用可能になっていますね
これで完了です！お疲れさまでした。
【javascript】Map, Set

# Map, Set
* データを管理するための入れ物。
* コレクションともいう
* ES6から採用された

## ObjectとMapの違い

|  | Object | Map |
|:-----------|------------:|:------------:|
| key       | 文字列        | 制約なし（数値、関数、オブジェクトなど）         |
|  for..in    | ○      | ×       |
|  for..of    | ×      | ○       |

* mapはEntriesという格納場所がありそこでデータを管理している。
![スクリーンショット 2021-11-25 15.24.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/97b45c66-b0ac-e07f-3975-f98b7f53668d.png)


```js
const map = new Map();

//オブジェクトをkeyに設定できる。
const key = {}
map.set(key, 'value');
console.log(map.get(key));

>>> value

//関数をkeyに設定できる。
const key2 = function(){};
map.set(key2, 'value2');
console.log(map.get(key2));

>>> value2

// 数値もkeyに設定できる。
const key3 = 3;
map.set(key3, 'value3');
console.log(map.get(key3));

>>> value3

//値の削除
map.delete(key3)
console.log(map.get(key3))

>>> undefined


//for..ofの確認
for(const [k, v] of map){
    console.log(k, v)
}

>>> {}:'value'
>>> ():'value2'
```

## ArrayとSetの違い

|  | Array | Set |
|:-----------|------------:|:------------:|
| 重複値       | ○        | ×        |
|  for..in    | ○      | ×       |
|  for..of    | ○      | ○       |
|  添字[]    | ○      | ×       |


```js

const key = {}
const key2 = function(){};

const s = new Set()

//値の重複ができないことの確認
s.add(key); //同じ値をsに追加している。
s.add(key);

//for...ofで確認
for(const k of s){
    console.log(k)
}

>>> {} //一つしか出力されなかった。

//値の削除
s.delete(key2)
console.log(s.key2)
>>> undefined


//値の存在確認（mapでも使える。）
console.log(s.has(key2))
>>> false

//添字を使えるようにsetをarrayに変換
const arry = Array.from(s)
// arry = [...s]スプレッド構文でも良い。
console.log(arry[0]) 
```
VMworld 2021 Japan セッションまとめ (VMware Cloud on AWS編)

VMworld 2021 **Japan** に参加したのでVMware Cloud on AWS 関連のセッションまとめます.。2021/11/25-26でライブ配信されていて、2021年末までオンデマンド視聴/資料ダウンロードも可能です。

https://vmworld.jp/

#1. そもそもVMworldって？

> VMware社の年次カンファレンスです。他にもいろんな会社(例えばApple社)も自社の大型イベントで新製品や新機能の発表しているかと思います。今年USでは10/5-7にオンラインで開催されました。日本でも同イベント(VMworld 2021 Japan)は11/25-26でライブ配信されます。(再掲)

そのほかは過去記事もご参照ください。

https://qiita.com/sanjushi/items/9805631d3cc3c1f47e58


#2. VMworld 2021 Japan セッションの見どころ（VMware Cloud on AWS 関連）

AWSもスポンサーということで、いくつもVMware Cloud on AWS関連のセッションを公開しています。日本のお客様事例や調査会社のレポートも閲覧・ダウンロード可能となっていて参考になります。

https://vmworld.jp/demozone/expo/26/

VMwareでVMware Cloud on AWSを担当されている方がブログでもお勧めセッションをピックアップされています。

https://blogs.vmware.com/vmware-japan/2021/10/vmworld-recommended-vmc.html

#3. 関連記事

https://qiita.com/sanjushi/items/9805631d3cc3c1f47e58

https://qiita.com/sanjushi003/items/2696271334893b12a494

https://qiita.com/sanjushi003/items/175aad0ccdbb3488bfda
wsadminで設定し、設定できたことを確認する(JDBCProvider編)　パターン2

https://qiita.com/XKYUXSOX/items/a270c28c04fafabfdac0
パターン１との違いは
classpathの部分とnativepathの部分を選択できるようにしている点。
※たいていはデフォルトで作成するだけなので、パターン１で十分だと思う。



```jvminfo.txt
yyd1Node01,server1
yyd1Node01,server2
yyd2Node01,server1
```
```yyd1Node01_server1.jdbc
"DB2","DB2 Using IBM JCC Driver","XA data source","DB2 Using IBM JCC DriverXA","${DB2_JCC_DRIVER_PATH}/db2jcc4.jar ${UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc_license_cu.jar ${DB2_JCC_DRIVER_PATH}/db2jcc_license_cisuz.jar ${PUREQUERY_PATH}/pdq.jar ${PUREQUERY_PATH}/pdqmgmt.jar",${DB2_JCC_DRIVER_NATIVEPATH}
"DB2","DB2 Using IBM JCC Driver","Connection pool data source","DB2 Using IBM JCC DriverONE","${DB2_JCC_DRIVER_PATH}/db2jcc4.jar ${UNIVERSAL_JDBC_DRIVER_PATH}/db2jcc_license_cu.jar ${DB2_JCC_DRIVER_PATH}/db2jcc_license_cisuz.jar ${PUREQUERY_PATH}/pdq.jar ${PUREQUERY_PATH}/pdqmgmt.jar",${DB2_JCC_DRIVER_NATIVEPATH}
```

```JDBC_set.py
import csv

with open('jvminfo.txt') as f:
    csvreader = csv.reader(f)
    for row in csvreader:
      nodename=row[0]
      servername=row[1]
      id=AdminConfig.getid('/Node:'+nodename+'/Server:'+servername+'/')

      with open(nodename+'_'+servername+'.jdbc') as f2:
          csvreader2 = csv.reader(f2)
          for row2 in csvreader2:
           J_dtype=row2[0]
           J_ptype=row2[1]
           J_itype=row2[2]
           J_name=row2[3]
           J_clspath=row2[4]
           J_ntvpath=row2[5]

           AdminTask.createJDBCProvider('[-scope Node='+nodename+',Server='+servername+' -databaseType "'+J_dtype+'" -providerType "'+J_ptype+'" -implementationType "'+J_itype+'" -name "'+J_name+'" -classpath "'+J_clspath+'" -nativePath '+J_ntvpath+' ]')

AdminConfig.save()
```

毎度の設定確認

```JDBC_get.py
import csv

with open('jvminfo.txt') as f:
    csvreader = csv.reader(f)
    for row in csvreader:
      nodename=row[0]
      servername=row[1]
      id=AdminConfig.getid('/Node:'+nodename+'/Server:'+servername+'/')

      with open(nodename+'_'+servername+'.jdbc') as f2:
          csvreader2 = csv.reader(f2)
          for row2 in csvreader2:
           J_name=row2[3]
           ProcessID = AdminConfig.list('JDBCProvider',id)
           JDBCList=AdminUtilities.convertToList(ProcessID)
           for jpv in JDBCList:
             if AdminConfig.showAttribute(jpv,'name') == J_name:
               print nodename + servername
               print AdminConfig.showAttribute(jpv,'name')
               print AdminConfig.showAttribute(jpv,'xa')

````
【javascript】for...ofの反復可能性

# for...of
イテレーターを持つオブジェクトの反復操作を行う。
※イテレーター：反復操作を行う際に使用するオブジェクト

* 反復可能オブジェクト
 * String
 * Array
 * map
 * set
 * arguments
 * etc...

## case1
* for...ofの実行時はprototypeのSymbol(Symbol.iterator)が使われることになる。

```js
const arry = ['a', 'b', 'c'];

for(let v of arry){
    console.log(v)
}

>>> a
>>> d
>>> c
```

![スクリーンショット 2021-11-25 14.35.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/fdd37a03-40ee-b077-b78c-b41d054918f2.png)

## case2

* 空の配列を用意するとundefinedが戻る。
* for...ofはイテレータープロパティを用いるのでprototyepでメソッドを追加しても、戻り値には含まれない。

```js

const arry = ['a', 'b', 'c'];

arry[4] = 'e'

for(let v of arry){
    console.log(v)
}

//イテレータープロパティを用いるのでprototyepでメソッドを追加しても、戻り値には含まれない。
Object.prototype.method = function(){}

//イテレーターを使用しているのでenumerableがfalseでも配列0番目の"a"も戻り値になる。   
Object.defineProperty(arry, 0, {
    enumerable: false
})

const b = Object.getOwnPropertyDescriptor(arry, 0);
console.log(b)

>>> {value: 'a', writable: true, enumerable: false, configurable: true}

//配列は0が出発点となるので、3はundifinedとなる。
>>> a [0]
>>> b [1]
>>> c [2]
>>> undefined [3]
>>> e [4]
```
Ubuntu 20.04にminikube使って簡単にKubernetesでJupyter notebook（scipy-notebook）環境をつくる方法

まずscipy-notebookをデプロイする（ここは各自好きなnotebookを選択してください）

```
$ kubectl create deploy jupyter --image=jupyter/scipy-notebook
```
jupyter notebookにアクセスするためのサービスを作成

```
$ kubectl expose deployment jupyter --type=NodePort --name=jupyter-svc --port=8888
```
Webブラウザでアクセスするためのポートを確認

```
$ kubectl describe service jupyter-svc
Name:                     jupyter-svc
Namespace:                default
Labels:                   app=jupyter
Annotations:              <none>
Selector:                 app=jupyter
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.107.207.241
IPs:                      10.107.207.241
Port:                     <unset>  8888/TCP
TargetPort:               8888/TCP
NodePort:                 <unset>  32517/TCP　<<<これがアクセスに必要なポート番号
Endpoints:                172.17.0.4:8888
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
```
Minikubeが公開しているIPアドレスを確認

```
$ minikube ip
192.168.49.2
```

Webブラウザを立ち上げてminikube ipにNoderPort番号でアクセス
（今回の例だと192.168.49.2:32517にアクセス）

Tokenを確認するページが表示される
![jupyter-notebook-k8s_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120864/aef5d70e-b7ea-24e0-c17a-88ce429166de.png)

Podに入ってTokenを取ってくるためにPod名を確認

```
$ kubectl get pods
NAME                       READY   STATUS    RESTARTS   AGE
jupyter-574c7f77f9-4mn7g   1/1     Running   0          3m14s
```
PODにアクセス

```
$ kubectl exec --stdin --tty jupyter-574c7f77f9-4mn7g -- /bin/bash
($ kubectl exec -it jupyter-574c7f77f9-4mn7g /bin/bash　でも可）
```
POD内でjupyter notebook listを実行してTokenを表示

```
jovyan@jupyter-574c7f77f9-4mn7g:~$ jupyter notebook list
Currently running servers:
http://0.0.0.0:8888/?token=c5eaeca9d111835a0859a8089766f6bf47b72e61beedc9b8 :: /home/jovyan
```

表示されたTokenをWebブラウザから入力するとjupyter notebookが利用できるようになります。
wsadminで設定し、設定できたことを確認する(JDBCProvider編)　パターン１


JDBCProviderの作成スクリプトと設定確認スクリプト


```jvminfo.txt
yyd1Node01,server1
yyd1Node01,server2
yyd2Node01,server1
```
Db2版で作成
上がXA版のJDBCプロバイダ
下がONEフェーズコミット版のJDBCプロバイダ

```yyd1Node01_server1.jdbc
"DB2","DB2 Using IBM JCC Driver","XA data source","DB2 Using IBM JCC DriverXA"
"DB2","DB2 Using IBM JCC Driver","Connection pool data source","DB2 Using IBM JCC DriverONE"
```

```JDBC_set.py
import csv

with open('jvminfo.txt') as f:
    csvreader = csv.reader(f)
    for row in csvreader:
      nodename=row[0]
      servername=row[1]
      id=AdminConfig.getid('/Node:'+nodename+'/Server:'+servername+'/')

      with open(nodename+'_'+servername+'.jdbc') as f2:
          csvreader2 = csv.reader(f2)
          for row2 in csvreader2:
           J_dtype=row2[0]
           J_ptype=row2[1]
           J_itype=row2[2]
           J_name=row2[3]

           AdminTask.createJDBCProvider('[-scope Node='+nodename+',Server='+servername+' -databaseType "'+J_dtype+'" -providerType "'+J_ptype+'" -implementationType "'+J_itype+'" -name "'+J_name+'"]')

AdminConfig.save()
```

毎度の設定確認

```JDBC_get.py
import csv

with open('jvminfo.txt') as f:
    csvreader = csv.reader(f)
    for row in csvreader:
      nodename=row[0]
      servername=row[1]
      id=AdminConfig.getid('/Node:'+nodename+'/Server:'+servername+'/')

      with open(nodename+'_'+servername+'.jdbc') as f2:
          csvreader2 = csv.reader(f2)
          for row2 in csvreader2:
           J_name=row2[3]
           ProcessID = AdminConfig.list('JDBCProvider',id)
           JDBCList=AdminUtilities.convertToList(ProcessID)
           for jpv in JDBCList:
             if AdminConfig.showAttribute(jpv,'name') == J_name:
               print nodename + servername
               print AdminConfig.showAttribute(jpv,'name')
               print AdminConfig.showAttribute(jpv,'xa')

````
新卒エンジニア面接で頻繁に聞かれた質問４選【就活】

#はじめに

こんにちは、坂内太一と申します。
今回は前回の記事で予告したように新卒のエンジニア面接で頻繁に聞かれた質問についてまとめました。
またそれぞれの質問に対しての僕自身の回答や思ったことも述べてあります。
拙い文章が多々あるかと思いますが最後まで読んでいただけたら嬉しいです。

#僕が面接を受けた企業の概要

まずは本題に入る前に僕がどのような会社の面接を受けたかについて話したいと思います。
僕が実際に面接を受けた回数は約30回ほどで地方在住である点と新型コロナウイルスの蔓延(コロナが一番酷かった時期)によって全ての面接をオンラインで受けました。
僕が面接を受けた会社は受託開発を中心に行っている企業を主としており、規模に関しては社員20人ほどのベンチャー企業から一部上場の大規模企業まで様々な企業の面接を受けました。
以上が僕が面接を受けた企業の概要になります。
また補足になりますが僕は地方の文系大学に通っており、プログラミングの学習やポートフォリオの作成は全て独学で行っております。
これらのことを踏まえて読んでいただければ幸いです。

#面接で頻繁に聞かれた質問４選

ここでは実際の面接で頻繁に聞かれた4つの質問を挙げていきます。

###1.なぜエンジニアになろうと思ったのか

1つ目のこの質問はどこの面接でも必ずと言っていいほど聞かれました。
先にも述べたように僕がITとは全く関係ない大学に通っていたことからなぜエンジニアになろうと思ったのかを聞きたかったのだと思います。

###2.あなたの長所を教えてください

この質問は就活では鉄板の質問ですので必ずと言っていいほど聞かれます。
自分の良さを相手にわかりやすいように話すようにしましょう。
また僕はこれに加えて話の内容がエンジニアで働くにあたってどう活かされるのかを意識して話をしました。



###3.あなたはどんなエンジニアになりたいですか

この質問は文字通りどのようなエンジニアになりたいかというものです。
実際の僕の回答としましては

>幅広いユーザーが不自由することなく快適にサービスを利用できるように細かいとこまで気遣いのあるエンジニアになりたいです。

です。
この質問に答えはありませんので皆さんが目指しているエンジニア像を話してみてください。


###4.エンジニアとしてどのようなキャリアを考えていますか

先の質問と少し似ていますがこの質問はこの先エンジニアとして働いていく上でどのようなキャリアを考えているかというものです。
僕の実際の回答は

>僕はプロジェクトマネージャーになりたいと思っています。なぜならユーザーに対して細かな気遣いのあるサービスを開発するにはサービスの全体像を把握してプロジェクトを進めていく必要があるからです。

です。
この質問の回答は３番の質問の『あなたはどんなエンジニアになりたいですか』とつながる点が少なからずあると思いますのでそれらを踏まえて回答をすると良いでしょう。


#まとめ

以上が僕が面接で頻繁に聞かれた質問になります。
今回のこの記事のほかに僕が面接で意識したポイントをまとめた記事もありますので是非そちらも合わせてご覧ください。
最後まで読んでいただきありがとうございました。
react-router-dom v6でstorybookを使用するときの注意

# エラーソース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/3077c2af-53a1-5efe-d83a-20f076320e22.png)

Material UI(MUI)を使用

``` HeaderLink/index.tsx
import Link from "@mui/material/Link";
import { Link as RouterLink } from "react-router-dom";

type HeaderLinkProps = {
  href: string;
  title: string;
  onClickLink?: () => void;
};

const HeaderLink: React.VFC<HeaderLinkProps> = ({
  title,
  href,
  onClickLink,
}) => {
  return (
    <Link
      component={RouterLink}
      to={href}
      onClick={() => {
        onClickLink?.();
      }}
      sx={{
        color: "#9d9d9d",
        position: "relative",
        textDecoration: "none",
        "::after": {
          position: "absolute",
          left: 0,
          content: '""',
          width: "100%",
          height: "2px",
          background: "#9d9d9d",
          bottom: "-1px",
          transform: "scale(0, 1)",
          transformOrigin: "center top",
          transition: "transform 0.3s",
        },
        ":hover": {
          "::after": {
            transform: "scale(1, 1)",
          },
        },
      }}
    >
      {title}
    </Link>
  );
};

export default HeaderLink;
``` 



``` HeaderLink/index.stories.tsx
import React from "react";
import { ComponentStory, ComponentMeta } from "@storybook/react";

import HeaderLink from ".";

// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
  title: "Atoms/HeaderLink",
  component: HeaderLink,
} as ComponentMeta<typeof HeaderLink>;

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof HeaderLink> = (args) => (
  <HeaderLink {...args} />
);

export const Normal = Template.bind({});
Normal.args = {
  title: "テストリンク",
  href: "#",
};
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/4001b0e8-b4e8-3d1d-e937-14ce3d893244.png)



# 修正後
``` HeaderLink/index.stories.tsx
import React from "react";
import { ComponentStory, ComponentMeta } from "@storybook/react";

import HeaderLink from ".";
import { MemoryRouter } from "react-router-dom";

// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
  title: "Atoms/HeaderLink",
  component: HeaderLink,
  decorators: [
    (Story) => (
      <MemoryRouter>
        <Story />
      </MemoryRouter>
    ),
  ],
} as ComponentMeta<typeof HeaderLink>;

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof HeaderLink> = (args) => (
  <HeaderLink {...args} />
);

export const Normal = Template.bind({});
Normal.args = {
  title: "テストリンク",
  href: "#",
};

```

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296391/a2add78c-63ae-976f-5d5c-f7d52ad36d61.gif)
CRUDとは。備忘録

#1.はじめに
現在学習中の身で、CRUDがよくわからなかったので調べた結果をまとめました。

#2.CRUDとは
　CRUD（クラッド）はシステムに必要な４大機能の頭文字をとったもの。らしい

###C(create)登録、新規作成
例：ツイートする、アカウントを作る
###R(read)読み出し、参照
例：フォローしたアカウントのツイートを一覧で表示する
###U(update) 更新
例：アカウント情報を変更する
###D(delete)削除
例：ツイートを削除する、アカウントを削除する

#3.おわりに
この４つを応用してシステムというのはできてるみたいです。
WebStorm で Typescript のデバッグ環境を手軽に構築する

## はじめに

コーディングをしていると「ちょっとここの動作だけ見たいな」とか「このパッケージ試したいな」ということが多々あると思います。
そんなときに使えるデバッグ環境を手軽に構築する方法を紹介します。

## 環境

![about_webstorm](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352620/cf5a1da1-3260-39ce-8d7a-76104ff41233.png)

```zsh
% node --version
v17.0.1

% yarn --version
1.22.17
```

## 手順

### 1. 新規プロジェクトの作成をする

WebStorm を起動して、メニューバーの `File > New > Project...` をクリックする。
New Project ウィンドウが表示されたら Node.js を選択する。
![new_project](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352620/59d9ffd6-728b-2676-e9e2-057a9d0c1605.png)
Package manager を yarn に変更する (npm を使いたい方はそのままで OK です。以下、適宜読み替えてください) 。
設定が終わったら Create をクリックする。

### 2. Typescript の環境とソースファイルの用意をする

メニューバーの `View > Tool Windows > Terminal` をクリックする。
ターミナルが表示されたら以下のコマンドを実行する。

```zsh:zsh
% yarn add --dev typescript ts-node
% yarn run tsc --init
% touch main.ts
```

まとめて実行する場合は以下。

```zsh:zsh&#x20;(コピペ用)
% yarn add --dev typescript ts-node && yarn run tsc --init && touch main.ts
```

main.ts ファイルが作成されるので、それを開いて適当なコードを書く。

```ts:main.ts
function main() {
    const greeting = 'Hello, world!'
    console.log(greeting)
}

main()
```

### 3. 実行構成の作成をする

package.json ファイルを開いて以下を追記する。

```json:package.json
  "scripts": {
    "run": "./node_modules/.bin/ts-node"
  }
```

`"run":` の行の左側に ▶︎ マークが表示されるので、それをクリックして `Modify Run Configuration...` を選択する。
![modify_run_configuration](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352620/29bb4969-2db4-1d75-539e-fe7e89a4d4b2.png)
Create Run Configuration ウィンドウが表示されたら Arguments に `main.ts` と入力する。
![create_run_configuration](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352620/5b845376-6ace-49ed-dd69-6ce3be7e0b23.png)
設定が終わったら OK をクリックする。

### 4. 実行する

メニューバーの `Run > Run 'run'` をクリックする。

```console:Run：run
/usr/local/bin/node /usr/local/Cellar/yarn/1.22.17/libexec/bin/yarn.js run run main.ts
yarn run v1.22.17
$ ./node_modules/.bin/ts-node main.ts
Hello, world!
✨  Done in 0.82s.

Process finished with exit code 0
```

プログラムが実行されて、コンソールに結果が表示されました。
ブレークポイントを設置すれば、メニューバーの `Run > Debug 'run'` をクリックしたとき…
![break](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352620/d830e13b-63ff-3bb5-8f9a-2cad243ae2a9.png)
実行を一時停止できますし、変数の確認もできます。

## 参考文献

1. [2020/11版：TypeScript の開発環境を yarn で構築する](https://zenn.dev/junki555/articles/c21e6e74ea6ffcf074f8)
2. [TypeScriptを動かす方法4選](https://dev.classmethod.jp/articles/ts-action/)
parquetファイルの内容を確認する方法について


# 背景・目的
- parquetファイルと、GlueやAthenaなどで定義したスキーマにおいて、データタイプが異なるため、HIVE_BAT_DATAのエラーになる場合があります。
- スキーマをparquetで定義されているデータタイプに合わせて修正する場合、１）ファイルで定義されているデータを調べる。２）スキーマを再作成する。事が必要です。
- １）のファイルで定義されているデータを調べる場合、parquet-toolsを使うことで内容を確認できるので使い方をメモしておく。

# 内容
## 前提
- 対象のparquetファイルはvpcflowログになります。

## スキーマを確認する場合
- コマンド

```
parquet-tools schema ${parquetファイル}
```

- 結果

```
[21-11-25 14:01] $ parquet-tools schema 0123456789012_vpcflowlogs_ap-northeast-1_fl-xxxxxxxxxxxxxxxxxxx_20211124T0000Z_4fcc3e99.log.gz                                                                          
message LogFormatSchema.LogFormatInfo {
  optional int32 version;
  optional binary account_id (STRING);
  optional binary interface_id (STRING);
  optional binary srcaddr (STRING);
  optional binary dstaddr (STRING);
  optional int32 srcport;
  optional int32 dstport;
  optional int32 protocol;
  optional int64 packets;
  optional int64 bytes;
  optional int64 start;
  optional int64 end;
  optional binary action (STRING);
  optional binary log_status (STRING);
}

[21-11-25 14:01] $ 
```

## データを確認する場合（全件）
- コマンド
```
parquet-tools cat ${parquetファイル}
```
- 結果
    - 出力量が多いので先頭30行のみ表示しています。

```
[21-11-25 14:09] $ parquet-tools cat 0123456789012_vpcflowlogs_ap-northeast-1_fl-xxxxxxxxxxxxxxxxxxx_20211124T0000Z_4fcc3e99.log.gz | head -30
version = 2
account_id = unknown
interface_id = eni-xxxxxxxxxx
srcaddr = -
dstaddr = -
start = 1637712005
end = 1637712056
action = -
log_status = NODATA

version = 2
account_id = unknown
interface_id = eni-xxxxxx
srcaddr = -
dstaddr = -
start = 1637712065
end = 1637712116
action = -
log_status = NODATA

version = 2
account_id = unknown
interface_id = eni-xxxxxxx
srcaddr = -
dstaddr = -
start = 1637712125
end = 1637712176
action = -
log_status = NODATA


```

## データを確認する場合（先頭N件）
- head --records N or n Nで件数が絞り込める。*自分はエラーにより実行できなかったので、後ほど確認する。*
- ここでは、デフォルト5件を表示している。

```
parquet-tools head ${parquetファイル}

```

```
[21-11-25 14:16] $ parquet-tools head 0123456789012_vpcflowlogs_ap-northeast-1_fl-xxxxxxxxxxxxxxxxxxx_20211124T0000Z_4fcc3e99.log.gz    
version = 2
account_id = unknown
interface_id = eni-XXXX
srcaddr = -
dstaddr = -
start = 1637712005
end = 1637712056
action = -
log_status = NODATA

version = 2
account_id = unknown
interface_id = eni-XXXX
srcaddr = -
dstaddr = -
start = 1637712065
end = 1637712116
action = -
log_status = NODATA

version = 2
account_id = unknown
interface_id = eni-XXXX
srcaddr = -
dstaddr = -
start = 1637712125
end = 1637712176
action = -
log_status = NODATA

version = 2
account_id = unknown
interface_id = eni-XXXX
srcaddr = -
dstaddr = -
start = 1637712245
end = 1637712296
action = -
log_status = NODATA

version = 2
account_id = unknown
interface_id = eni-XXXX
srcaddr = -
dstaddr = -
start = 1637712185
end = 1637712236
action = -
log_status = NODATA

[21-11-25 14:16] $ 
```

# 考察
- この他にも、meta情報や件数出力、ファイルマージなどいくつかできる模様。後ほど記載する。

# 参考