2018/12/16

GCP: IoTデータ分析環境立ち上げ on GCP

Goal:ローカルPCをIoTGateway端末と見立てて、Bigqueryに、気温データをストリーミングインサートする。利用するサービスは、IoT Core --- Pub/Sub --- Dataflow --- Bigquery と連係する。
Gateway側には、データをPushする処理が必要だが、それ以外は、コーディング不要!

How
0. 準備:仮想IoTGateway として、気温/計測時間/デバイスIDを送るプログラムを作成
https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/iot/api-client/mqtt_example
をローカルPCにクローンして、Pythonの環境などをセットする。
cloudiot_mqtt_example.py を加工。変更箇所は、以下の通り。
### line 265−266を変更する
# もとのソース
# payload = '{}/{}-payload-{}'.format(
# args.registry_id, args.device_id, i)
# import pytz も合わせて実施すること
# 気温を乱数でセット
temp = str(round(random.uniform(0, 15),2))
# 計測時間をセット
t = str(datetime.datetime.now(pytz.utc).strftime("%Y-%m-%d %H:%M:%S"))
# payload内にtemprature, timecollected, deviceID をセット
payload = u'{"temperature": "' + temp + u'", "timecollected": "' + t + u'", "deviceID": "' + args.device_id + u'"}'
view raw iotdemo.py hosted with ❤ by GitHub


1. Pub/Subのトピックを作成
(1)APIを有効にする
(2)トピックを作成する
トピックとは、メールボックスみたいなもの




2. デバイスをIoT Coreに登録する
(1)APIを有効にする
(2)端末レジストリを作成する
端末レジストリとは、デバイスのグループを作成すること
トピックの選択が必要。1で作成したトピックを選択する。
そうすると、この端末レジストリ内のデバイスから送られてきたメッセージは、そのトピックに投げ込まれる。
(3)端末を作成する(デバイスを登録する)
公開鍵の登録は一旦せずにデバイスを作成する。
公開鍵の種類は、 RS256_X509 とする。


3. 認証鍵の作成と登録
(1)デバイス側で、Google root certificate を取得する
wget https://pki.goog/roots.pem
あるいは、
curl https://pki.goog/roots.pem > roots.pem
で取得する
(2)鍵のペアを作成する
openssl req -x509 -newkey rsa:2048 -keyout rsa_private.pem -nodes -out rsa_cert.pem -subj "/CN=unused"
(3)公開鍵を、IoT Core のデバイスに貼り付ける
(4)private key は、ローカルマシンに保存

4. サブスクライバーのを登録する
デバイスが、パブリッシャーなので、そのトピックの購読者を登録する。
ここでは、Bigqueryにセンサーの値を書き出すので、エクスポート機能を使う。
登録すると、自動的にCloud DataflowのJobが立ち上がる。
(1)Bigqueryに、データを登録するためのテーブルを登録する

(2)トピックのエクスポート登録を行う





5. テスト実行!!
デバイスを稼働させて、データがBigqueryに流れ込むのを確認する。


$ python iotdemo.py --cloud_region=us-central1 --project_id=iotdemo1 --algorithm=RS256 --private_key_file=rsa_private.pem --registry_id=demo-reg --device_id=iotdemo



Bigquery側は。。。。
成功!!
実に簡単に、分析環境の構築が可能。

2018/11/18

GCP: Cloud Shell上でのサンプルコマンド

備忘録
Cloud Shell上でのオペレーション

### Storageの操作
### GCE関連、Snapshotの作成
### Storageの操作
# Google Storageのバケットを作成する
# gsutil mb gs://<bucket name>
$ gsutil mb gs://test-toshi
Creating gs://test-toshi/...
# Cloud shell から storage に コピーする
$ gsutil cp test.data gs://test-toshi
Copying file://test.data [Content-Type=application/octet-stream]...
- [1 files][ 19.0 B/ 19.0 B]
Operation completed over 1 objects/19.0 B.
### GCE 関連の操作
# GCEのリストを表示する
$ gcloud compute disks list
NAME ZONE SIZE_GB TYPE STATUS
toshi-vm us-central1-f 10 pd-ssd READY
# Snapshotを作成する
# gcloud compute disks snapshot <GCE name> --zone=<ZONE name> --snapshot-names=<snapshot name>
$ gcloud compute disks snapshot toshi-vm --zone=us-central1-f --snapshot-names=test
Creating snapshot(s) test...done.

2018/10/14

GCP: Google App EngineのランタイムPython3.7を使ってみる2 -- Rest API

