GeekFactory

int128.hatenablog.com

Google Photos Library APIで写真をアップロードする

Google Photos Library APIが使えるようになったので、写真のアップロードを試してみました。

アクセストークンの取得

https://console.cloud.google.com/apis/credentials から新しいOAuth Clientを追加します。Client IDとClient Secretが表示されるのでメモしておきます。

アクセストークンを取得します。まず、ブラウザで以下のURLを開きます。YOUR_CLIENT_ID はClient IDに置き換えてください(以下同じです)。

https://accounts.google.com/o/oauth2/v2/auth?client_id=YOUR_CLIENT_ID.apps.googleusercontent.com&response_type=code&scope=https://www.googleapis.com/auth/photoslibrary&redirect_uri=urn:ietf:wg:oauth:2.0:oob

すると、ブラウザ上に認可コードが表示されます。以下のコマンドを実行します。

curl -X POST --data 'code=YOUR_AUTH_CODE&client_id=YOUR_CLIENT_ID.apps.googleusercontent.com&client_secret=YOUR_CLIENT_SECRET&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code' https://www.googleapis.com/oauth2/v4/token

アクセストークンを含むJSONが返されるのでメモしておきます。

{
 "access_token": "YOUR_ACCESS_TOKEN",
 "token_type": "Bearer",
 "expires_in": 3600,
 "refresh_token": "..."
}

写真のアップロード

ここからは Upload media にしたがって進みます。

まず、画像ファイルをアップロードします。

curl -v --upload-file YOUR_IMAGE.png -X POST -H 'Content-type: application/octet-stream' -H 'X-Goog-Upload-File-Name: YOUR_IMAGE.png' -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' https://photoslibrary.googleapis.com/v1/uploads

アップロードに成功するとトークンが返されるのでメモしておきます。

< HTTP/2 200
< x-guploader-uploadid: ...
< content-type: text/plain
< content-length: 510
< date: Wed, 06 Jun 2018 14:11:39 GMT
< server: UploadServer
< alt-svc: quic=":443"; ma=2592000; v="43,42,41,39,35"
<
UPLOAD_TOKEN

次に、アップロードした写真を自分のライブラリに追加します。

curl -v --data '{"newMediaItems":[{"simpleMediaItem":{"uploadToken":"UPLOAD_TOKEN"}}]}' -H 'Content-type: application/json' -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate"

ライブラリへの追加が成功すると以下のようなレスポンスが返されます。

< HTTP/2 200
< content-type: application/json; charset=UTF-8
< vary: X-Origin
< vary: Referer
< vary: Origin,Accept-Encoding
< date: Wed, 06 Jun 2018 14:14:27 GMT
< server: ESF
< cache-control: private
< x-xss-protection: 1; mode=block
< x-frame-options: SAMEORIGIN
< x-content-type-options: nosniff
< alt-svc: quic=":443"; ma=2592000; v="43,42,41,39,35"
< accept-ranges: none
<
{
  "newMediaItemResults": [
    {
      "uploadToken": "UPLOAD_TOKEN",
      "status": {
        "message": "OK"
      },
      "mediaItem": {
        "id": "...",
        "productUrl": "https://photos.google.com/lr/photo/...",
        "mimeType": "image/png",
        "mediaMetadata": {
          "creationTime": "2018-06-06T14:14:25Z",
          "width": "2462",
          "height": "1040"
        }
      }
    }
  ]
}

Googleフォトを開いてみましょう。新しい写真が追加されていれば成功です。

重複する写真のアップロード

ここで同じ写真を再度アップロードしてみます。

curl -v --upload-file YOUR_IMAGE.png -X POST -H 'Content-type: application/octet-stream' -H 'X-Goog-Upload-File-Name: YOUR_IMAGE..png' -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' https://photoslibrary.googleapis.com/v1/uploads

先ほどとは異なるトークンが返されました。このトークンを自分のライブラリに追加してみます。

curl -v --data '{"newMediaItems":[{"simpleMediaItem":{"uploadToken":"UPLOAD_TOKEN"}}]}' -H 'Content-type: application/json' -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate"

すると、不思議なことに先ほどと同じレスポンスが返されました。mediaItemidが同じ値になっています。

