« 2016年10月 | メイン | 2017年4月 »

2016年12月

2016年12月27日 (火)

UDP双方向通信を実装しやすくなったソラコムBeam

エンジニアの佐藤です。こんにちは。

今回は12月22日にソラコムBeamに追加された機能「SORACOM Beam のUDP、TCP エントリポイントでステータスコードを返さないオプション」についてです。

ソラコムBeamはSIMからUDP(HTTPやTCP、MQTTもある)で発信したデータをHTTPSリクエストに変換してくれるサービスです。(前回投稿「ソラコムBeamでUDP通信機器の暗号化を実装」を参照)

たいへん便利なサービスなのですが、今回のリリースによりさらに便利になったと思います。

今回の機能追加ではソラコムBeamの設定で「ステータスコードを省略」の設定ができるようになりましたが、さらにBeamから来たHTTPリクエストのレスポンスでHTTPヘッダに「Content-Type: application/octet-stream」を指定することにより、レスポンスBODYをSIM側へUDPでそのまま返信することができます。

この機能がなぜ重要なのか。筆者の知っているIoTデバイスは、いずれもUDPリモートコントロール機能を備えています。IoTデバイスは遠方に配置されるケースが多く、サーバーからUDPパケットを送信してデバイスの設定変更などを行う機能は、広範囲に実装されている定番機能なのです。そしてたいていの場合、そのパケットフォーマットはバイナリー形式で定義されています。

この類のデバイスをクラウドサービスにインテグレーションする場合は、通常SIM側のIPアドレスを固定し、回線全体をインターネットから隔離する「閉域ネットワーク」を用いることが考えられます。(そして事前登録されたIPアドレスに向かってサーバーからUDPパケットを投げる。)しかしながらこの方式の場合は回線費用が高く、相当の収益が見込めないと設置できないのが実情ではないでしょうか。

ソラコムBeamを使うと、小規模案件を安価に実装できます。IoTデバイスはサーバーへデータ送信する場合がほとんどでしょう。(そしてソラコムBeamを設定するとこのデータ送信はHTTPSリクエストに変換される。)サーバーはこのHTTPSリクエストに対し、Content-Typeをapplication/octet-streamに設定して今度は「デバイスを設定するUDPパケット」をHTTPレスポンスBODYに貼り付けて返信します。すると今度はbeam.soracom.io(のIPアドレスプールのどれか)からデバイスに向かってUDPパケットが送信され、デバイス設定が実行されます。

デバイスとソラコムBeamの間は秘密回線ですので、第三者がデータを見ることはできません。閉域ネットワークは不要。わずかなソラコムBeam料金とWebサーバーで、UDP双方向通信を実現できます。

ソラコムサンタよ、ありがとう。

Cloudblog20161227_01_2 図. ソラコムBeamからのHTTPリクエストに対して、デバイスに送信するバイナリデータ(青網掛け部分)を返信する。

2016年12月 7日 (水)

CodeBuildでgo言語のプロジェクトをビルドする際の注意事項

こんにちは。エンジニアの島袋です。

前回に引き続き、AWS CodeBuildの話になります。

CodeBuildでgo言語のプロジェクトをビルドする場合のハマりポイントに気づいたので、そちらを紹介します。

要点から先に言うと、以下です。

  • CodeBuildは/tmp配下にリポジトリをチェックアウトするため、ビルド対象がGOPATH配下にない
  • GOPATH配下にないとvendoringが有効にならないため、go build時に「パッケージが見つからない」と言われる

go buildがコケる??

前回のエントリではbuildspec.ymlのphase名をtypoしたせいでドハマリしてたんですが、その後typoを修正し、再度ビルドを実行すると、今度はgo buildでコケました。

エラーメッセージには「cannot find package〜」と表示されています。

依存しているパッケージが見つからないということですが、そんなはずはありません。

installフェイズでglideを使い、依存パッケージは全てvendorディレクトリの中にダウンロード済みです。

では何が駄目だったのでしょうか?

ビルド対象のプロジェクトがGOPATH配下になかったため、vendoringが有効になっていなかった

GOPATHとvendoringについて簡単に説明しておくと、GOPATHはgo言語を利用する際に設定が必要になる環境変数で、ユーザが任意のパスを指定する必要があります。

go言語でbuildコマンドを叩くと、buildに必要な依存パッケージをGOPATH/src配下から走査します。

(go get "パッケージ名" とコマンドを叩くと、GOPATH/src配下にパッケージをダウンロードできます)

ところが、この方法ではプロジェクト毎に利用するパッケージのバージョンを管理することができません。

(go getコマンドは常に最新版を取得します)

そこで追加された機能がvendoringです。

vendoringは有効な状態では、GOPATH/src配下を走査する前に、プロジェクトのルートディレクトリ直下のvendorディレクトリからパッケージを走査します。

上述のglideはvendorディレクトリ内に依存パッケージをダウンロードするパッケージマネージャです。

(rubyにおけるbundlerのようなものですね)

そんな便利なvendoringなんですが、ビルド対象のプロジェクトディレクトリをGOPATH/src配下に配置していないと有効になりません。

ところが、CodeBuildはビルド対象として指定したリポジトリを"/tmp/src257031055/src"といった感じで/tmp配下にチェックアウトしてしまうんですね。

当該ディレクトリ内のvendorディレクトリ内に依存パッケージをダウンロードし、go buildコマンドを叩いても、vendoringが有効になっていないため、GOPATH/src配下した走査してくれず、「cannot find package〜」と表示されてしまうわけです。