前回メモ(hello world with Python3.7)の続編。Restサービスの立上げ。
App Engine APIs が使えなくなっているので、代わりにGCPのPython用のライブラリを使う。(例えば、Datastoreの読み書きにndbは使えない。)

  • Goal
    GAE(Google App Engine) + python3.7ランタイム上にREST API(メソッドはPOST)を作成する。
    APIが呼び出されたら、GCP(Google Cloud Platform)のDatastoreに新規Entity(レコード)を追加する。
  • case
    名前、点数、教科名をjsonでPOSTしたら、GCPのDatastoreに書き込みして、Keyを返信する。
  • How
    1. 開発前準備
    1)開発環境に、google-cloud-datastoreをインストール
    2)
    GOOGLE_APPLICATION_CREDENTIALS 環境変数を設定
    あくまで、ローカルでテストするために必要。
    以下コマンドを打つと、betaコンポーネントのダウンロードを聞かれる。
    「Y」を入力すると、ダウンロードされて環境変数の設定までしてくれる。
    $ gcloud beta auth application-default login

    2. requirements.txt の中身。google-cloud-datastoreも追加すること。

    # This requirements file lists all third-party dependencies for this project.
    #
    # Run 'pip install -r requirements.txt -t lib/' to install these dependencies
    # in `lib/` subdirectory.
    Flask==1.0.2
    google-cloud-datastore==1.7.0


    3. main.py の中身。

    # -*- coding: utf-8 -*-
    # Import the Flask Framework
    from flask import Flask, request, jsonify, abort
    from google.cloud import datastore
    import datetime
    app = Flask(__name__)
    # rootにアクセスされた場合のコントロール
    @app.route('/')
    def hello():
    """Return a friendly HTTP greeting."""
    return 'Hello!' # abort(402) -- abortにしてもよい
    # 今回は、/addtest を Postで呼び出すという想定
    @app.route('/addtest', methods=['POST'])
    def runaddtest():
    # jsonがなかったり、Nameがなければ、400で返す
    if not request.json or not 'name' in request.json:
    abort(400)
    # 認証
    datastore_client = datastore.Client(project='<project name>')
    # Kind名を設定--- テーブル名みたいなもの
    kind = '<kind name>'
    # KEYを作成−−− このケースは、自分で設定せずに、GCPがKEYを作成
    item_key = datastore_client.key(kind)
    # それぞれの要素をjsonからパース
    item = datastore.Entity(key=item_key)
    item['name'] = request.json['name']
    item['points'] = request.json['points']
    item['subject'] = request.json['subject']
    item['creationdate'] = datetime.datetime.now()
    # datastoreに登録する
    datastore_client.put(item)
    # 返信用のjson作成。登録したEntityのKeyを返す
    replymes = {
    'id': item.key.id
    }
    # json と STATUS 201を返す
    return jsonify({'result': replymes}), 201
    @app.errorhandler(404)
    def page_not_found(e):
    """Return a custom 404 error."""
    return 'Sorry, Nothing at this URL.', 404
    @app.errorhandler(500)
    def application_error(e):
    """Return a custom 500 error."""
    return 'Sorry, unexpected error: {}'.format(e), 500
    # For local testing
    if __name__ == '__main__':
    # This is used when running locally only. When deploying to Google App
    # Engine, a webserver process such as Gunicorn will serve the app. This
    # can be configured by adding an `entrypoint` to app.yaml.
    app.run(host='127.0.0.1', port=8080, debug=True)

  • Result --- curlのサンプルと結果
    Toshiのhistoryが67点


    $ curl -i -H "Content-Type: application/json" -X POST -d '{"name":"toshi","points":67,"subject":"history"}' https://.appspot.com/addtest
    HTTP/2 201 
    content-type: application/json
    x-cloud-trace-context: 4140694e3538666bb96627febc6130e4;o=1
    date: Sun, 14 Oct 2018 14:08:21 GMT
    server: Google Frontend
    content-length: 35
    alt-svc: quic=":443"; ma=2592000; v="44,43,39,35"
    {"result":{"id":5635703144710144}}



GCP: Google App EngineのランタイムPython3.7を使ってみる1 -- Hello World

