2017年6月28日水曜日

StackEdit で Google ドライブに保存使用したら「Unable to authenticate user xxxxxxxxxxx, please sign in with Google.」が出た

概要

作成した Markdown を Google ドライブに保存しようとしたらタイトルのエラーが発生しました
対応方法を紹介します

環境

  • Windows7
  • Firefox 53.0.3

対応方法

この作業は StackEdit に関するローカルストレージの情報をすべて削除してるので Markdown の記事の情報も削除されます
なので、事前に Markdown の情報はどこかに退避しておいてください

  1. https://stackedit.io/recovery.html にアクセスします
  2. 「StackEdit local storage.json」をダウンロードします
  3. Menu -> Settings -> Utils -> Import docs and settings で先程ダウンロードした json を開きます
  4. 再度 https://stackedit.io/recovery.html の画面に戻り「To remove one document from the local storage click here.」の click here をクリックします
  5. 同様に「To fully clear the local storage click here.」の click here をクリックします
  6. 「To reopen StackEdit click here.」のクリックして再度 StackEdit を開きます

これで再度 Google ドライブに保存してみてください
成功するはずです

最後に

原因おそらくは複数のユーザを使い分けようとしてるのが原因かなと思います
例えば昔 Firefox で StackEdit を使っていて、そのとき利用してた Google アカウントではないアカウントで今回利用とすると該当のエラーが発生すると思います
認証情報が過去のユーザのものになっているのでエラーが発生していた感じだと思います

2017年6月27日火曜日

VMware Harbor の REST API を有効にしてプロジェクトやユーザに API でアクセスしてみる

概要

VMware Harbor の管理画面で実行されているライブラリやユーザ作成はバックエンドでは API 経由で実行されています
実はこの API は利用者側からも使用することができます
デフォルトではオフになっているので有効にすることで使用できるようになります

環境

  • Ubuntu 16.04
  • Harbor 1.1.1
  • docker-compose 1.13.0
  • docker 17.03

事前作業

Harbor のインストールはオフラインインストールを使って Ubuntu 上にインストールしています
手順はこちらの記事を参考にしてください

REST API の有効化

Harbor が動作しているサーバにログインしてサーバ上で作業する必要があります
harbor は /root/harbor にインストールしているものとします

  • cd /root/harbor
  • wget https://raw.githubusercontent.com/vmware/harbor/master/docs/prepare-swagger.sh https://raw.githubusercontent.com/vmware/harbor/master/docs/swagger.yaml
  • vi prepare-swagger.sh
SCHEME=https
SERVER_IP=reg.your.domain

ここのスキーマとサーバの設定の部分は http で IP ベースで動作している場合は、それを入力してください
ドメインを貼って証明書まで設定してる場合は、https で Harbor に設定したドメインを入力してください

  • chmod +x prepare-swagger.sh
  • ./prepare-swagger.sh

シェルを実行するとカレントに swagger.tar.gz が作成されているはずです

  • cp docker-compose.yml{,.back}
  • vi docker-compose.yml
- ../src/ui/static/vendors/swagger-ui-2.1.4/dist:/harbor/static/vendors/swagger
- ../src/ui/static/resources/yaml/swagger.yaml:/harbor/static/resources/yaml/swagger.yaml

上記 2 行を「ui:」の「volumes:」の部分に追記します
diff だと以下の通りになります

  • diff docker-compose.yml.back docker-compose.yml
79a80,81
>       - ../src/ui/static/vendors/swagger-ui-2.1.4/dist:/harbor/static/vendors/swagger
>       - ../src/ui/static/resources/yaml/swagger.yaml:/harbor/static/resources/yaml/swagger.yaml

あとはコンテナを再起動すれば OK です

  • docker-compose down
  • docker-compose up -d

動作確認

まず https://reg.your.domain/static/vendors/swagger/index.html にアクセスして Swagger UI が表示されることを確認してください
ここで UI が表示されないと API が有効になっていません