Googleフォトを開いてみましょう。やはり画像が重複することはなく、1枚だけ表示されているはずです。

ドキュメントによると同じ写真をアップロードした場合はトークンが発行されないはずですが、実際には一連のAPIは成功するが画像は重複しない振る舞いになるようです。冪等になるように工夫されているのですね。

(6/20追記)下記の記事も参考にしてください。

int128.hatenablog.com

See Also

Debian and Kubernetes optimized Kernel in kops

kopsが利用するAMIについて調べたのでまとめておく。

kopsでサポートされているOSは https://github.com/kubernetes/kops/blob/master/docs/images.md に書かれている。デフォルトではDebianが選択される。他にCoreOS、UbuntuCentOSRHELがサポートされているが、現実的にはDebianかCoreOSを選択することになると思う。ドキュメントやGitHub Issuesを見る限り、Debianが最もよくテストされているようだ。

kopsの構成でAMIを指定しない場合、 stable channel で定義されているAMIが選択される。現時点では、Kubernetes 1.9の場合は kope.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-02-08 というAMIが選択される。

spec:
  images:
    - name: kope.io/k8s-1.8-debian-jessie-amd64-hvm-ebs-2018-02-08
      providerID: aws
      kubernetesVersion: ">=1.9.0 <1.10.0"

このAMIはDebian 8(Jessie)がベースになっている。具体的な構成はYAML形式のテンプレートで定義されている。詳しくはテンプレートを読むと理解できるが、必要なパッケージのインストールや設定ファイルの変更が記述されている。Dockerのインストールもここで行われる。途中で apt-get dist-upgrade コマンドが実行されているので、ビルド時点で最新のJessieが生成されるようだ。

このAMIではDebianの標準カーネルではなくKubernetesに最適化されたカーネルが使われている。先ほどのAMIには 4.4.115-k8s というバージョンのカーネルが組み込まれている。カーネルの具体的な設定はconfigファイルで定義されている。

AMIのビルドおよびリリースにはImageBuilderが利用されている。カーネルのビルドおよびリリースにはMakefileが利用されている。いずれも継続的にリリースできるように工夫されている。

なお、実際の環境で使われているDebianカーネルのバージョンを調べるにはSSHするのが手っ取り早い。先ほどのAMIでは以下のバージョンが使われている。

$ uname -a
Linux hostname 4.4.115-k8s #1 SMP Thu Feb 8 15:37:40 UTC 2018 x86_64 GNU/Linux

$ cat /etc/debian_version
8.10

Slack公式のJIRA連携機能を試した

Slackが公式に公開しているJIRA連携機能を試してみました。

get.slack.help

JIRA連携機能はJIRA CloudとJIRA Serverに対応しています。今回は個人で運用しているJIRA Serverを利用しました。

以下の手順でSlackとJIRAを連携できます。詳しくは公式ページを参照してください。

  1. 自分のSlackワークスペースにJIRA Server Alertsを追加する。
  2. 通知先のチャンネルを指定する。
  3. JIRAでWebHookを作成する。

これだけです。簡単ですね。

JIRAのWebHookは以下のように設定しています。

f:id:int128:20180522101845p:plain:w425

デフォルトではIssueのステータスを更新した時にのみ通知されるようです。以下のオプションを有効にすると、Issueにコメントを書いた時にも通知されるようになります。

f:id:int128:20180522101207p:plain:w600

JIRAのIssueにコメントを書いて、ステータスをDoneに更新すると、Slackに以下のように通知されます。

f:id:int128:20180522100745p:plain:w509

以下の点が気になりました。

  • ユーザ名ではなくフルネームが表示されるため、Slack上でメンションにならないので通知に気付かない。Slackの通知設定でフルネームを入れておけば解決しそう。
  • JIRA記法のメンション([~hidetake])がSlack記法のメンション(@hidetake)に変換されない。これもSlackの通知設定で解決しそう。
  • デフォルトでは標準的なステータスしか設定されていないので、チームで独自のステータス(In Reviewなど)を使っている場合は設定を見直す必要がある。

SlackとJIRAの連携は簡単なので、ぜひ試してみてください。

ちなみに上記の問題点を解決した拙作のBotもあります。参考まで。

int128.hatenablog.com