GAEのStandard Environment に、Python3のランタイムがbeta版でリリースされていたので使ってみる。SecondGenerationというらしい。OPENCVかPillowが使えるかどうか?までテストする予定。まずはHello Worldまで。
https://cloud.google.com/appengine/docs/standard/python3/
  • Goal
    GAEのStandardEnvironmentにおいて、Python3.7のランタイムを使ってHelloWorldする。
  • How
    1. app.yaml, main.py, requirement.txt を用意する。サンプルは以下。
      https://github.com/pumpkinpietea/py37.git
    $ ls -lt
    total 32
    -rw-r--r--@ 1 Toshi_Admin  staff  817 Oct 14 11:22 app.yaml
    -rw-r--r--  1 Toshi_Admin  staff  101 Oct 14 10:08 README.md
    -rw-r--r--@ 1 Toshi_Admin  staff  956 Oct 14 01:17 main.py
    -rw-r--r--@ 1 Toshi_Admin  staff  197 Oct 14 00:11 requirements.txt
    2. ローカルでテスト
         $ pip install -r requirements.txt
         $ python main.py
    3. deploy

          $ gcloud app deploy ./py37/app.yaml


  • Comment
    1. libフォルダーに、pip -t でインストールは不要。逆にすべてrequirements.txtに記入する必要がある。
    2. ローカルテスト用のdev_appsever.py は、使えない。
      逆に普通に、local で実行すればよい。便利になった!
    3. deploy は、gcloud コマンドで実施が必要、appcfg.py は、使えない。
    4. 普通のpython3をそのままGAE上で動かす事を狙っているようなので、Cとかのライブラリも動くと思われる。別途テスト予定。

2018/10/13

3ヶ月の使い方で人生は変わる 佐々木大輔 ー 本

メモ
 1.ある意味「いらない」と言われていること自体が業界のニッチな状況を作る参入障壁となっている。p57 --- 問題の本質が見えにくくなることはよくあり、Userにいらないと言われたとしても、本当に価値があるかどうかまでUserがわかっている訳ではない。
 2.「これとこれを組み合わせるだけ」=イノベーション p61
 3.長期的なゴールも、3ヶ月ごとのテーマ設定が肝心
 4.まず考えるべきは「理想」や「本質的な価値」。自分の能力や、できることにとらわれる必要はない。理想を軸に考える癖をつければ、自分の能力を自分で制限することはなくなる。P71
 5.目標は自分がコントロールできること。ゴールは、「売上100万円(達成目標)」ではなく、「クライアントへの訪問回数20回(行動目標)」というように自分がやることに的を絞る。P73
 6.グーグルで働きながら、インターネットやAIを中心とするテクノロジーの活用で日本のすべてのビジネスをアップデートできるのではないか、という思いが強くなっていった。P76 
 7.長期的なゴールは、「世の中にどれだけ貢献できるか」p79
 8.どんな条件より「ストーリー」が大切。誰もが納得できる「腹落ち感」が欠かせない。p87
 ・誰に対して、何がしたいのか?
 ・それを実現できたら何がおきるのか?
 ・それにはどんな意味があるのか?
 9.意思決定の場を振り分ける「それは自分で決めたらいいんじゃない」「それは、あのチームの確認だけ取ってすすめる」「それは難しいから、だれを集めてミーティングしてきめよう」p95
 10.「他人の目を気にすると時間を奪われる」P102
 11.「この文書はわかりやすいか?これを読んだ人は行動してくれるか?」mail p111

平積みされてて、帯みて購入。あまり、3ヶ月の使い方って感じの本ではない。後半は、いわゆる仕事の効率化テクの記述がおおい。

2018/09/13

アマゾン 成毛 眞 ー 本

メモ
  1. ”プライム”マークは、自社で物流している会社でも表示できる。
    (アマゾンの提示するサービスレベルを満たせばもらえる)
  2. FBAサービス: 倉庫+配送業の請負もしてくれる。アマゾンに出店して、楽天に出店して、でも物流はアマゾン頼むとかできる
  3. ヒット商品だと判ると、中抜き・直販をする。結果、どこよりも低価格を出せる。
  4. 低関与商品(なんでもいいや)をダッシュボタンで取り込み。
  5. ADRS: トナーとかがなくなったら自動で発注。IoTのしかけ。
  6. 安い卸からから順番に必要な数になるまで仕入れる。何も考えなくてよい。結果、常にサプライヤから提示されている最安値で買える。サプライヤは安い値段を出す以外、取引ができない。
  7. アマゾンは、地域・商圏に縛られることも、販売促進協力も関係ない。安いものが売れる。(ECとは、そういうことだと納得する)
  8. KIVA: 物流倉庫のロボットは、アマゾンでしか使えないようにした。
  9. 卸の中抜きは安値の基本。2018年2月から、取次を経由するのを止めた。直販にした。
  10. 間接材のECについて、アマゾンサプライ(卸機能)をまずトライする。しばらくしたら、アマゾンビジネス(直販)をスタートした。B2Bの勉強のため?結果、今はアマゾンサプライは停止している。
  11. 配送業務のシェアリング、アマゾンフレックスというサービスもある。荷物を取りに来た、買い物に来たついでに、隣の家の人の荷物を持って帰る
  12. 音声認識は、家庭内のポストスマホとなる。
  13. ベゾスの考え:コミュニケーションを必要とする組織は、きちんと機能していないという証拠でしかない。協調よりも、個のアイデアが優先される組織がよい。