表示されたら実際に API をコールしてみましょう
例えばプロジェクトやリポジトリを検索する API /search は以下のようにコールできます

  • curl -X GET --header 'Accept: application/json' 'https://reg.your.domain/api/search?q=library'

結果以下のような json が返却されれば OK です

{
  "project": [
    {
      "project_id": 1,
      "owner_id": 1,
      "name": "library",
      "creation_time": "2017-06-26T08:03:45Z",
      "creation_time_str": "",
      "deleted": 0,
      "owner_name": "",
      "public": 1,
      "Togglable": false,
      "update_time": "2017-06-26T08:03:45Z",
      "current_user_role_id": 0,
      "repo_count": 0
    }
  ],
  "repository": []
}

SDK や詳しいドキュメントはほぼないので、Swagger UI を見ながら API をコールするしかないと思います
swagger.yaml が公開されているので go-swagger を使って swagger generate client すればクライアントツールは簡単に作れるかもしれません

最後に

Harbor の REST API を有効にしてプロジェクトやレジストリの情報にアクセスできるようにしてみました
認証等は特になかったので公開するのは少し危険ですが、プライベートで独自の UI を作ったりするには便利かなと思います

参考サイト

2017年6月23日金曜日

Arduino でバイト配列を文字列に変換する方法

概要

タイトルの通り
MQTT の PubSubClient.h を使う時にペイロードが byte* だったので文字列に変更したかった感じです

環境

  • macOS 10.12.5
  • Arduino IDE 1.6.12

コード

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';
  String msg = String((char*) payload);
  Serial.println(msg);
  if (msg == "start") {
    // something ...
  } else if (msg == "stop") {
    // something ...
  }
}

ポイントはバイト配列の最後に終端文字を入れてること
こうしないとうまく文字列に変換できません

最後に

*byte を String に変換する方法を紹介しました
久しぶりに Arduino に触るとよくわかんないですね

参考サイト

2017年6月22日木曜日

firebase-ruby の get, push, set, update, delete の挙動を確認してみた

概要

前回 は firebase-ruby を使った GettingStarted 的な記事を紹介しました
今回はリアルタイムデータベースを操作できるその他のメソッドについて挙動を確認してみました

環境

  • CentOS 7.3.1611
  • ruby 2.3.3p222
  • firebase-ruby 0.2.6

使用するコード

  • bundle init
  • vim Gemfile
gem "firebase"
  • bundle install
  • vim test.rb
require 'firebase'

class FB
  BASE_URI = 'https://project-id.firebaseio.com/'
  SECRET_KEY = 'your-database-secret-key'

  def initialize
    @client = Firebase::Client.new(BASE_URI, SECRET_KEY)
  end

  def get(path, query)
    @client.get(path, query)
  end

  def push(path, hash)
    @client.push(path, hash)
  end

  def set(path, hash)
    @client.set(path, hash)
  end

  def update(path, hash)
    @client.update(path, hash)
  end

  def delete(path, query)
    @client.delete(path, query)
  end
end

f = FB.new

res = f.push('test', { :name => "hoge" })
id = res.body['name']
res = f.get("test/#{id}", {})
p res.body['name'] # => "hoge"

f.set('test1', { :name => "fuga" })
res = f.get('test1', {})
p res.body['name'] # => "fuga"

f.update("test/#{id}", { :name => "hogehoge" })
res = f.get("test/#{id}", {})
p res.body['name'] # => "hogehoge"
f.update('test1', { :name => "fugafuga" })
res = f.get('test1', {})
p res.body['name'] # => "fuga"

f.delete("test/#{id}", {})
f.delete('test1', {})
  • bundle exec ruby test.rb

BASE_URI と SECRET_KEY は自分のプロジェクトの値を設定してください

挙動説明

firebase-ruby にはデータを登録するためのメソッドが 2 つ用意されています
push と set があります

push の場合、基本的に毎回新規オブジェクトの追加となります
追加したオブジェクトに自動で ID を振ってくれるため、その ID でオブジェクトを識別します
ID は push したレスポンス情報に含まれています

方や set は指定したパスにそのままデータを登録します
なので 2 回 set しても内容は変わりません、オブジェクトも増えません
get でアクセスする場合のパスにも ID が含まれることはありません

