はじめに こんにちは!竹村です! 最近、だいぶ前に作った個人用のアカウントを使ってAWS学習をしているのですが、ふと「ルートユーザーのセキュリティについてあまり気にしていなかったな。。。」と思い、改めて見直してみる事にしました。 AWS学習を始めたばかりの人や、以前アカウントは作って作業してたけど今は放置気味。。。なんて人、もしくは久しぶりにAWSを学習している人もいるかと思います。 今回は、AWSで安全に作業するために確認するべきルートユーザー周りのセキュリティについて、基本的な部分を2点ピックアップしてみます! ルートユーザーのアクセスキーを削除する プログラムからAWSのリソースを操作する際に必要となるアクセスキー。 ルートユーザーとIAMユーザーそれぞれでアクセスキーが作成できますが、ルートユーザーはAWSの全リソースに対して権限を持つ最も強力なユーザーであるため、通常はルートユーザーの権限を使用してプログラムからAWSのリソースを操作する事は推奨されていません。 また、AWSアカウント自体の設定変更や解約も行えるので、万が一アクセスキーが漏洩してしまった場合、恐ろしい事になってしまいます。。。 そんな事態を防止するためにも、ルートユーザーのアクセスキーは存在しない状態にしておくべきです。 通常の手順でアカウントを作成していれば、ルートユーザーにはアクセスキーは作成されていませんが、もし何らかの操作で誤って作成してしまっていた場合は削除しましょう。 ルートユーザーのアクセスキーを削除するには、以下の手順で行います。 まず、ルートユーザーでログインします。 コンソール画面の上部にあるアカウント名をクリックし、「セキュリティ認証情報」をクリックします。 アクセスキーの項目を開き、有効になっているアクセスキーを見つけ出してください。 アクセスキーを削除するには、まず無効化させる必要があります。 「無効化」をクリックすると、以下ポップアップが表示されますので、「無効化」をクリックしてください。 その後、コンソール画面で「削除」をクリックしてください。 テキストフィールドにアクセスキーIDを入力し、削除します。 これでルートユーザーのアクセスキーが削除されます。 ルートユーザーのMFAを有効化する MFA(Multi Factor Authentication:多要素認証)はその名の通り、複数の要素をもって認証を行うことです。 認証要素は大きく分けて「知識要素」「所持要素」「生体要素」の3つがあります。 ・知識要素:パスワードや暗証番号等、本人しか知らない情報 ・所持要素:スマホやパスポート、クレジットカード等、本人しか持っていないもの ・生体要素:指紋、網膜といった生物学的な情報 認証は、これらのうち2つ以上の要素を組み合わせることでより強力になります。 初期設定のままの場合、ルートユーザーの認証に必要なのはメールアドレスとパスワードのみです。 ルートユーザーの持つ強力な権限に対し、この2つだけでは相対的に弱いのは明白ですので、スマホを仮想MFAデバイスとして使い、ルートユーザーのMFAを有効化します。 手順は以下です。 まず、認証で利用するスマホにMFA用のアプリをインストールします。 Twilio AuthyやGoogle Authenticator等、いくつか種類がありますが、基本的な動作や機能は同じです。 自分はMicrosoft Authenticatorをインストールしました。 次に、アクセスキーの削除を行った先ほどの画面(セキュリティ認証情報画面)から、多要素認証(MFA)を選択し、「MFAの有効化」をクリックします。 今回は、スマホを仮想MFAデバイスとして使用してみます! 一番上にチェックを入れて続行します。 インストールしたMFA用アプリで、表示されたQRコードを読み取ります。 読み取った後、アプリ上では認証に必要なMFAコードが表示されますので、これをコンソールのポップアップ画面に入力していきます。 2つの連続したコードを入力する必要があるのですが、2つ目のコードが表示されるまでに30秒ほどかかるかと思います。 入力できたら、「MFAの割り当て」をクリックします。 これで、仮想MFAが正常に割り当てられます。 次回以降ルートユーザーでログインする場合は、メールアドレスとパスワードに加え、インストールしたMFA用アプリが発行するMFAコードが必要になります。 おわりに 今回取り上げた要素以外にも、AWSにはセキュリティについてのベストプラクティスが定義されていますので、参照する事をお勧めします。 IAM でのセキュリティのベストプラクティス https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html ベストプラクティスに記載してある設定を全て行ったとしてもリスクを100%回避できるわけではありませんが、不正利用や意図しない高額請求を防ぐためにも、セキュリティ意識はしっかりと持っておくべきだと感じました。 ではまた! The post AWSアカウントのセキュリティを見直してみた話 first appeared on miracleave Tech Blog .
こんにちはこんばんわ!末端冷え性な気がする、佐々木です! そして日々、業務効率化や自動化での改善に取り組んでいる皆さんお疲れ様です。 そんな皆さんの中でPythonを利用して改善に取り組んでいる方もいらっしゃるのではないでしょうか? 自分も以前Pythonでちょっとしたツール作っていました。(今も趣味半分でたまに作ります) しかし、せっかく作ったは良かったものの「 使ってもらう方のPCにわざわざPythonをインストールしてあげないと、、 」となると、これは めちゃくちゃめんどくさい 導入ハードルがぐーーーーーーーーーんっとあがりますね。 というわけで、今回はそんな悩みをサクッと解決できるライブラリ、「pyinstaller」を紹介します。 pyinstaller pyinstaller/index.rst at fcff15e6e7ab6fad135c584c2b6cc5e0f7809319 · pyinstaller/pyinstaller Freeze (package) Python programs into stand-alone executables - pyinstaller/index.rst at fcff15e6e7ab6fad135c584c2b6cc5e0f7809319 · pyinstaller/pyinstaller github.com ⭕メリット PythonをインストールしていないPCでも動かせるようになる。 コマンドではなく、クリックで起動することができるようになる。 ❌デメリット exe化させた実行ファイルのサイズが大きくなりがち(普通に6〜30MBくらいになる) 作成した実行ファイルはOSに依存してしまう。(Windowsで作成した場合はWindows、Macで作成した場合はMac上でのみ動作する) 冒頭のお話しのようなパターンだと、実行ファイル1つ渡せば良いだけですので、ややこしい環境設定も何も必要ないのは、大きいメリットですね。 サイズが大きくなりがちなデメリットに関しては、余計なライブラリを含まないようにすることで多少はリサイズすることが出来ます。(それでも僅かですが) 配布するプログラムを作成する 配布するためのプログラムを作成するに当たり、ちょっとポイントがあります。 1つ目は、仮想環境で作成することです。 作成されたファイルには実行環境となるPythonのライブラリやパッケージが詰め込まれます。 未使用なライブラリやパッケージであっても、容赦なく実行ファイルに含まれてしまうので、仮想環境を作りましょう。( 同様の理由でAnacondaなどを使っている方もお気をつけください ) 2つ目は、入力用の「input」 を記述することです。 作成された実行ファイルを実行させるとシェルが立ち上がります。(一応、このシェルを立ち上げないように設定することも出来ます。) ですが、プログラム上入力を必要としない場合はシェルはそのまま閉じてしまいます。 入力が不要であればそれでも良いのですが、クリックしたら「いきなりシェルが立ち上がって、すぐ閉じて、、ってなんかめちゃくちゃ怖くない?w」って思うので、上記の「input」を記述することを勧めます。 上記の2つを踏まえてプログラムを書いてみます。 仮想環境を作成する。 python -m venv .venv 2. 仮想環境に切り替える Windows(PowerShellの場合) .venv/Scripts/Activate.ps1 Mac source .venv/bin/activate 3. 配布したい内容のプログラムを書く (結構前に作っていたんですが、githubにあげてなかったのでこのタイミングであげましたw) ## main.py import psutil from matplotlib import pyplot import time def monitor(): # Get memory info cap_memory = psutil.virtual_memory() # Get cpu info cpu = psutil.cpu_percent(interval=1) return cap_memory, cpu if __name__ == "__main__": input("Press the enter.. ") print("start Monitoring...") i = 1 # byte convert gb = 1024 * 1024 * 1024 mem_total_arr = [] mem_used_arr = [] mem_free_arr = [] cpu_used_arr = [] while i <= 10: memory, cpu = monitor() print(f"{i}回目----") # memory capacity print(f"memory capacity > {round(memory.total / gb, 2)}GB") mem_total = round(memory.total / gb, 2) mem_total_arr.append(mem_total) # Used memory volume print(f"Used memory > {round(memory.used / gb, 2)}GB") mem_used = round(memory.used / gb, 2) mem_used_arr.append(mem_used) # free memory Volume print(f"free memory > {round(memory.available / gb, 2)}GB") mem_free = round(memory.available / gb, 2) mem_free_arr.append(mem_free) # Used cpu activity print(f"Used cpu > {cpu}%") cpu_used_arr.append(cpu) time.sleep(2) i += 1 x = list(range(10)) fig = pyplot.figure() fig_mem = fig.add_subplot(211, title="Used Memory", ylabel="GB") fig_mem.plot(x, mem_used_arr, color="r") pyplot.grid(ls="--") fig_cpu = fig.add_subplot(212, title="Used Cpu", ylabel="%") fig_cpu.plot(x, cpu_used_arr, color="g") pyplot.grid(ls="--") pyplot.show() input("exit Press the enter..") ※必要なライブラリなどはgithubにrequirements.txtを置いてますので参考にしてください。 GitHub - daisuke8000/cpuMonitor Contribute to daisuke8000/cpuMonitor development by creating an account on GitHub. github.com 実行ファイルを作成しよう では、実際に配布できるように実行ファイルを生成してみたいと思います。 1. インストールを行う。 pip install pyinstaller 2. 実行ファイルを作成する(”–onefile” ・・・ 実行ファイルを単一化させるオプションコマンド ) ※ここでの「main.py」は実際にプログラムが書かれたpyファイルを指します。 pyinstaller main.py --onefile 3.「dist」というフォルダが同階層に作成され、その中にあるファイルが実行ファイルとなる。 以上、これだけのステップで配布できる実行ファイルが作成されます。 実際に私の方でも上記の手順で作成してみました。作業フォルダが以下のようになっているかと思います。(赤丸の部分) 最後に 如何だったでしょうか? 「作ったはいいけど、使える人は限られちゃうから自己満ツールになっちゃったなぁ、、」 なんて寂しい思いはもうしなくて済みそうですね! ではまた! The post 「pyinstaller」で作ったツールを配布しよう! first appeared on miracleave Tech Blog .
はじめに 新年あけましておめでとうございます! 新垣です!年末年始どう過ごしてましたでしょうか?正月って意外とやることなくて暇ですよね。。。私は最近Vue.jsの案件にアサインして勉強の日々なのですがVue.jsを使ってブログを構築してみたいなと思い、調べたところVue.jsの静的サイトジェネレーターのGridsomeというものがあり年末年始でブログ構築してみたのでこちらのブログのネタにしようとのことで今回のテーマにしました! 開発環境 まずは環境の確認です。以下のコマンドでnodeのバージョンを確認してください。 $node -v v16.0.0 今回はv16.0.0を使用していきます。 次に以下のコマンドでgridsomeのcliをインストールしていきます。 $npm install --global @gridsome/cli アプリケーションの作成 インストール完了しましたら以下のコマンドでアプリケーションを作成します。 今回はblog-appという名前にしました。 $gridsome create blog-app しばらくしてアプリケーションの作成が完了したら以下のコマンドを実行してアプリケーションを立ち上げます。 $cd blog-app $gridsome develop 立ち上げに完了しているかどうかlocalhostの8080ポートで確認してみましょう。 http://localhost:8080 以下の様な画面が表示されれば問題なく立ち上がっています。 それでは以下の様にソースを修正しましょう。 タイトル部分を「This is My Blog!」に変更してみます。 src/pages/index.vue <template> <Layout> <!-- Learn how to use images here: https://gridsome.org/docs/images --> <g-image alt="Example image" src="~/favicon.png" width="135" /> - <h1>Hello, world!</h1> + <h1>This is My Blog!</h1> <p> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Pariatur excepturi labore tempore expedita, et iste tenetur suscipit explicabo! Dolores, aperiam non officia eos quod asperiores </p> <p class="home-links"> <a href="https://gridsome.org/docs/" target="_blank" rel="noopener">Gridsome Docs</a> <a href="https://github.com/gridsome/gridsome" target="_blank" rel="noopener">GitHub</a> </p> </Layout> </template> <script> export default { metaInfo: { title: 'Hello, world!' } } </script> <style> .home-links a { margin-right: 1rem; } </style> 以下の様に変更されていればOKです。 githubに新たにリポジトリ を作成。以下コマンドでgit pushしましょう。create repositoryボタンを押します。 git init git add -A git commit -m "first commit" git remote add origin git@github.com: git branch -M main git push -u origin main Netlifyにデプロイ Netlifyにアクセスしましょう。 https://www.netlify.com/ 以下のImport an existing projectのimport from gitをクリック。 githubを選択 githubの認証を済ましてリポジトリを選択 リポジトリ の設定を行う。 build commandはgridsome buildに変更。Deploy siteをクリック。 しばらくするとアクセスすることができます。 アクセスしてデプロイが完了しているか確認しましょう。 デプロイ成功しました! 最後に 皆さんうまくブログ構築できましたでしょうか?gridsomeとNetlifyをつかうことで素早くアプリケーションをデプロイすることができて私もかなり驚きました!今回はgridsomeはあまり深く取り上げることはできませんでしたがgraphqlを利用したりすることもできるので興味のある方は試してみてください! 今回参考にした記事、サイト https://gridsome.org/ https://qiita.com/Dev-kenta/items/14ae9fdc6eec76f63ba1 The post Vue.js 静的サイトジェネレーター GridSome でブログをNetlifyに爆速デプロイ! first appeared on miracleave Tech Blog .
Controller、Request、Resource、Actionファイルを一つずつ作るの面倒くさ〜い。 はじめに 上野です! 今回はLaravelでのファイル作成をより楽にできないかなと思い、Makefileで複数ファイルを一括作成できるようにしてみました! ちなみに、今回一括作成したいファイルは1メソッドのみのControllerファイル、Requestファイル、Resourceファイル、Actionファイルの4つのファイルです。 Makefileとは makeコマンドは、コンパイル作業を行うために様々な作業を自動的に行うためのコマンドです。「Makefile」は、コンパイル、依存関係の管理、インストールなどのルールを記述しておくためのファイルで、makeコマンドが読み込んで処理を行います。Makefileには、ファイルの生成手順や、プログラムを構成しているファイル同士の関係を記述します。 参考元の記事: https://linuc.org/study/knowledge/542/ 簡単な例だと、下記のように実行したいルールをMakefileに書いておけば、 make [実行したいルール] で呼び出すことができます。 Makefile build: docker compose up -d --build greeting: touch greeting.txt @echo 'Good morning' >> greeting.txt @echo 'Hello' >> greeting.txt @echo 'Good evening' >> greeting.txt Makefileが存在する階層のターミナル上で make build とするとdocker composeのbuildが始まります。 make greeting とすると下記のようなファイルが作成されます。 実行環境とLaravelのフォルダ構成 実行環境:macOS(macの方であれば、インストールしなくてもmakeコマンドが実行できます。) Docker Composeの構成 - api (Laravel) - nginx - db (Mysql) - front (Next.js) Laravelのフォルダ構成 - api - app - Http - Controllers - API - User - GetUser.php // Makefileを利用して作成したファイル - Requests - User - GetUserRequest.php // Makefileを利用して作成したファイル - Resources - User - GetUserResource.php // Makefileを利用して作成したファイル - Models - Providers - UseCases - User - GetUserAction.php // Makefileを利用して作成したファイル - config - database ...以下省略 - front (Next.js) - docker-compose.yml - Makefile // 左記Makefileを利用し複数のファイルを一括作成します - MakefileDir - TestAction.php // Actionファイルを作成する際の元となるファイル MakefileDir/TestAction.php <?php namespace App\UseCases\DIR; class NAME { public function __invoke() { return; } } 下記のなんちゃってクリーンアーキテクチャのフォルダ構成を参考に、原則1ファイル1アクションという構成にしています。 参考元の記事: https://zenn.dev/mpyw/articles/ce7d09eb6d8117 Makefileでファイル作成を簡素化 今回はDocker環境でのファイル作成を想定しています。もし、Docker環境をご利用でない場合は docker compose exec api の部分を削除し、php artisanコマンドが実行できるフォルダ階層にMakefileを作成していただけると同じように実行できます。 ちなみに、今回は自由にディレクトリとファイル名を指定して作成できるようにしています。 $(DIR)、$(NAME) となっている部分は変数ですので、makeコマンドを実行する際、引数に2つの変数(DIR、NAME )を渡す必要がありますのでご注意ください。 コントローラファイルの作成用のルール create-controller: docker compose exec api php artisan make:controller API/$(DIR)/$(NAME) --invokable リクエストファイルの 作成用のルール create-request: docker compose exec api php artisan make:request $(DIR)/$(NAME)'Request' リソースファイルの 作成用のルール create-resource: docker compose exec api php artisan make:resource $(DIR)/$(NAME)'Resource' アクションファイルの 作成用のルール create-action: mkdir -p ./api/app/UseCases/$(DIR) cp ./MakefileDir/TestAction.php ./api/app/UseCases/$(DIR)/$(NAME)'Action.php' sed -i.bk -e 's/DIR/'$(DIR)'/g' ./api/app/UseCases/$(DIR)/$(NAME)'Action.php' sed -i.bk -e 's/NAME/'$(NAME)'Action/g' ./api/app/UseCases/$(DIR)/$(NAME)'Action.php' rm ./api/app/UseCases/$(DIR)/$(NAME)'Action.php.bk' Controller、Request、Resource、Actioinファイル一括作成用のルール create-controller: docker compose exec api php artisan make:controller API/$(DIR)/$(NAME) --invokable create-request: docker compose exec api php artisan make:request $(DIR)/$(NAME)'Request' create-resource: docker compose exec api php artisan make:resource $(DIR)/$(NAME)'Resource' create-action: mkdir -p ./api/app/UseCases/$(DIR) cp ./MakefileDir/TestAction.php ./api/app/UseCases/$(DIR)/$(NAME)'Action.php' sed -i.bk -e 's/DIR/'$(DIR)'/g' ./api/app/UseCases/$(DIR)/$(NAME)'Action.php' sed -i.bk -e 's/NAME/'$(NAME)'Action/g' ./api/app/UseCases/$(DIR)/$(NAME)'Action.php' rm ./api/app/UseCases/$(DIR)/$(NAME)'Action.php.bk' create-api: @make create-controller @make create-request @make create-resource @make create-action 上記Makefileファイルを定義したうえで、下記コマンドを実行するとContorller、Requset、Resource、Actionファイルがそれぞれ作成されます。 make create-api DIR=User NAME=GetProfile 実行後作成されるファイル ・./api/app/Http/Controllers/API/User/GetProfile.php ・./api/app/Http/Requests/User/GetProfileRequest.php ・./api/app/Http/Resources/User/GetProfileResource.php ・./api/app/UseCases/User/GetProfileAction.php また、コントローラファイルだけリクエストファイルだけ作成したいという場合は、下記のコマンドを実行するだけで作成することができます。 コントローラファイルの作成 make create-controller DIR=User NAME=GetProfile リクエストファイルの作成 make create-request DIR=User NAME=GetProfile まとめ 今回は少し面倒なファイル作成を一括で作成できるようにしてみました。今回はMakefileで実装しましたが、Laravelでも同じようにカスタマイズしたコマンドを作成し、1つのコマンドで複数のファイルを作成できるようなので、今度試してみたいと思います! これからも開発の中で楽ができそうな箇所があればMakefileなどを活用してもっと簡素化していき、こちらで情報共有できればと思います! 今回は以上となります。ありがとうございました! The post MakefileでLaravelのファイル作成を楽にしてみた first appeared on miracleave Tech Blog .
記事作成から1年以上経過しています。 内容が古い可能性があります。 publicスキーマってなんじゃ!!! TL;DR(要約すると・・・) MySQLではデータベースとスキーマは同じと思って大丈夫。 PostgreSQLではデータベースがあってその下にスキーマが存在する。 デフォルトでは public スキーマが作成される。 これまでの経緯 とある日の昼下がり BOSS: ちょっと悪いんだけどさ、検証用のPostgreSQLにdevelopスキーマ追加してもらえないかな? 私: developスキーマですね、いいっすよ。 私 : (ユーザ作って、DB作って、権限付与してと…) 私: BOSS!developスキーマできました! BOSS: ありがとう! BOSS: ・・・ん? これpublicに繋げばいいの? 私: ・・・ん? public? ほんとだ!publicスキーマってなんじゃ!!! というわけで、今回は MySQL と PostgreSQL のスキーマについて確認しましょう。 必要なもの Docker上に MySQL と PostgreSQL を構築し確認していきますが、 ローカル環境でも問題無いです。 また、データベースの操作はA5 SQL Mk-2を使用します。 必須 MySQL:8.0 PostgreSQL:12.3 任意 Docker, Docker Compose A5 SQL Mk-2 Sublime Text MySQLで確認 DockerComposeでMySQLを起動して、 version: '3' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root TZ: 'Asia/Tokyo' ports: - "3306:3306" A5M2 で接続して、 developデータベースとテーブルを作成して、 /* データベースの作成 */ CREATE DATABASE develop; /* テーブルの作成 */ CREATE TABLE develop.schema_info ( id int, name varchar(255) ); /* 適当にデータを insert */ INSERT INTO develop.schema_info values(1, 'MySQL.develop'); 一度接続を閉じてDBの内容をA5M2で確認してみる。 RDBMS(local_mysql) > Database(develop) > Table(schema_info) の構成なので、データベースとスキーマは同じという認識でも問題なさそう。 次は、PostgreSQLを確認してみます。 PostgreSQLで確認 MySQLと同様に確認します。 ※ PostgreSQL:12.3 だと A5M2 のバージョンによってはエラーが出るので要注意!詳細は下部のおまけにて DockerComposeで PostgreSQL を起動して、 version: '3' services: postgres: image: postgres:11.8 environment: POSTGRES_PASSWORD: postgres ports: - "5432:5432" A5M2 で接続して、 developデータベースとテーブルを作成して、 /* データベースの作成 */ CREATE DATABASE develop; /* テーブルの作成 */ CREATE TABLE schema_info ( id integer, name varchar(255) ); /* 適当にデータを insert */ INSERT INTO schema_info values(2, 'PostgreSQL.develop'); 一度接続を閉じてDBの内容を確認してみる。 いつの間にか public がいた! そして develop がいない!! developに接続できるようにDB設定を修正してテーブルを作り直す Database(local_postgres.develop) > schema(public) > Table(schema_info) の構成なので、MySQLとは異なりデータベースとテーブルの間にスキーマが挟まっていることが確認できた。 エピローグ 私: BOSS!! スキーマの概念について私が間違っておりました!接続手順書もつけるので許してください! BOSS: うむ!! 手順書ありがとう!助かります! みんな開発に着手できましたとさ、めでたしめでたし。 おまけ PostgreSQL:12.3 に A5M2:2.14.1 で接続すると が出てくる。 ポスグレ内の構成が変わったことが原因みたい。 トピック: 【不具合報告】接続エラー | The post DB→わかる。Table→わかる。Schema→お前は一体なんなんだ・・・! first appeared on miracleave Tech Blog .
変数展開がされないやんけ・・・! TL;DR 値をローテしない場合は Parameter Store がシンプルで使いやすい。 systemd の EnvironmentFile は変数やコマンドは展開されない。 事前に systemctl set-environment で値を設定することが可能。 はじめに あけましておめでとうございます。 新年一本目の執筆権をいただきました Bell です。 今回は AWS Systems Manager の Parameter Store という機能を利用して 環境ごとの設定値差分を吸収しようとした際のお話です。 ことの発端 お昼休憩を終えたある日の午後 Bell: ゴクゴク… (食後に黒烏龍茶飲んでるからお昼ごはんの脂肪分は帳消しだな) 長田: ベルくん, ちょっと相談してもいいかな? Bell: はいはい, なんでしょう? 長田: AWS 上の Linux で環境変数を使って本番と検証で DB の接続先とか, 外部連携の鍵とか切り替えたいんだけど・・・ なんかいい方法知らないかな? Bell: そうですね・・・ Parameter Store ってのがあるのでそれでどうですかね? ということで, AWS Systems Manager の Parameter Store の使い方をまとめます。 Parameter Store から値の取得 まずは parameter store から値を取得するまでを検証しましょう。 構成としては以下のイメージです。 EC2 インスタンス の aws cli を使って Parameter Store から値を取得し環境変数に設定します。 設定した環境変数を読み込んでアプリケーションが起動します。 シンプルですね。 ここでは DB のユーザ名とパスワードを取得する場合を想定して実践します。 値の設定 まずは Parameter Store に値を設定しましょう。 マネジメントコンソールから Systems Manager (ssm) を検索して画面を表示します。 左メニューのパラメータストアからパラメータの設定画面を表示します。 パラメータの作成ボタンから登録に進みます。 パラメータの設定をしていきます. key val 名前 dev.User 説明 db user name 利用枠 標準 タイプ 文字列 データ型 text 値 dev-ssm-ps-db-user パラメータを作成で確定してもう一度パラメータの作成ボタンからパスワード情報を登録します。 key val 名前 dev.Password 説明 db user password 利用枠 標準 タイプ 文字列 データ型 text 値 dev-ssm-ps-db-password パラメータの名前には 環境の識別や IAM policy でのアクセス制御のため環境毎のプレフィックスを付与しました。 これで Parameter Store の設定は完了です。 直感的でいいですね。 EC2 インスタンスの作成 値を取得する EC2 インスタンスを作成します。 Parameter Store にアクセスするための権限が必要ですので、 まずは IAM Role とそれに適用する IAM Policy を作成しましょう。 マネジメントコンソールから IAM を検索して画面を表示し左メニューのロールを選択します。 EC2 インスタンスに付与するロールを作成したいので, ロールからロールを作成を選択します。 EC2 に付与するロールのため、ユースケースの選択には EC2 を選んで 次のステップを選択します。 権限を細かく制御したいのでポリシーの作成から新しくポリシーを作成します。 新しいポリシーに ec2:descrive-instance と ssm:GetParameters の権限を付与します。 これで Systems Manger に設定した秘匿情報にアクセスすることができるようになります。 パラメータ個別にアクセス制限を設定することも可能なので、本番と開発で参照の可否を分けることもできます。 今回は dev. で始めるパラメータの参照権限を付与しています。 インスタンス自身の Name タグのプレフィックスを取得するために ec2:descrive-instance も付与しています。 ec2:descrive-instance 項目 値 サービス EC2 アクション DescribeInstances ssm:GetParameters 項目 値 サービス Systems Manager アクション GetParameters リソース Region ap-northeast-1 リソース Account そのまま リソース Parameter name… dev.* 設定できたら次のステップに進みましょう。 タグは Name タグに dev-ssm-param-policy とします。 ポリシーの確認画面の名前も同様に dev-ssm-param-policy を設定します。 作成できましたらロールの作成画面に戻り、再読み込みをしてから dev-ssm-param-policy をチェックして次のステップを選択します。 Name タグに dev-ssm-param-role を設定して次のステップを選択します。 ロール名にも dev-ssm-param-role を設定してロールの作成をします。 ロールができたら EC2 インスタンスを作成します。 ネットワークなどのリソースは必要に応じてよしなに作成してください。 EC2 を検索してインスタンスの画面を表示します。 新しくインスタンスを作成するのでインスタンスを起動 基本的にデフォルトや無料枠の設定で大丈夫です。 インスタンスの詳細の設定の IAM ロールに先程作成した dev-ssm-param-role を選択します。 Name タグには dev-ssm-ps-inst を設定します。 細かい設定はご自身のAWS環境に応じて設定してください。参考までに例で設定した内容をまとめて載せておきます。 内容に問題が無いことこ確認して作成しましょう。 インスタンスの状態が 実行中 になれば作成完了です。 インスタンスに SSH 接続して値が取れるか確認します。 aws ssm get-parameters --region ap-northeast-1 --name dev.User --query "Parameters[0].Value" --output text parameter store に設定した値が取得できていればインスタンスの作成が完了です。 systemd の設定 作成したインスタンスの systemd に parameter store の値を読み込んでサービスを起動する設定を入れましょう。 追加する設定およびスクリプトは以下の 3 つです。 ssm-param.sh 起動するサービスを想定したスクリプト DBのユーザ名とパスワードを一定間隔でログに出力する ssm-param-pre-exec.sh parameter store から値を読み込んで設定するスクリプト ssm-param.sh の前に起動する ssm-param.service ssm-param.sh を起動するための systemd の定義ファイル 内容は以下のとおりです。 #!/bin/bash LOG_FILE=$(dirname $0)/$(basename $0 .sh).log while true; do echo "Connection DB by ${DB_USER}/${DB_PASSWORD}" >> $LOG_FILE sleep 10 done; 10 秒ごとにユーザ名とパスワードを出力しています。 DB 接続のヘルスチェックみたいなイメージですね。 スクリプトと同じ場所にログファイルを作成して追記しています。 #!/bin/bash # region の設定 export AWS_DEFAULT_REGION=$(/usr/bin/curl 169.254.169.254/latest/meta-data/placement/region 2>/dev/null) # インスタンス情報の取得 INSTANCE_ID=$(/usr/bin/curl 169.254.169.254/latest/meta-data/instance-id 2>/dev/null) INSTANCE_NAME=$(/usr/bin/aws ec2 describe-instances --instance-ids ${INSTANCE_ID} --query "Reservations[0].Instances[0].Tags[?Key=='Name'].Value" --output text) # パラメータの取得 DB_USER=$(/usr/bin/aws ssm get-parameters --name ${INSTANCE_NAME%%-*}.User --query "Parameters[0].Value" --output text) DB_PASSWORD=$(/usr/bin/aws ssm get-parameters --name ${INSTANCE_NAME%%-*}.Password --query "Parameters[0].Value" --output text) # パラメータを systemd に設定 systemctl set-environment DB_USER=${DB_USER} systemctl set-environment DB_PASSWORD=${DB_PASSWORD} aws cli を使って parameter store から設定値を取得して systemctl コマンドを利用し設定しています。 設定値の取得のためにリージョンの情報やインスタンスの情報が必要なのではじめに取得しています。 [Unit] Description = load environment from aws system manager parameter strore [Service] User=root ExecStartPre=/usr/bin/bash /opt/ssm-param-pre-exec.sh ExecStart=/usr/bin/bash /opt/ssm-param.sh ExecStartPre で値を設定して ExecStart でスクリプトを起動します。 シンプルですね。 設定が終わったら起動してログファイルを見てみましょう。 sudo systemctl start ssm-param tail -f /opt/ssm-param.log parameter store に保存された値が読み込めているのが確認できるかと思います。 失敗談: EnvironmentFile の設定 systemd の設定に環境変数を読み込むための EnvironmentFile が設定できるのですが、 こちらの挙動でハマったことがありました。 EnvironmentFile は変数の展開がされないのです!! 試しにサービスの設定を以下のように修正してみましょう。 [Unit] Description = load environment from aws system manager parameter strore [Service] User=root EnvironmentFile=/opt/ssm-param-pre-exec.sh ExecStart=/usr/bin/bash /opt/ssm-param.sh サービスを再起動して環境変数の値を確認してみましょう。 変数にコマンドが出力されているのがわかるでしょうか? このように EnvironmentFile では変数やコマンドが展開されないので注意しましょう・・・💧 The post AWS Systems Manager Parameter Store の値を systemd の環境変数に設定する first appeared on miracleave Tech Blog .
記事作成から1年以上経過しています。 内容が古い可能性があります。 大分昔に書いた内容なので注意 「 PlayFramework2 徹底入門 」でModelを作成するところでimport分が全く効かなかったのでメモ。 環境 windows 10 eclipse oxygen プロジェクトを作成(ディレクトリは任意) c:¥hoge>activator new [作成したプロジェクトの名前] play-java ディレクトリの移動 c:¥hoge>cd [作成したプロジェクト] plugins.sbtに追記 addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.10") addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0") addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0") addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.4") addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.8") addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.1") addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0") addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.6") # 追加 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.2") addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0") #addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.2") eclipse用に変換 c:¥hoge¥hoge>activator eclipse アプリケーション起動 c:¥hoge¥hoge>activator run ここまでは順調だったが、model作成時にハマってしまった。 問題のjavaファイル package models; import java.util.Date; import javax.persistence.*; import com.avaje.ebean.Model; import lombok.Getter; import lombok.Setter; @Getter @Setter @Entity public class Message extends Model { @Id public Long id; public String name; public String mail; public String message; public Date pastDate; } plugins.sbtに追記 addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.10") addSbtPlugin("com.typesafe.sbt" % "sbt-coffeescript" % "1.0.0") addSbtPlugin("com.typesafe.sbt" % "sbt-less" % "1.1.0") addSbtPlugin("com.typesafe.sbt" % "sbt-jshint" % "1.0.4") addSbtPlugin("com.typesafe.sbt" % "sbt-rjs" % "1.0.8") addSbtPlugin("com.typesafe.sbt" % "sbt-digest" % "1.1.1") addSbtPlugin("com.typesafe.sbt" % "sbt-mocha" % "1.1.0") addSbtPlugin("org.irundaia.sbt" % "sbt-sassify" % "1.4.6") # 追加 addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "5.2.2") addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0") # コメント解除 addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "3.0.2") build.sbtに追記 lazy val root = (project in file(".")).enablePlugins(PlayJava) .enablePlugins(PlayEbean) // 追記 scalaVersion := "2.11.7" libraryDependencies ++= Seq( javaJdbc, cache, javaWs, javaJpa, // 追記 "org.postgresql" % "postgresql" % "9.4.1212.jre7", // 追記 "org.projectlombok" % "lombok" % "1.16.10" // 追記 ) activatorアップデート c:¥hoge¥hoge>activator update eclipseに反映 c:¥hoge¥hoge>activator "eclipse with-source=true" コンパイル c:¥hoge¥hoge>activator compile 一先ず解決。 The post Play Framework 2.6 (Java) の開発環境を整える first appeared on miracleave Tech Blog .
はじめに 初めまして!青柳です。30代で未経験ながらエンジニアに転職し、早2年が経ちます。以前よりRuby on Railsを勉強していましたが、最近は業務で携わることも増えてきました。基本的なソースコードを書くことは慣れてきましたが、RSpecを書く機会があったときにつまずきました。 今回はそのRSpecの中でも初めて使用したstubについてまとめました。 Webmockとは HTTPリクエストするときに、リクエスト部分をスタブ化するためのライブラリのことです。 一から実装するのではなくGemを使用することで比較的簡単に実装することが可能になります! Webmockを使用する準備 まずはgemを追加していきます。主にテストで使用するのでtest配下に追加します。(プログラムによってはdevelopmentなどへの追加もあり得ます) #Gemfile group :test do gem "webmock" end その後、installを実行します。 $ bundle install テストで使用するModel 今回はBitflyer APIを叩く簡素なModelを定義します。 # model/Bitflyer.rb require 'net/https' require 'uri' class Bitflyer < ApplicationRecord class << self def access(params) begin uri = URI('https://api.bitflyer.jp/v1/board') uri.query = params response = Net::HTTP.get_response(uri) puts response.code rescue => e puts e end end end end Bitflyer.access とすると https://api.bitflyer.jp/v1/board に対してアクセスをします。 引数に params を指定すれば、アクセス先を指定することもできます。 また例外が発生したときにキャッチできるように rescue を追加しています。 RSpecを実装する では実際にRSpecを実装します。 まず初めにゴールとなるソースをご紹介します。 #spec/bitflyer_spec.rb require 'rails_helper' require 'webmock/rspec' RSpec.describe Bitflyer do describe "#access" do let(:endpoint) { {params: 'product_code=FX_BTC_JPY'} } subject { Bitflyer.access(endpoint[:params]) } context 'Bitflyer Api' do before do bitflyer_api_request end it 'should be access bitflyer api'do expect{ subject }.not_to raise_error end end end def bitflyer_api_request WebMock.stub_request(:get, "https://api.bitflyer.jp/v1/board?#{endpoint[:params]}") .to_return( body: File.read("#{Rails.root}/test/fixtures/bitflyer/response.json"), status: 'OK', headers: { 'Content-Type' => 'application/json'} ) end end では解説していきます。 まず、webmockを使用するために、ソース上部で読み込みます。 require 'webmock/rspec' 次に subject の実装です。 下記のように先ほど実装した Bitflyerモデルの access メソッドを実行するように subject を登録しています。 また今回は引数に endpoint[:params] を指定しています。 letで登録している変数を参照しており、 product_code=FX_BTC_JPY が代入されます。 これはBTCとJPYの為替情報を取得するAPIになります。(先程の Bitflyerモデルのaccessメソッドを確認していただければと思います) let(:endpoint) { {params: 'product_code=FX_BTC_JPY'} } subject { Bitflyer.access(endpoint[:params]) } 次に context Bitflyer Apiの中のbeforeの中身を見てみましょう。 context 'Bitflyer Api' do before do bitflyer_api_request end ・ ・ ・ この bitflyer_api_request がWebmock登録箇所になります。 実装の中身を見ていきましょう。 def bitflyer_api_request WebMock.stub_request(:get, "https://api.bitflyer.jp/v1/board?#{endpoint[:params]}") .to_return( body: File.read("#{Rails.root}/test/fixtures/bitflyer/response.json"), status: 'OK', headers: { 'Content-Type' => 'application/json'} ) end 上記のようにまずstubを登録するには WebMock.stub_request メソッドを使用します。 引数にHTTPメソッド(get、post、patchなど)と、登録したいURLを設定します。 またそれに対して to_return メソッドを指定すると response を指定することもできます。 上記では、 response.json というファイルを指定しています。 こちらには実際にAPIにアクセスした際に期待するレスポンスを記入しておくことで、(今回は行いませんが)正しいレスポンスが得られているかなどのテストに使用するができます。 最後に実際のテストですが、今回は下記のように実装しています。 こちらは subject を実行した際にerrorが発生しないことを確かめるテストになります。 it 'should be access bitflyer api'do expect{ subject }.not_to raise_error end これでRSpecを実行すると登録されたstubを元にテストが開始されます! 注意点 前提として、テストの実行前にstubを登録しないと、 Bitflyer.access の中の response = Net::HTTP.get_response(uri) が実際にuriにアクセスしてしまいます。 そのため、今回のケースのように、テスト実行前にbeforeで登録しておくことが重要です。 また、stubに登録しているURLやHTTPメソッドが間違っている場合ももちろん動作しません。 RSpecを実行してみて、エラーが出るとき、もしそのエラーが実際にAPIにアクセスしているようであれば、stubのURLやHTTPメソッドの指定がうまくいっていないケースが多いです。 Webmockを使用してStubを登録した際の流れとしては下記のようになります。 Stubを登録する テストを実行する テストの中であるURLに対してアクセスをする Stubに登録されたURLと照合して合致すればStubに登録された情報を元にレスポンスを返す(実際のURL先にアクセスはしない) もし合致しなければそのまま実際のURLにアクセスする この流れを覚えておけば、スムーズに実装できると思います。 まとめ 今回はRSpecにおけるWebmockの使用方法についてご紹介しました。 私がこの機能を使用したのは、業務にて外部API連携を実装していて、そのテスト実装に使用しました。 具体的にはAPIが返す値を設定できるのですが、その設定が遅延していたため、stubを使用してシステムを先に構築しようと言うことになったために実装するというものでした。 レアケースかもしれませんが、外部APIのテストなどに使用するケースはあると思います。 皆さんの業務の一助になれば幸いです。 初めての投稿で拙いところもあったと思いますが、今後も繰り返し投稿していきますのでよろしくお願い致します。 The post RSpecにおけるWebmockを使用したstubの使い方 first appeared on miracleave Tech Blog .
記事作成から1年以上経過しています。 内容が古い可能性があります。 AWS で EC2 インスタンスを監視する 以下の監視構成を構築する。 監視 Instance監視 Disk容量 Service監視 通知 メール通知 SMSショートメール セルフヒーリング 自動再起動 目次 インスタンス作成 カスタムメトリクスの取得 CloudWatchのアラーム設定 通知設定 再起動設定 インスタンス作成 検証用にインスタンスを作成する。 AmazonLinux でEC2インスタンスを起動 > httpdをinstall > port:80を許可する > welcomeページの表示を確認する。 完了。 カスタムメトリクスの取得 以下の項目はCloudWatchのデフォルトのメトリクスでは監視できないので、カスタムメトリクスとしてデータを取得する。 Disk容量 Service監視 カスタムメトリクスを取得し、CloudWatchに送信するスクリプトを作成する。 まずはcliで操作するためのアカウントと資格情報を取得する。 カスタムメトリクス用のアカウント作成 IAM > ユーザー > ユーザーを追加 ユーザー名(今回は CustomMetrics とする)とアクセスの種類( プログラムによるアクセス )を入力する。 CustomMetrics ユーザーに必要な権限を付与する。 今回は 既存のポリシーを直接アタッチ から CloudWatchFullAccess を付与する。 ※ 必要に応じて最小の権限を付与することを推奨します。 必要に応じてタグを追加する(今回は付与しない)。 内容を確認し、問題がなければユーザーを作成する。 CSVをダウンロードし、アクセスキーIDとシークレットアクセスキーを控えておく。 スクリプトから読み込むためにファイルに保存しておく。 # 監視スクリプトの領域を作成 mkdir -p ~/Bashdir/customMetrics cd ~/Bashdir/customMetrics # アクセスキー情報をファイルに保存する echo "AWSAccessKeyId=xxxxxxxxxxxxxxxxxxxx" > credential echo "AWSSecretKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" >> credential アカウント作成およびアクセスキー情報の取得完了。 Disk容量監視設定 ディスクの使用率が既定値以内に収まっているか監視する。 参考 Amazon EC2 Linux インスタンスのメモリとディスクのメトリクスのモニタリング – Amazon Elastic Compute Cloud 準備 ### root 実行 ### sudo -i # 必要モジュールインストール yum install -y perl-Switch perl-DateTime perl-Sys-Syslog perl-LWP-Protocol-https perl-Digest-SHA exit ### ec2-user 実行 ### # 監視ツールを取得 cd ~/Bashdir/customMetrics wget http://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.1.zip unzip -q CloudWatchMonitoringScripts-1.2.1.zip rm -f CloudWatchMonitoringScripts-1.2.1.zip touch disk_check.sh chmod +x disk_check.sh vi disk_check.sh ディスク容量をチェックするスクリプトを作成する。 #!/bin/bash SCRIPT_DIR=/home/ec2-user/Bashdir/customMetrics/aws-scripts-mon # --disk-path は監視対象のディスクの分だけ渡す ${SCRIPT_DIR}/mon-put-instance-data.pl --disk-space-util --disk-path=/ --disk-path=/data --aws-credential-file=/home/ec2-user/Bashdir/customMetrics/credential --from-cron cronに登録 # 毎分実行する場合の設定 * * * * * /home/ec2-user/Bashdir/customMetrics/disk_check.sh 1>/dev/null ディスク容量のカスタムメトリクスの準備が完了。 あとはこのメトリクスの内容に従ってアラームを設定する。 アラームの設定は後述 Service監視設定 サービスが稼働しているか監視する。 cd /home/ec2-user/Bashdir/customMetrics touch service_check.sh chmod +x service_check.sh vi service_check.sh #!/bin/bash CUR_DIR=/home/ec2-user/Bashdir/customMetrics export JAVA_HOME=/usr/lib/jvm/jre export AWS_CLOUDWATCH_HOME=/opt/aws/apitools/mon export EC2_REGION=ap-northeast-1 export AWS_CREDENTIAL_FILE=${CUR_DIR}/credential InstanceId=`cat /var/tmp/aws-mon/instance-id` # HTTP Healthcheck URL=https://staging.pms-colon.jp/pms-cloud/Id001/show.action WORD="<title>ログイン|Pearl Colon</title>" COUNT=`curl $URL | grep "${WORD}" | wc -l` echo $URL:$COUNT /opt/aws/bin/mon-put-data --metric-name HTTP_SERVICE_CHECK --namespace "CustomMetrix" --dimensions "InstanceId=${InstanceId}" --value ${COUNT} ※ HTTPSのリクエストを送信しているため、セキュリティグループなどは合わせて修正する。 cronに登録 # 毎分実行する場合の設定 * * * * * /home/ec2-user/Bashdir/customMetrics/service_check.sh 1>/dev/null CloudWatchのアラーム設定 CloudWatch > アラーム > アラームの作成 > メトリクスの選択 監視するメトリクスを選択する(今回はディスク容量) 統計を 最大値 、条件を 静的 , より大きい , 80 で設定する。 通知先を PMS_miracleave に設定する。 必要に応じて再起動のEC2アクションを設定する アラームに適切な名前を設定する。 内容を確認し、問題がなければ アラームの作成 ボタンでアラームを作成する。 通知設定 SNSでトピックとサブスクライブを設定する。 CloudWatchの作成時にサブスクライブが作成されているので、対象のメールアドレス来たメールからサブスクライブを承認する。 設定が完了したら通知が飛ぶかチェックするために stress-ng コマンドでCPU負荷をかけてみる。 $ yum install -y stress-ng $ 再起動設定 CloudWatchのEC2アクションに再起動を設定する。 カスタムメトリクス EC2初期設定 – Qiita The post [AWS] CloudWatch で EC2 インスタンスを監視する first appeared on miracleave Tech Blog .
はじめに こんにちは! 現在私はPythonとDjangoを使用した案件に携わっております。 業務で担当となったバッチの作成に「データレコードをCSV形式で生成しそれを他のテーブルのとあるカラムに値に設定する」という処理がありました。私自身ここの処理が上手く実装できずに苦労したので備忘録的な感じで今回投稿します。 筆者について 高校・大学でプログラミングをかじり、2021年の4月からmiracleaveに入社した新卒2期生です。 入社後は運用保守チームで開発・改修を行い、現在はPythonとDjangoの案件に参画しています。 今回の完成形・ゴール class CsvDataCreate(BatchLogic): # 商品情報をcsv編集登録 def __init__(self, *args, **options): super().__init__(*args, **options) @transaction.atomic() def handle(self, *args, **options): fruit_data = Fruit.object.get(name=apple) csv_info_list = [] csv_info_obj = CsvObject() csv_info_list = csv_data_obj.csv_info(self, fruit_data) fruit_info_create = [val for val in csv_info_list.__dict__.values()] fruit_data = store( fruit=','.join(map(str, fruit_info_create)) ) fruit_data.save() class CsvObject(): def __init__(self): self.code: str # 商品コード self.name: str # 商品名 self.explanation: str # 商品説明 self.price: str # 商品価格 self.create_at: str # 作成日時 self.update_at: str # 更新日時 self.create_user: str # 作成者 self.update_user: str # 更新者 def csv_info(self, fruit_data): self.code = fruit_data.code self.name = fruit_data.name self.explanation = fruit_data.expanation self.price = fruit_data.price self.create_at = fruit_data.create_at self.update_at = fruit_data.update_at self.create_user = fruit_data.create_user self.update_user = fruit_data.update_user return self 今回の実装のゴールはFruitテーブルの1レコードの各カラムの値をcsv形式の文字列にして、Storeテーブルのfruitのカラムに登録するのがゴールです。下記のテーブルのようなイメージです。 fruitテーブル id code name explation price create_at update_at create_at update_at 1 123456 apple 青森産で凄く甘い 1000 2021/01/01 2021/02/01 Taro Hanako 2 987654 banana エクアドル産で大きい 100 2021/01/01 2021/02/01 Hiroshi Satoshi storeテーブル id store_name rice bread fruit water beer ice_cream sweet_treat 1 東京支店 あきたこまち 国産もち米 123456,”apple”,”青森産で凄く甘い”,1000,”2021-01-01″,”2021-02-01″,”Taro”,”Hanako” 南アルプス ドライビール バニラ クッキー 2 大阪支店 玄米 メロンパン 987654,”banana”,”エクアドル産で大きい”,100,”2021-01-01″,”2021-02-01″,”Hiroshi”,”Satoshi” 北アルプス ビール 抹茶 チョコレート csv形式データ作成(準備) class CsvObject(): def __init__(self): self.code: str # 商品コード self.name: str # 商品名 self.explanation: str # 商品説明 self.price: str # 商品価格 self.create_at: str # 作成日時 self.update_at: str # 更新日時 self.create_user: str # 作成者 self.update_user: str # 更新者 def csv_info(self, fruit_data): self.code = fruit_data.code self.name = fruit_data.name self.explanation = fruit_data.expanation self.price = fruit_data.price self.create_at = fruit_data.create_at self.update_at = fruit_data.update_at self.create_user = fruit_data.create_user self.update_user = fruit_data.update_user return self まずcsv形式で生成するデータ準備段階としてCsvObjectという名前のクラスを宣言します。次にcsv_infoという名前のメソッドを定義し、 fruitテーブルの各カラムに、Storeテーブルのfruitに登録したい値を入れます。 fruit_dataが不意に登場していますが何者かというと条件を指定して取得したレコードです。こちらは次のところで説明したいと思います。 csv形式データ作成(実行) class CsvDataCreate(BaseLogic): # 商品情報をcsv編集登録 def __init__(self, *args, **options): super().__init__(*args, **options) @transaction.atomic() def handle(self, *args, **options): fruit_data = Fruit.object.get(name=apple) csv_info_list = [] csv_info_obj = CsvObject() csv_info_list = csv_data_obj.csv_info(self, fruit_data) fruit_info_create = [val for val in csv_info_list.__dict__.values()] ここからcsv文字列に変換したいと思います。最初にFruitテーブルの中でcsv形式にしたいレコードを条件を指定し、変数に入れます。今回はappleのレコードを選択したいと思います。このappleのレコードが格納されている変数( fruit_data )が3の csv_info の引数となります。 次に CsvObject() クラスとその中のメソッドを順々に 変数に入れていきます。そしてその変数( csv_info_list )を for文でぐるぐるまわし fruit_info_create に値を代入していきます。ここでのポイントが __dict__.values() を使用することです。これは簡単にいうと、_dict__属性の values メソッドを使用すれば全プロパティの値だけ取得することができます。このメソッドを使わないと値だけが欲しいのにオブジェクトが返ってきてしまいcsv形式の文字列にはできないないので、ここに注意しましょう。 またエディターの debug 機能もしくはprint()で fruit_info_createを確認すると以下のようにリストになっていれば成功です ['123456','apple','青森産で凄く甘い','1000','2021-01-01','2021-02-01','Taro','Hanako'] データベース登録 fruit_data = Store( fruit=','.join(map(str, fruit_info_create)) ) fruit_data.save() ここでStoreテーブルのfruitというカラムに、3と4で準備・実行して生成されたデータをデータベースに登録します。’,’をつけることで、csv形式のコンマ区切りにすることができます。map関数は、map(使用したい関数, 関数を使用したいオブジェクト)という形式で書いていきます。数値を文字列化するstr関数を、オブジェクト fruit_info_create に対して使いたいので、map(str, fruit_info_create )と書き、リストの要素を連結するjoinを使用して連結させましょう。 最後にfruit_dataをsave()をすればStoreテーブルの東京支店のfruitカラムにcsv形式の文字列が値としてコミットされ、冒頭にお見せしたテーブルのようになります。 一通りの実装はここまでです。お疲れ様でした。 おわりに いかがでしたしょうか。ある程度Python/Djangoを経験したエンジニアからしたらもっと良い実装方法であったり、カンタンに実装できる内容だったかもしれないです。ですが私自身はじめにで記載した通り、ここの実装で大変苦労し、自分の知識の無さを痛感させられ心が折れそうになりました…(笑) なので今回の記事は初学者向け・駆け出しエンジニア向けということで、少しでも参考になれば幸いです。 The post PythonでデータレコードをCSV形式に変換・登録 first appeared on miracleave Tech Blog .
記事作成から1年以上経過しています。 内容が古い可能性があります。 皆さんは、ご存じでしょうか?? アンドロイドには知られざる2つの裏メニューがある事を… 男のロマンとも言える隠しコマンドですが、社長がAndroidのキオスクモードについて投稿されていたので、触発され佐々木も隠しコマンドについて紹介させていただきたいと思います。 アンドロイドの裏メニューの入り方 さて、それではアンドロイドの裏メニューの入り方を早速見て行きましょう。 アンドロイドの隠しコマンドと隠し操作 アンドロイドの裏メニューへと入るための隠しコマンドとその操作を解説しますね。 電話発信画面にて、 *#*#4636#*#* を入力してみてください。 すると以下のメニュー画面?が表示されるはずです。 携帯電話情報 電池情報 使用統計情報 WiFi information そうです。これが裏メニューの正体です! 裏メニュー項目の説明 携帯電話情報 こちらの裏メニューには自身のアンドロイドの電話番号は勿論、他にも以下のような情報が確認できます。 IPアドレス ホスト名 HTTPクライアントテスト 電波強度 GSMサービスの有無 ネットワークの種類 電池情報 こちらの裏メニューでは、電池残量の他にも以下のようなの情報を確認できます。 電池残量 蓄電池電圧 電池温度 電池技術 電池の状態 使用統計情報 こちらの裏メニューでは、自身のアンドロイドにおいてのアプリの使用回数や使用時間などを確認できます。 これは各アプリごとの情報を確認できるので、他人のAndroidでやると恥ずかしいことになりそうですね… 社内のメンバーは大体がiPhoneユーザーなので意味なしかもしれませんが… Wi-Fi information こちらの裏メニューは、自身のアンドロイドのWi-FiのAPKを直接実行できるらしいです。 ですが、中には実行する事によってアンドロイドに危険を及ぼす内容もあるみたいなので もし、実行する時は必ず細心の注意を払った上で、自己責任で実行しましょう。 まとめ アンドロイドには、知られざる裏メニューが存在する事が分かって頂けたと思います。 また、アンドロイドの魅力は使い勝手が良い事だと思っております。 この、記事を読んで下さったあなたにアンドロイドの良さが伝わって頂ければ嬉しい限りです。 ちなみに私はiPhoneユーザーです。 それでは、最後まで読んだ頂きありがとうございました。 The post [Android]隠しコマンドが存在した! first appeared on miracleave Tech Blog .
はじめに こんにちは! JP1を利用している際、呼び出した処理の結果によってジョブの正常終了/異常終了を判定させることがあります。 プロジェクトによってどのような形式で処理の結果を返すかはそれぞれだと思うのですが、多くの場合は単純にリターンコードを返しているのではないでしょうか? 0:正常終了 9:異常終了 1:警告終了 みたいな。 そんな中、「JSONで返されることになったけど、どうやって処理結果を取ればいいの?」と詰まった方いませんか? この記事は次のことが知りたい方へ向けた内容となっています! ・JSON形式のデータから値を取得する方法 ・JP1で呼び出した処理結果でジョブの正常終了/異常終了を判断する方法 筆者について 弊社運用保守チームに所属しています。 これまで数多くのプロジェクトに携わってきた中で、JP1やSystemWalkerといったジョブ管理のツールを使った経験があります。 この度、当記事のような仕様で処理結果の判定を対応したため、備忘の意味も含め残しておきます。 JP1 って? ここでは簡単に触れておくだけにしておきます。 JP1 とは、日立製作所が開発・販売している、企業のITシステムの運用管理ソフト。IT資産の管理や稼動状況の把握、定型業務の自動化、セキュリティ対策などを統合的に行うことができる。1台から数千台まで様々な規模のシステムに導入することができ、必要に応じて拡張していくことができる。 引用元: IT用語辞典 e-words より 色々機能がありますが、 「ジョブ管理」 で使うことが多いかと思います。 “タスクスケジューラやcronが発展したツール”と考えるとわかりやすいかもしれません。 スケジューリングされた処理をいくつも順序をつけて起動することができたり、Windows・Linuxといった異なるプラットフォームにまたがった処理も連動させることができます。 処理結果の判定 結論から書くと、JSON形式の戻り値でジョブの正常終了/異常終了を判定するのは次の方法で可能です。 jqコマンドを使って、JSONから”処理結果”の値を取得する 取得した値を必要に応じJP1の終了コードに変換する これだけでOKです! 前提としては、JSONのどの値を処理結果として扱うのか、プロジェクトで先に決めておきましょう。 なお、JP1では「0:正常終了」「0以外:異常終了」としています。 jqインストール jqとはJSONから値を抜き出したり、集計、整形などができるツールです。 https://stedolan.github.io/jq/ マニュアルはこちら。 http://stedolan.github.io/jq/manual/ まずは処理を呼び出す環境にjqをインストールし使えるようにします。 CentOSだと以下のように2行のコマンドだけでさくっとインストール完了です。 $ sudo yum -y install epel-release $ sudo yum -y install jq Windowsの場合は公式ページからexeファイルをダウンロードし、環境変数Pathにexeを配置したフォルダを追加してあげればOKです。 jqインストールや使用方法の詳細については、他に紹介しているサイトがあるので気になった方は探してみてください。 今回のサンプル 次は実際にJSONから値を取得する方法です。 ここでは以下の例を使います。 JP1ジョブからshellでバッチ処理呼び出しを行う バッチ処理はPythonで実装。戻り値をJSON形式で返す shellは戻り値のJSONから処理結果を取得し、JP1の終了コードに変換する 変換された終了コードでJP1は正常/異常終了を判定する test.sh #!/usr/bin/env bash #実行するバッチ処理 RUN="python3 test.py" #バッチ実行→戻り値のJSONからstatus取得 STATUS=$(${RUN} | jq -r '.status') #ステータス判定 if [ "$STATUS" = "True" ]; then exit 0 else exit 9 fi test.py import json JSON_DEMO = '{"message":"null","result":[{"address1":"東京都","address2":"新宿区","address3":"新小川町","kana1":"トウキョウト","kana2":"シンジュクク","kana3":"シンオガワマチ","prefcode": "13","zipcode": "1620814"}],"status":"True"}' data = json.loads(JSON_DEMO) print(json.dumps(data, indent=2)) JP1のジョブ定義 JP1のジョブ定義 test.shの以下でjqを使用してJSONから値を取得しています。 #バッチ実行→戻り値のJSONからstatus取得 STATUS=$(${RUN} | jq -r '.status') バッチの戻り値JSONをjqコマンドの標準入力として渡してあげます。 「’.status’」でJSONの中から「status」の値を取得できます。 最初の「.」はルートを意味しており、続けてプロパティーを指定することで、その値が出力される仕組みです。 またオプションの「-r」は、結果が文字列の場合にJSON形式ではなく、文字列を直接出力してくれるものです。 今回の場合、「”status”:”True”」をオプション無しで取得すると「”True”」となります。 取得後にステータス判定をする際、ダブルクォートが邪魔なのでオプションを指定して文字列「True」として出力しています。 取得した値で処理結果を判定 前述した通り、JP1では終了コードが「0:正常終了」「0以外:異常終了」となっています。 なので例えば、取得したstatusが「True」の場合0、それ以外は9を終了コードとするように分岐させてあげればOKです。 問題なく実装されていると、こんな感じでジョブの実行結果を判定することができます。 “status”:” True “の場合 JP1 ジョブ実行結果 “status”:” False “の場合 JP1 ジョブ実行結果 まとめ いかがだったでしょうか? JP1はネットに情報があまりなく、公式ページにあるマニュアルもかなりのボリュームなので、欲しい情報を探すことが大変な場合がたびたびあります。 今後も構築・設定時に手こずった点や、マニュアルから読み解くのが難しい手順など、同じように困った方の役に立つ記事を残していければと思います! The post 【JP1】バッチの戻り値がJSONだったらどうする!?処理結果の取得とジョブの終了判定方法まとめ first appeared on miracleave Tech Blog .