読みやすいのでサクサク行ける。

2018/09/08

silicon valley シリコンバレー

シーズン1〜シーズン4まで一気に見た。やたらF○ckって単語が出てくるのと、下ネタ重視、ちょっと差別的な話も多いけど面白い。あと、1話30分なので、通勤中に見やすいのと、深く考えずに見れるのがよかった。

英語としては、下ネタ系の言い回しを学ぶにはいいのかもしれない(テキトー)。
アマゾンプライムで視聴。

2018/09/02

GCP: GCP外のサーバーからDatastoreへデータをインポートする(GCPのKeyを使う場合)

  • Goal
    タブ区切りのテキストファイルをローカルマシン(OR AWSのEC2でも同じ)GCPのDatastoreにインポートする。pythonのプログラムで実施。

    前のPOSTのKeyを自分で設定しないバージョン

  • Case
    以下のようなテキストファイルを、Datastoreにインポートする。
    想定するのは、DatastoreをGAEのマスタのように利用していて、バッチで更新をするようなケース。keyは、GCPで自動設定されるKeyを使う。
    list.txtの中身(タブ区切り)
    id     shimei   score
    1234   山田      89
    2341   田中      90
    1238   佐藤      81

  • How
    1.GCPのコンソールで、Service Account Keyを作成する
     形式は、JSON
     権限は、DatastoreのOwner(これは、Import&Exportでも良いのかも?)
     作成された、JSONはローカルマシンのどこかに設置する。
    2.Google cloud datastore のクライアントライブラリをインストールする。
     ~$ pip install google-cloud-datastore
    3.pythonのプログラムでインポートする。
      ##utf-8に変換⇒Unicodeに変換して、インポートすること!
       あとで、Pythonから呼び出しをする事を想定している。


    from google.cloud import datastore
    infile = 'list.txt'
    datastore_client = datastore.Client.from_service_account_json('gcp_ds.json')
    kind = 'testscoreNokey'
    with open(infile, 'r') as inputfile:
    inputfile.readline()
    for line in inputfile.readlines():
    i = line.split('\t')
    id = i[0].decode('utf-8')
    shimei = i[1].decode('utf-8')
    score = i[2].decode('utf-8')
    item_key = datastore_client.key(kind)
    item = datastore.Entity(key=item_key)
    item['id'] = unicode(id)
    item['shimei'] = unicode(shimei)
    item['score'] = unicode(score)
    datastore_client.put(item)
  • Result

GCP: GCP外のサーバーからDatastoreへデータをインポートする(keyを自分で設定する場合)

  • Goal
    タブ区切りのテキストファイルをローカルマシン(OR AWSのEC2でも同じ)GCPのDatastoreにインポートする。pythonのプログラムで実施。
    Keyは自分で設定したい。

    Keyを自分で設定する必要がない場合はこちら
  • Case
    以下のようなテキストファイルを、Datastoreにインポートする。
    想定するのは、DatastoreをGAEのマスタのように利用していて、バッチで更新をするようなケース。id をKeyとして登録したい。
    list.txtの中身(タブ区切り)
    id     shimei   score
    1234   山田      89
    2341   田中      90
    1238   佐藤      81
  • How
    1.GCPのコンソールで、Service Account Keyを作成する
     形式は、JSON
     権限は、DatastoreのOwner(これは、Import&Exportでも良いのかも?)
     作成された、JSONはローカルマシンのどこかに設置する。
    2.Google cloud datastore のクライアントライブラリをインストールする。
     ~$ pip install google-cloud-datastore
    3.pythonのプログラムでインポートする。
      ##utf-8に変換⇒Unicodeに変換して、インポートすること!
       あとで、Pythonから呼び出しをする事を想定している。


    from google.cloud import datastore
    # データファイル
    infile = 'list.txt'
    # 認証情報 サービスアカウントキーのJsonを指定する
    datastore_client = datastore.Client.from_service_account_json('gcp_ds.json')
    # datastore のkind名
    kind = 'testscore'
    # ここからメインパート
    with open(infile, 'r') as inputfile:
    inputfile.readline() # 1行目読み飛ばし、項目名なので
    for line in inputfile.readlines():
    i = line.split('\t') # タブ区切り
    id = i[0] # datastore上のKeyとなる
    shimei = i[1].decode('utf-8')
    score = i[2].decode('utf-8')
    item_key = datastore_client.key(kind, id)
    item = datastore.Entity(key=item_key) # Keyとして設定
    item['shimei'] = unicode(shimei)
    item['score'] = unicode(score)
    datastore_client.put(item) # 書き込み
  • Result

2018/08/15