get は path を指定してデータを取得します
path 配下にあるオブジェクトに対して絞り込みを行いたい場合はクエリを使います
https://firebase.google.com/docs/reference/android/com/google/firebase/database/Query
例えば上位 10 件のみを取得したい場合は limit を使います

あとは update と delete ですが、これも path で取得したオブジェクト配下の情報を削除したり更新したりします
update に関しては上書き更新なのでデータが新規で登録されるということはありません
delete に関しては物理削除なので、一度削除したオブジェクトは再度戻すことはできません

最後に

firebase-ruby が用意している関数の挙動を確認してみました
個人的には push ではなく set を使ってデータ登録したほうが毎回 ID を走査しなくて済むので簡単かなと思います

あとは get, update, delete を使って登録したデータを path を指定して操作する感じかなと思います

Firebase のデータベース機能はリアルタイムデータベースなので push や set で登録したときのアプリ側の挙動も確認したいと思っています
また Firebase には他にもストレージやホスティング機能、スクリプト機能があるのですが、firebase-ruby ではデータベース機能に対する制御しかできません
ストレージなどを使いたい場合は直接 Google Storege を操作する感じになるみたいです

参考サイト

2017年6月21日水曜日

作成した gem ファイルを rubygems.org で公開する手順

概要

前回 独自の gem ファイルを作成する方法を紹介しました
今回は作成した gem ファイルを rubygems.org で公開する手順を紹介します

環境

  • CentOS 7.3.1611
  • ruby 2.3.3p222
  • gem 2.6.11
  • rake 10.4.2

サインアップ

https://rubygems.org/sign_up からアカウントを作成しましょう
メールアドレスがあれば簡単に作成できます

登録したメールアドレスに確認用の URL が送信されるのでクリックしてアカウントを承認します
問題なくログインできるか確認してください

gem の作成

とりあえず今回は何でも OK です
本記事では 前回 の記事を参考に gem を作成しています

とりあえずリリースしてみる

まず Github にソースをアップロードします
Github じゃなくても良いですが remote のリポジトリがないと怒られます

でコードを push しましょう
そして

  • bundle exec gem push

で rubygems.org に認証します
登録したメールアドレスとパスワードで認証しましょう
cat ~/.gem/credentials ができれば OK です
そして

  • bundle exec rake release

で gem ファイルアップロードできます

fstlib 0.1.0 built to pkg/fstlib-0.1.0.gem.
Tag v0.1.0 has already been created.
Pushed fstlib 0.1.0 to rubygems.org.

こんな感じになれば成功です
rubygems の自分のアカウントのページにアクセスするとアップロードした gem があると思います

バージョンアップしてみる

適当にコードを改修してバージョンアップしてみましょう

  • vim lib/fstlib.rb
require "fstlib/version"

module Fstlib
  def self.hello
    "My second rubygems"
  end
end
  • vim lib/fstlib/version.rb
module Fstlib
  VERSION = "0.1.1"
end

でコードを改修したら

  • git add .
  • git commit -m “Second commit”
  • git push -u origin master

でコミットして

  • bundle exec rake release

で再度アップロードします
アップロード完了後再度 gem のページを見てみるとバージョンが 0.1.1 に上がっていることが確認できると思います

使ってみる

新しいスクリプトを作成してアップロードした gem が使えるか確認してみましょう

  • bundle init
  • vim Gemfile
gem "fstlib"
  • bundle install

で rubygems.org からアップロードした gem がインストールできます

  • vim test.rb
require 'fstlib'

p Fstlib.hello
  • bundle exec ruby test.rb

実行すると "My second rubygems" が表示されると思います

最後に

作成した gem を rubygems.org で公開する手順を紹介しました
今回紹介した rake release の流れは「ビルド -> コミットがあるかチェック -> リモートに push -> rubygems.org にプッシュ」という流れをやってくれています
https://github.com/bundler/bundler/blob/master/lib/bundler/gem_helper.rb#L55