筆者含め、go言語利用者はGOPATH/src配下にディレクトリを作ってコードを書き始めるのが半ば常識化しているため、vendoringが無効になっていることに気づくのに時間を要しました。

回避策

とりあえずのワークアラウンドなんですが、以下のようにしました。

...省略...
  pre_build:
    commands:
      - glide install
      - mkdir -p $GOPATH/src/github.com/stk132/tsg
      - mv * $GOPATH/src/github.com/stk132/tsg/.
  build:
    commands:
      - cd $GOPATH/src/github.com/stk132/tsg && go build

はい。pre_buildフェイズでGOPATH/src配下にディレクトリを切って、CodeBuildがチェックアウトしてきたリポジトリの中身を全てコピーしています。

(これで当該ディレクトリの中ではvendoringが有効になります。)

そしてbuildフェイズでは当該ディレクトリに移動して、go buildを実行します。

(cdコマンドとgo buildをチェインしているのは、別の行にわけて実行すると、元のワーキングディレクトリに戻っているためです。多分Dockerfileのビルド時と同じ挙動??)

これ、もうちょっとスマートな解決方法ないですかね。。。。?

GOPATH=$GOPATH:pwd

とかして、ワーキングディレクトリをGOPATHに追加する方法も考えたんですけど、それだとビルド対象プロジェクト内のサブパッケージが走査できなくなるんですよね。

終わりに

よくよく考えると、jenkins等も同様の問題をはらんでいる気がするのですが、もしかしてgo言語のプロジェクトのCIを回している人にとっては今回のようなのは常識だったりするのでしょうか?

筆者は専らローカルで利用するCLIコマンドばかり作っているため、ビルドもローカルマシン上で行なっていたため、まんまとハマってしまいました。

2016年12月 5日 (月)

AWS CodeBuildに入門失敗した話

こんにちは。エンジニアの島袋です。

今回のエントリ内容については表題の通りです。

typoで日曜の夜をふいにしました。

要約すると以下です。

  • CodeBuildはbuildspec.ymlのphase名をtypoしてもエラーにはならない
  • phase名をtypoすると、phasesが全て無視される?

AWS CodeBuildとは

re:invent 2016で発表されたAWSの新しいサービスの1つで、コンテナベースのフルマネージドなCI環境を提供する的なやつです。

(CodeBuild単体だとビルドに特化してるから、CIとは言わないかな?)

ユーザが自分で管理するjenkinsなどと比較して、勝手にスケールしてくれるので、ビルドキューが詰まって長時間ビルド完了待ちをすることがないというのがウリのようですね。

(あと根本的にサーバー管理の必要がない)

詳細については

あたりを参考にしてください。

早速使ってみようとしたところ。。。

CodeBuildではビルド手順をyaml形式でbuildspec.ymlというファイル名で保存し、ビルド対象のプロジェクトのルートディレクトリ直下に配置する必要があります。

今回は筆者が作ったslackにコメント投稿するためのgo言語製のCLIコマンドをビルドしました。

buildspec.ymlは以下のようになります。

version: 0.1

environment_variables:
  plaintext:
    GOPATH: "/go"

phases:
  install:
    commands:
      - mkdir -p $GOPATH/{bin,src}
      - curl https://glide.sh/get | sh
  pre-build:
    commands:
      - echo prebuildstart
      - PATH=$PATH:$GOPATH/bin
      - echo prebuildend
  build:
    commands:
      - echo buildstrat
      - glide install
      - go build
  post_build:
    commands:
      - echo Build completed on `date`


artifacts:
  type: zip
  files:
    - oshirase

一応buildspec.ymlの記法について説明すると、以下のようになります。

  • environment_variables : 環境変数の設定
  • phases : 実際のビルド手順
    • install : ビルドに必要なコマンドなどのインストール
    • pre_build : ビルド前の作業
    • build : ビルド作業
    • post_build : ビルド後の作業
  • artifacts : zipにパッケージングするビルド成果物の指定

はい。pre_buildとするところをpre-buildとしてしまったんですね。

これに気づくのに二時間近く費やしました。

なぜそれほど時間がかかったかというと、phasesの中に誤ったphase名を記述しても、エラーにならず、ビルド完了となってしまったためです。

ビルドは完了しているにも関わらず、artifactsに指定したビルド成果物が見つからないとうログが出力されていたためおかしいと思い、artifactsの内容について試行錯誤してたんですね。

(そもそもビルド成果物見つからないのであればエラーにしてほしいところなんですが)

今回の場合、typoしたpre_buildだけじゃなく、phasesを全て素通りしてartifactsの処理だけ走っていたようです。

(それが規定動作なのかは現状不明ですが)

終わりに

typoには気をつけましょう。

あと、codebuildはビルド対象のブランチを指定できないようですね。codebuild単体だとjenkins氏やCircleCI等のCIサービスにすぐにとってかわるということは無さそうです。(他のcode〜シリーズと組み合わせること前提ですかね?)

採用情報

株式会社フレクトでは、事業拡大のため、
・Salesforce/Force.comのアプリケーション開発
・HerokuやAWSなどのクラウドプラットフォーム上での
Webアプリケーション開発
エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみたい方、
是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、セールスフォースパートナーです。
また、heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。

2024年4月

  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30        
ブログ powered by TypePad