GCP: gcloud のバージョンアップ時のエラーと解消方法 on Windows Subsystem for Linux


  • GAEのFlexible environmentを利用するにあたり、コンソール画面でデプロイしたソースを見れるようにするには、gcloudを195以上にしないと駄目らしい。
  • 188から最新版にUPDATEしようとしたら、エラーが出たので経緯と対応手順メモ
  • 開発環境は、Windows10+Bash on windows(Ubuntu 16.04.3)

以下、ログ

~#
gcloud components update
# 普通にアップデートしようとしたら以下のエラー
ERROR: (gcloud.components.update)
You cannot perform this action because the Cloud SDK component manager is disabled for this installation. You can run the following command to achieve the same result for this installation:
sudo apt-get update && sudo apt-get --only-upgrade install kubectl google-cloud-sdk google-cloud-sdk-datastore-emulator google-cloud-sdk-pubsub-emulator google-cloud-sdk-app-engine-go google-cloud-sdk-app-engine-java google-cloud-sdk-app-engine-python google-cloud-sdk-cbt google-cloud-sdk-bigtable-emulator google-cloud-sdk-app-engine-python-extras google-cloud-sdk-datalab

~# sudo -E apt-get update
# 私の環境では −E が必要
Hit:1 http://archive.ubuntu.com/ubuntu xenial InRelease
Get:2 http://packages.cloud.google.com/apt cloud-sdk-xenial InRelease [6,372 B]
Err:2 http://packages.cloud.google.com/apt cloud-sdk-xenial InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 6A030B21BA07F4FB
(省略)
Reading package lists... Done
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://packages.cloud.google.com/apt cloud-sdk-xenial InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 6A030B21BA07F4FB
(省略)
# よくわからないけど、Public Key が使えないとかなんとか。。。
# Google Groupsのトピによると、以下でKeyを追加せよとのこと

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1326  100  1326    0     0   2062      0 --:--:-- --:--:-- --:--:--  2062
OK

# 再トライ 
~# sudo -E apt-get update
Get:1 http://packages.cloud.google.com/apt cloud-sdk-xenial InRelease [6,372 B]
Hit:2 http://archive.ubuntu.com/ubuntu xenial InRelease
Get:3 http://packages.cloud.google.com/apt cloud-sdk-xenial/main amd64 Packages [45.3 kB]
Hit:4 http://archive.ubuntu.com/ubuntu xenial-updates InRelease
Get:5 http://security.ubuntu.com/ubuntu xenial-security InRelease [107 kB]
Fetched 158 kB in 1s (84.8 kB/s)
Reading package lists... Done

# うまくいった
# つづいて、SDKのUPDATE 余計なパッケージ名もあるけど、そのまま実行

~# sudo -E apt-get --only-upgrade install kubectl google-cloud-sdk google-cloud-sdk-datastore-emulat
or google-cloud-sdk-pubsub-emulator google-cloud-sdk-app-engine-go google-cloud-sdk-app-engine-java google-cloud-sdk-app
-engine-python google-cloud-sdk-cbt google-cloud-sdk-bigtable-emulator google-cloud-sdk-app-engine-python-extras google-
cloud-sdk-datalab
Reading package lists... Done
Building dependency tree
Reading state information... Done
Skipping google-cloud-sdk-app-engine-go, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-java, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-python, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-app-engine-python-extras, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-bigtable-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-cbt, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-datalab, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-datastore-emulator, it is not installed and only upgrades are requested.
Skipping google-cloud-sdk-pubsub-emulator, it is not installed and only upgrades are requested.
Skipping kubectl, it is not installed and only upgrades are requested.
The following package was automatically installed and is no longer required:
  snap-confine
Use 'sudo apt autoremove' to remove it.
Suggested packages:
  google-cloud-sdk-app-engine-java google-cloud-sdk-app-engine-python google-cloud-sdk-pubsub-emulator
  google-cloud-sdk-bigtable-emulator google-cloud-sdk-datastore-emulator kubectl
The following packages will be upgraded:
  google-cloud-sdk
1 upgraded, 0 newly installed, 0 to remove and 155 not upgraded.
Need to get 19.2 MB of archives.
After this operation, 28.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://packages.cloud.google.com/apt cloud-sdk-xenial/main amd64 google-cloud-sdk all 212.0.0-0 [19.2 MB]
Fetched 19.2 MB in 11s (1,652 kB/s)
(Reading database ... 50185 files and directories currently installed.)
Preparing to unpack .../google-cloud-sdk_212.0.0-0_all.deb ...
Unpacking google-cloud-sdk (212.0.0-0) over (188.0.1-0) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up google-cloud-sdk (212.0.0-0) ...