なので bundle exec gem push を実施しないでいきなり release しても初回であれば rubygems.org に対する認証を聞かれると思います
うまくログインができない場合は個別で gem push を実行すると良いと思います

また削除する場合はコマンドで行います

  • gem install gemcutter
  • gem yank fstlib -v 0.1.1
  • gem yank fstlib -v 0.1.0

という感じで全バージョン削除すると rubygems.org から消えます

参考サイト

2017年6月20日火曜日

RSpec で undefined method 'get' for が出たときの対処法

概要

エラーの詳細は以下の通り

undefined method `get' for #<RSpec::ExampleGroups::MyApp:0x00000002fc48e0>
Did you mean?  gets
               gem

Sinatra など get リクエストを送信するテストが実行できない状況です

環境

  • CentOS 7.3.1611
  • ruby 2.3.3p222
  • rspec 3.6.0

対処方法

  • rspec --init

で .rspec ファイルを作成します
中身は

--require spec_helper

となっているので .rspec ファイルを作成しないで spec_helper.rb で require しても大丈夫だと思います

2017年6月19日月曜日

Sinatra で設定ファイルを使う方法

概要

sinatra-contrib というパッケージを使うと簡単に設定ファイルを読み込むことができます
実際に設定ファイルを使ったサンプルの sinatra アプリケーションを紹介します

環境

  • CentOS 7.3.1611
  • ruby 2.3.3p222
  • sinatra 2.0.0
  • sinatra-contrib 2.0.0

ライブラリのインストール

  • bundle init
  • vim Gemfile
gem "sinatra"
gem "sinatra-contrib"
  • bundle install

また今回のディレクトリ構成は以下の通りです

.
├── app.rb
├── config.ru
├── config.yml
├── Gemfile
├── Gemfile.lock
└── views
    └── hello.erb

アプリの作成

  • vim app.rb
require "sinatra/base"
require "sinatra/config_file"

class MyApp < Sinatra::Base
  register Sinatra::ConfigFile
  config_file './config.yml'

  get '/' do
    @message = settings.message
    @friends = settings.friends
    erb :hello
  end
end

Sinatra::Base を継承して独自のコントローラクラスを定義します
そして、設定ファイルを読み込むために Sinatra::ConfigFile を登録します
読み込みに成功した後は settings というオブジェクトを参照することで値を取得することができます
今回は取得した値をテンプレートに渡してテンプレート側で値を確認します

設定ファイルの作成

  • vim config.yml
message: "My friends"
friends:
  - name: 'bob'
    age: 20
    favorites:
      - 'baseball'
      - 'soccer'
  - name: 'tom'
    age: 19
    favorites:
      - 'soccer'

app.rb と同じディレクトリに配置します
YAML 形式で記述します
今回は配列も使っています

テンプレートファイルの作成

  • mkdir views
  • vim views/hello.erb
<h2>"<%= @message %>"</h2>
<% @friends.each do |f| %>
<div>
  <div>name: <%= f['name'] %></div>
  <div>age: <%= f['age'] %></div>
  <div>favorites:</div>
  <% f['favorites'].each do |fa| %>
    <div>- <%= fa %></div>
  <% end %>
</div>
<% end %>

app.rb から呼び出されるテンプレートファイルです
設定ファイルの内容を出力しています
ハッシュとして渡ってくるので ruby のハッシュを参照する方法で値を取り出すことができます

アプリ起動用の rackup ファイル作成

  • vim config.ru
require 'bundler'
Bundler.require

require './app'
run MyApp

rackup コマンドでアプリを起動するためのスクリプトです

動作確認

  • bundle exec rackup
  • curl localhost:9292

で config.yml に書かれた情報が HTML で出力されると思います

最後に

sinatra で YAML で書かれた設定ファイルを読む込む方法を紹介しました
値の参照は settings オブジェクトを使って参照しますがスコープは sinatra アプリケーション内のみとなります
なので、自分で定義したライブラリの関数などに値を渡したい場合は引数などで渡す必要があります (ライブラリ側で settings を参照することはできません)

参考サイト