# 完了 
~# gcloud --version
Google Cloud SDK 212.0.0
alpha 2018.08.13
beta 2018.08.13
bq 2.0.34
core 2018.08.13
gsutil 4.33

2018/07/29

リストの要素の重複排除とNone(空要素)の排除 − Python

  • Goal
    リスト型の要素の中の重複排除とNone(空要素)を排除する。
    集合型(set)なら、重複排除は自動でできて、.discardでNoneは排除可能だが、リスト型で行いたい。理由は、リスト内の順番をキープしたいから。
  • How
    if で要素があるかどうか?と長さが0より大きいかを確認する。
    ※filterを使うとか、内包表記を使うとか色々載っていたが、これが一番分かりやすかった。。。
    # -*- coding: utf-8 -*-
    import unicodedata
    inputtext = u'Aaa\nbBbb\n\nCCddff\n\nAaa\n\n'
    inputlist3 = []
    # 全角を半角へ、小文字を大文字へ変換
    itemcode = unicodedata.normalize('NFKC', inputtext).upper()
    # 改行区切りでリストに代入
    inputlist = list(itemcode.replace(' ','\n').replace(' ','\n').split('\n'))
    # 改行区切りでリストに代入 でも、最後の改行は排除
    inputlist2 = list(itemcode.replace(' ','\n').replace(',','\n').splitlines())
    # 重複排除と長さの確認
    for x in inputlist:
    if x not in inputlist3 and len(x) > 0 :
    inputlist3.append(x)
    print "=== inputtext"
    print inputtext
    print "=== after normalize"
    print itemcode
    print "=== normal list splitted by \\n"
    print inputlist
    print "=== normal list with splitlines"
    print inputlist2
    print "=== eliminating duplication and None"
    print inputlist3
  • Result

    ~$ python eliminating_duplication.py
    === inputtext
    Aaa
    bBbb

    CCddff

    Aaa


    === after normalize
    AAA
    BBBB

    CCDDFF

    AAA


    === normal list splitted by \n
    [u'AAA', u'BBBB', u'', u'CCDDFF', u'', u'AAA', u'', u'']
    === normal list with splitlines
    [u'AAA', u'BBBB', u'', u'CCDDFF', u'', u'AAA', u'']
    === eliminating duplication and None
    [u'AAA', u'BBBB', u'CCDDFF']

2018/07/01

GCP: gcloud コマンドで GAEのログを取る方法

備忘録
GAE アプリのログ解析をする場合、Stackdriver logging からログを取り出す必要あり。gcloud コマンドで簡単にできる。



# log のリストを取得
$ gcloud logging logs list
NAME
projects/<project名>/logs/appengine.googleapis.com%2Frequest_log
# GAEのlogを取得する; 取得して見やすくする
$ gcloud logging read 'resource.type=gae_app AND \
logName=projects/<プロジェクト名>/logs/appengine.googleapis.com%2Frequest_log AND \
severity>=INFO' --limit 1 --format json | python -m json.tool
[
{
"httpRequest": {
"status": 200
# GAEのlogを取得する; フィルター付き
# 結果の加工まで含めた処理
# timestamp の文字列を変数にするには、dt=`date --rfc-3339=s --date="1 days ago"|tr ' ' 'T'`
# で、変数にして timestamp>="'"${dt}"'" で指定する
$ gcloud logging read 'resource.type=gae_app AND \
logName=projects/<project名>/logs/appengine.googleapis.com%2Frequest_log AND \
timestamp>="2018-06-29T23:39:34+00:00" AND \ #logの期間を設定
severity>=INFO AND \
"品番が見つかりません"' \ #ログ内の日本語や文字列でフィルターしたければ、””で囲むだけ
--limit 10 \ # 検索結果の表示上限を指定
--format json | \
jq ".[].protoPayload.<parse tag>" | \ # 結果をjq に渡して、パース
sed -e '/<行頭文字>/d' | \ # 不要な行を削除
awk '{print $4}' | \ # スペース区切りの 4列目を取得
sed -e s/,//g > test.log # 不要文字(この場合はコンマ)を削除して、test.logへ出力


2018/05/27

GCP: GAE appcfg.py の使い方

GAEの appcfg.py の使い方。Deploy以外にも使うことがあり、備忘録


# Deployする
~$ appcfg.py update --noauth_local_webserver -A <Project Name> -V <Version Name> <Source directory>
# version の一覧を表示する
~$ appcfg.py list_versions --noauth_local_webserver -A <Project Name>
# ソースをダウンロードする (default のサービスでよい場合)
~$ appcfg.py download_app --noauth_local_webserver -A <Project Name> -V <Version Name> <Source directory>
# ソースをダウンロードする (サービスを指定する場合)
~$ appcfg.py download_app --noauth_local_webserver --module=<Service Name> -A <Project Name> -V <Version Name> <Source directory>

2018/02/25

GCP: GAE上にAPI(POST)を作成ーDatastoreの操作(Create) ー Python



  • Goal
    GAE(Google App Engine)上にREST API(メソッドはPOST)を作成する。
    APIが呼び出されたら、GCP(Google Cloud Platform)のDatastoreに新規Entity(レコード)を追加する。言語・環境はPython+flask。
  • case
    名前、点数、教科名をjsonでPOSTしたら、GCPのDatastoreに書き込みして、Keyを返信する。
  • How
    1:開発環境は、以下でセットアップ
      Ubuntu16.4 + Pyenv:Python2.7.13 on GCE
      GCP: Google App Engine上にPython(Flask)アプリを立ち上げる手順

    2:ライブラリのセットアップ
      app.yaml に、flaskの記述を追加
      - name: flask
        version: 0.12

    3:mainプログラム と curl 結果

    # -*- coding: utf-8 -*-
    # app.yamlに追記すればOK.libで持っていかなくてもよい。
    from flask import Flask,request,jsonify,abort
    # GCPのDatastoreを使うには必要。libで持っていかなくても、GAE上にある
    from google.appengine.ext import ndb
    import datetime
    app = Flask(__name__)
    # DatastoreのEntityの定義
    class test(ndb.Model):
    name = ndb.StringProperty()
    points = ndb.IntegerProperty()
    subject = ndb.StringProperty()
    creationdate = ndb.DateTimeProperty()
    # rootにアクセスされた場合のコントール
    @app.route('/')
    def hello():
    """Return a friendly HTTP greeting."""
    return 'Hello!'#abort(402) -- abortにしてもよい
    # 今回は、/addtest を Postで呼び出すという想定
    @app.route('/addtest', methods=['POST'])
    def runaddtest():
    testrecord = {}
    # jsonがなかったり、Nameがなければ、400で返す
    if not request.json or not 'name' in request.json:
    abort(400)
    # 登録するために、jsonを各項目にパースする
    testrecord = test(
    name = request.json['name'],
    points = request.json['points'],
    subject = request.json['subject'],
    creationdate = datetime.datetime.now()
    )
    # datastoreに登録する
    testrecord.put()
    # 登録したEntityのKeyの値を取ってくる。
    recordid = str(testrecord.key.id())
    # 返信用のjson作成。登録したEntityのKeyを返す
    replymes = {
    'id': recordid
    }
    # json と STATUS 201を返す
    return jsonify({'result': replymes}), 201
    @app.errorhandler(404)
    def page_not_found(e):
    """Return a custom 404 error."""
    return 'Sorry, Nothing at this URL.', 404
    @app.errorhandler(500)
    def application_error(e):
    """Return a custom 500 error."""
    return 'Sorry, unexpected error: {}'.format(e), 500
    $ curl -i -H "Content-Type: application/json" -X POST -d '{"name":"toshi","points":81,"subject":"kokugo"}' https://<project>.appspot.com/addtest
    HTTP/2 201
    content-type: application/json
    x-cloud-trace-context: XXXXXX;o=1
    date: Sun, 25 Feb 2018 03:15:06 GMT
    server: Google Frontend
    content-length: 51
    alt-svc: hq=":443"; ma=000; quic=531; quic=339; quic=338; quic=337; quic=335,quic=":443"; ma=2592000; v="41,39,38,37,35"
    {
    "result": {
    "id": "56765079040"
    }
    }
    view raw test-curl hosted with ❤ by GitHub

    4:Datastoreの結果

  • Thanks!

2018/02/24

Docker CE のディレクトリを引っ越しする方法

AWSのEC2 RHEL7.4 にDocker CEをセットアップする手順 の後に、Rootディレクトリを引っ越しする方法


・システム領域のハードディスクを大量に消費するので、別ディレクトリへ引っ越しする
以下の例は、/var/lib/docker から /xxx/mnt/docker/ へ引越し
0.初期設定確認
1.ServiceSTOP
2.ディレクトリを作ってコピー
3.設定変更
4.ServiceStart


## 0.初期状態確認
$ docker info | grep 'Docker Root Dir'
Docker Root Dir: /var/lib/docker
##RHEL7+Docker-CEの場合の設定ファイルを見ると、”dockerd”
##本設定は、dockerd の場合有効です。
$ sudo cat /usr/lib/systemd/system/docker.service
[sudo] xxxxのパスワード:
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
# Uncomment TasksMax if your systemd version supports it.
# Only systemd 226 and above support this version.
#TasksMax=infinity
TimeoutStartSec=0
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
# restart the docker process if it exits prematurely
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
## 1.Service Stop ー Docker の停止
$ sudo service docker stop
Redirecting to /bin/systemctl stop docker.service
## 2.ディレクトリを作ってコピー
$ sudo mkdir /xxx/mnt/docker
$ sudo cp -r /var/lib/docker /xxx/mnt/docker
## 3.設定変更 - 設定ファイルを作成する
$ cd /etc/docker/         ##これが設定ファイル置き場。Jsonで置くらしい
$ ls
key.json
##ここに、daemon.jsonを作る
$ vi daemon.json
{
"graph": "/xxx/mnt/docker"
}
~
~
~
## 以下のように作成される。
$ ls
daemon.json key.json
##4. Service Start
$ sudo service docker start
Redirecting to /bin/systemctl start docker.service
## Root Directoryが変更されているので成功!!
$ docker info | grep 'Docker Root Dir'
Docker Root Dir: /xxx/mnt/docker
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
httpd latest 7239615c0645 7 weeks ago 177MB

2018/02/11

GCP: GAE(Google App Engine)のバージョン別のURL

GAEは、バージョン別に個別のURLをもっている。
なので、同時に複数バージョンを公開してテストできる。
知らなかった。。。

サンプル

https://"バージョン名"-dot-"プロジェクト名".appspot.com/

GCP: Google App Engine上にPython(Flask)アプリを立ち上げる手順



  • Goal
    開発環境も何も無い状態から、GAE(Google App Engine)上にFlaskアプリ(Hello World)を30分以内に立ち上げる。
    GAEは、Standard Environmentなので、Pythonは、2.7
  • How
    1. GCP上に新プロジェクト作成(xxxxx-test−0001) ⇒ 手順割愛
    2. GCP上で、GAEを有効にする。 ⇒ 手順割愛
      初めてのアプリ作成で、Pythonを選ぶ。
      チュートリアルはやらなくて良いので、途中で抜ける。
      1プロジェクトで、1GAEアプリしか持てない。
    3. GCP上に新VMインスタンス(Ubuntu16.4)作成(dev001) ⇒ 手順割愛
      TYPEはMicro(無料マシン)でOK。
      別にローカルマシンがあればそれでもOK。
    4. VM(dev001)の設定 ー 開発環境構築
        4-1. 初期設定 + Pyenv + GAEのSDKの導入
          以下のファイルを実行
       
         ~$ . UbuntuSetupForGAE.sh
    #! /bin/bash
    #update and upgrade
    sudo apt-get update
    sudo apt-get -y upgrade
    #install - I may put unnessary package
    sudo apt-get install -y git gcc make openssl build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev xz-utils libgtk2.0-dev pkg-config unzip
    #Set up Pyenv and GAE SDK
    git clone https://github.com/yyuu/pyenv.git ~/.pyenv
    echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
    echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
    echo 'eval "$(pyenv init -)"' >> ~/.bashrc
    git clone https://github.com/pyenv/pyenv-virtualenv.git ~/.pyenv/plugins/pyenv-virtualenv
    echo 'eval "$(pyenv virtualenv-init -)"' >> ~/.bashrc
    #Please select version
    wget https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.66.zip
    mkdir bin
    cd bin
    unzip ~/google_appengine_1.9.66.zip
    cd
    echo 'export PATH="$PATH:$HOME/bin/google_appengine"' >> ~/.bashrc
    exec $SHELL -l

        4-2. Localに開発用フォルダの作成とPyenvのセットアップ      
           
    # 開発を行うディレクトリで操作すること
    # 必要なファイルを取ってくる ー GAEへのデプロイに必要なファイル
    git clone https://github.com/pumpkinpietea/GAEdevelopping-with-Flask.git
    # PYTHONの環境を作成
    pyenv install 2.7.14
    pyenv virtualenv 2.7.14 GAEFlask
    cd ./GAEdevelopping-wtih-Flask
    pyenv local GAEFlask
    # 必要なライブラリを開発を行うディレクトリ内のlibディレクトリにインスト−ルする。
    # そうすると、Deploy時に一緒に持っていく
    pip install -r requirements.txt -t lib

    5. Deploy
      localでのテスト。main.pyがあるディレクトリで以下を実行
          $ 
    dev_appserver.py .
     
       Deploy。 main.pyがあるディレクトリで以下を実行する
          $ appcfg.py update --noauth_local_webserver -A "project id" -V "version" .

    6. 確認する。以下のURLにアクセスする。
      
    https://”projectid”.appspot.com
         



  • Notes
    これを使って、LineのBotなどマイクロサービスを立ち上げれる
    main.pyの編集と必要なlibのインストールが必要
  • Thanks!!