Skip to main content

6 posts tagged with "Google App Engine"

View All Tags

· One min read

WerckerでGAEにデプロイしようとしたらエラーが発生。

今回は wercker というサービスアカウントを作成し、WerckerからGAEにデプロイしようとした。

ERROR: (gcloud.app.deploy) PERMISSION_DENIED: Not allowed to get project settings for project PROJECT_ID

このエラーが発生したので「App Engine 管理者」の役割を設定した。

ERROR: (gcloud.app.deploy) Error uploading files: User [wercker@PROJECT_ID.iam.gserviceaccount.com] does not have permission to access b [staging.PROJECT_ID.appspot.com] (or it may not exist): wercker@PROJECT_ID.iam.gserviceaccount.com does not have storage.objects.list access to staging.PROJECT_ID.appspot.com.

このエラーには「ストレージのオブジェクト管理者」の役割を設定した。
「ストレージのオブジェクト作成者」ではエラーが発生した。

[-] IAM - Google Cloud Platform
https://console.cloud.google.com/iam-admin/iam/project
設定はこのページからできる。

参考ページ​

[-] WerckerでGAEにデプロイする手順
https://findlog.github.io/55

· 8 min read

また海藻猫が騒いでいたのを見つけてしまったのが運の尽き…。 [blackbirdpie id="126122863177633793"]

Android開発はやったことがないからわからないけど、Scala + Eclipseは使っているから、簡単に手順を書いておく。

■ teaplanet/sbt-appengine-eclipse - GitHub

https://github.com/teaplanet/sbt-appengine-eclipse以下の手順で作るふたつのbuild.sbtはGitHubに置いといた。

前提

sbtとEclipseを使ってAppEngineの開発を行う。 テストにはspecs2を使うことを想定してるので、specs2がいらない場合は後述のbuild.sbtからspecs2の依存関係消してね。

こんな役割分担で使ってます。 依存関係解決:sbt エディタ:Eclipse コンパイル:Eclipse(, sbt) テスト:Eclipse(, sbt) デバッグ:Eclipse こんな構成で行います。

ライブラリの依存関係の解決はsbtに任せる。ついでにEclipseのプロジェクトファイル(.project)の生成もsbtに任せる。 Eclipseはエディタとして使いつつ、同時にコンパイルも行う。 テストしつつデバッグもEclipseで行ってる。 基本的にどちらを使ってもいいんだけど、個人的にはこうやって使ってる。

依存関係の解決をsbtがやってくれるもんだから、バージョン管理にバイナリが含まれなくて精神衛生上よい。 プロジェクトをコンパイルするにもコンソールだけで済むし(Eclipse不要)。

環境

Mac OS X 10.7.1 Scala 2.9.1 sbt 0.11.0-RC1 Eclipse Indigo

開発環境構築

sbtの入手

■ Index of ivy-snapshots/org.scala-tools.sbt/sbt-launch/0.11.0-RC1http://repo.typesafe.com/typesafe/ivy-snapshots/org.scala-tools.sbt/sbt-launch/0.11.0-RC1/コンパイルしてもいいけど、持ってきた方が楽。今はこれを使ってます。 違うバージョンでも問題ないかもしれないけど、他のバージョンを使ってたらsbteclipseが動かなかった。

sbtのインストール

入手したsbt(sbt-launch.jar)を実行するために ~/bin/sbt ファイルを作成する。
java -Xmx512M -jar `dirname $0`/sbt-launch.jar "$@"
chmod u+x ~/bin/sbt
実行権限付けて、実行できるようにする。

プロジェクト作成

プロジェクトは "ws/sample" に作ることにする。
mkdir -p ws/sample cd ws/sample sbt
これでsbtで必要なファイルが作成され、sbtのプロンプトが表示されているはず。 aboutって入力するとsbtやScalaのバージョンが表示されます。

プロジェクト定義

プロジェクト定義ファイルであるbuild.sbtを作る。 このファイルを作るときはエディタで作ってもいいし、別コンソールからviで作ってもいい。このあともちょくちょくsbtでコマンドを実行するので、sbtプロンプトは残しておいた方が便利だと思う。 ws/sample/build.sbt
name := "sample"

version := "1.0.0"

scalaVersion := "2.9.1"

organization := "teaplanet"

// for Specs2
resolvers ++= Seq("snapshots" at "http://scala-tools.org/repo-snapshots",
"releases" at "http://scala-tools.org/repo-releases",
"releases" at "http://repo1.maven.org/maven2/")

libraryDependencies ++= {
val appEngineVersion = "1.5.5"
Seq(
"com.google.appengine" % "appengine-api-1.0-sdk" % appEngineVersion,
"com.google.appengine" % "appengine-api-stubs" % appEngineVersion % "test",
"com.google.appengine" % "appengine-api-labs" % appEngineVersion % "test",
"com.google.appengine" % "appengine-testing" % appEngineVersion % "test",
"com.google.appengine" % "appengine-tools-sdk" % appEngineVersion % "test",
"org.specs2" %% "specs2" % "1.6.1" % "test",
"org.specs2" %% "specs2-scalaz-core" % "6.0.1" % "test",
"junit" % "junit" % "4.9" % "test"
)
}

build.sbtの空行は大切。

このファイルを作成したら、sbtプロンプトへ戻る。

reload
update

reloadコマンドで更新したファイルを読み込み、updateコマンドで設定を反映する。 初回は依存ライブラリをダウンロードするから時間がかかると思うので、しばし待つ。 ここまででAppEngineの開発が出来る状態になってる。

sbteclipseプラグインを導入する

Eclipseのプロジェクトファイル(.project)を作るためにsbteclipseプラグインを導入する。 ws/sample/project/plugins/build.sbt
resolvers += Classpaths.typesafeResolver

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse" % "1.4.0-RC4")

pluginsディレクトリは無いと思うので作成する。 ここでもbuild.sbtの空行は意味があるので注意。

またsbtプロンプトへ戻ってお約束のコマンド。

reload
update

これでsbteclipseの導入が完了。

ecl[TAB]

と打って "eclipse" と補完されるようであれば正常に導入されてる。

.projectを作るために次のコマンドを実行する。

eclipse create-src

EclipseでScalaを使う準備

■ Scala IDE for Eclipsehttp://www.scala-ide.org/EclipseでScalaを使うためにScala IDE for Eclipseをインストールしておくこと。

Eclipseの設定でbuildmanagerとしてsbtを使う設定ができる。

でも、これが役に立っているかはわかっていない…。

■ Using the Google Plugin for Eclipse - Google App Engine - Google Code

http://code.google.com/intl/en/appengine/docs/java/tools/eclipse.html#Installing_the_Google_Plugin_for_Eclipseライブラリの依存関係はsbtで解決してるので、こっちは必要ないかも。入れてあるけど。

Eclipseをエディタとして使う

sbtで.projectを作成したので、それを読み込む。File -> Import...Existing Projects into Workspace"Browse..." からws/sampleディレクトリを選択。結果的にこんな感じにAppEngineのライブラリが読み込まれた状態でプロジェクトが出来る。

ルーティン

依存ライブラリが増えた場合はbuild.sbtを修正し、reload -> updateを行う。 その後、eclipse create-srcを実行し.projectを作成。 Eclipseに反映するために、更新(F5)を行う。

この環境はsbtとEclipseの共存なので、好きな方を使えばいい。 テストの実行をリアルタイムに行いたいなら、sbtで "~test" しておけばいいし、トレース実行したいならいつものようにEclipseを使えばいい。

課題

ひとつだけ問題があって、Eclipseでテストは実行できるんだけど、sbtでコンパイルすると次のエラーが発生してテストに失敗する。
NullPointerException: No API environment is registered for this thread. (DatastoreApiHelper.java:118)
これはAppEngine絡みの問題なので、AppEngineを使わない人は出会わないだろうし、設定次第で解決できそうな気もする。

今回作ったプロジェクトはEclipseのプラグインを導入してない。導入した所で.projectファイル作成時に設定が上書きされ、消えてしまう。 ■ eed3si9n/sbt-appengine - GitHub

https://github.com/eed3si9n/sbt-appenginesbt-appengineプラグインもあるんだけど、うまく動かなかったので放置してる。

実は…

このやり方、pomuさんに教えてもらったんだけどね。 [blackbirdpie id="117144635427663872"]

· 12 min read

既にいろんなところで話題になってるGoogle App Engineの新料金体系。

■ Google cloud services – App Engine

http://www.google.com/enterprise/cloud/appengine/pricing.html

今後、自分でもどのサービス、どのクラウドを利用していくか迷っているけど、今思っていることをメモしておくことにする。 Google擁護な内容が出てくるかも知れないので、先に書いておくと…トップゲート社員です。でも、Googleのサービスを使った業務には携わっていなく、ITアーキテクトとして働いてます。 なので、書いてることは間違ってるかもしれません!!

Twitter botの場合

自分で動かしてるのは小さなTwitter bot(3分間隔でごにょごにょして、tweetしてるだけ)だから課金されることないだろうと思っていたのだが、あんな小さなbotも課金されるくらいに料金体系が変わってました。 具体的にどれくらいになっていたかというと、$2.25〜$2.34/dayくらい。月額に換算すると5500円/月くらい。 今までは毎月無料の範囲内に収まっていたのに、急に5000円以上の出費!…になるかも。

お手軽な対処

まず、お手軽にこの金額を減らす方法。 あっとゆーまに設定が完了する割に効果あります! Max Idle Instancesを1にし、Min Pending Latencyをなるべく大きく(15.0s)にすること!

■ 404 shin1のつぶやき ないわー Not Found: Google App Engineの新料金体系に向けた準備 #gaeja

http://shin1o.blogspot.com/2011/09/google-app-engine-gaeja.html詳細はこちらを参照〜。

具体的な効果は?というと、これによって、$0.03/dayくらいまで下がりました。 月に換算すると70円/月程度。これなら全然問題無し。 ここで気を付けなければならないのは「な〜んだ、月に70円か」にはならないいうこと! 有料プランの場合$9/monthかかります。 今なら$9と言っても700円かからないくらいだけど、70円からすると大きな数字。

自分が取るであろう選択肢は有料プランにしないこと。 無料の範囲を超えてしまった場合、アプリが止まってしまうが、困る人がいないので気にしない。 1日70円分だけアプリが止まりますって解釈。

金額に関しては上記のとおりなんだけど、これによるアプリの性能はどうなるか?というのがまだよくわからない。 Twitter botなんて放置しっぱなしだし、性能なんて気にしてないんだけど、サービスとして利用している人はどうなるだろう? レスポンスが遅くなって、不便になったりするんではないだろうか?という懸念がある。

この施策は簡単に出来るものの、インスタンスに関わる設定なので、そのことも気にしておいた方がよさそうだ。

Google App Engine使うのやめる?

簡単に課金を抑える施策をして一息ついたところで、今後どうするか?ということを考えてみる。 うちのbotは放置だけど、世間一般的に…ってことで。

この新料金体系によって、運営無理っ!って辞めてる人もいるんだけど、その答えを出すには早いと思ってる。 大きな理由は2つ。

  • App Engineの最適化してないでしょ?
  • App Engineと他のクラウド比べてどっちが安い?

App Engineの最適化というのは、各種サービスをうまく活用しているか?ということ。 うちのTwitter botは最適化してない。最適化したら間違いなく無料の範囲内に収まる。 Twitter botの最適化としてすぐに挙げられるのはこれら。

  • Task QueueをBackendsで動くようにする
  • 1インスタンスで複数スレッドを捌く
  • Memcacheを使う

たぶん、これだけでだいぶ変わる。 Botを作った当初はMemcacheなくても動くからいいやって放置したままだし、他の2つはあとからリリースされた機能なので対応してない。 これらの対応をするだけで無料で収まるのであれば、また、安くなるのであれば、これらを実装しなかったエンジニアの怠惰だと思う。

後者のAppEngineと他のクラウドの価格についてだが、これは人それぞれだろう。 AppEngineが安くなることもあれば、高くなることもあると思ってる。 そこはアプリの特徴次第だと思っているけど、その比較はインスタンス数を等しくしてから比べるべきだと思う。 少なくとも、Max Idle Instancesの設定がAutomaticなんて無しだろー!ということ。

で、App Engineどうするよ?

個人的には、App Engineはありだと思いつつ、無しだと思うところもある。 アプリの特徴次第としか言えないが、結果的に他のクラウドより高くなるのであれば辞めればいいと思う。 辞めればいいというと、少し乱暴だが、そのアプリの適所がApp Engineではなかったということか、App Engine用に最適化していないということだと思う。 移植性やベンダーロックを考えれば、App Engineに最適化すべきとも言えないわけだし、そこは適するクラウドを選択すべきだと思う。 App Engineと相性のいいアプリだったらまた利用すればいいんじゃないかな?

新料金体系になって、どういうアプリがApp Engineに適しているかというと、とても小さなアプリか、スケールアウトを自動にして欲しいアプリだと思う。 とても小さなアプリであれば無料の範囲内で収まるし、イニシャルコストがなくて済む。ただし、App Engineに最適化していないと無料の範囲を超えやすいため、各種サービスをうまく連携させる必要がある。そういう意味では従来よりも敷居が上がっている。 Memcacheを間に挟むだけだとしても、どのデータをどのようにキャッシュさせておくか?ということを考慮するのは容易ではないと思うから。

もうひとつのスケールアウトして欲しいアプリは、キャンペーンサイト向けなのかも? 常にトラフィックが多いサイトであれば、他のクラウドの方が安い気もするが…この辺はよくわからない。 それよりも、キャンペーンサイトみたいに一時的にトラフィックが膨大になる可能性がある場合、 「$9/month払うし、膨大なトラフィックにはその分払うからなんとかしてよ」 ってことに対応できる。膨大なトラフィックに関しては前例もあるし、安心して任せることが出来る。

では、上記2つに当てはまらないアプリについてはどうだろう? これについては全体的に模索している時期なのではないだろうか? 今までは最適化してないアプリでも無料だったけど、新料金体系では最適化してあるアプリがどれくらいの価格になるかまだ落ち着いてなくて、感覚が芽生えていない気がする。

他のクラウド

個人的に気になっているクラウドは次の2つ。
  • Cloud Foundry
  • さくらのクラウド

どちらもまだ料金体系が明確になっていなくて、リリースされていないので比較できないが、楽しそうではある。 App Engineを含めたこの中で、自分の要望にあっているクラウドはどれだろう?と考えた場合、 App Engine >= Cloud Foundary > さくらのクラウド のような感じかな?と思ってる。 理由は簡単で、

  • サービスを作ることに集中できる
  • 知らない分野はプロに任せる

ということ。 IaaSの場合、色々と出来るけど、ネットワークやサーバーの扱いについては知っているけど、専門家じゃない。 それに比べ、PaaSの場合は実装だけに集中できる。

理屈では書いたとおりだと思っているけど、Cloud FoundryのMongoDBにも興味あるし、さくらのクラウドにも興味あります!(笑) 嗜好や感情を入れたらキリないよね。

· 2 min read

ScalaからApp EngineのDatastoreに書き込みたいんだけど、使いやすい文法はないものか? ここに直接書いてるから、文法は間違ってるかも?雰囲気だけ伝わればよし。

DSL風?

Entity.store("kind") {
p("name", "Taro"),
p("age", 10)
}

DSL風は嫌いではないけど、プロパティ名を毎回指定するのはどうなんだろ?と思う。KVSってそういうものだけど、もうちょっと楽したいよね?って意味で。

Java風?

class Entity {
val name:Option[Property[String]] = "name".p
val age = "age".p // 型推論でOption[Property[Int]]
val birthday = "date".p.index
}
val e = new Entity()
e.name = "Taro"
e.age = 10 // def age_=(value) = valueとかしておく必要ありか
e.birthday = Date(2001, 7, 15)
Datastore.put(e)

なんとなく、これにはしたくない。せっかくのScalaなんだし…という、感情的理由(^^;

trait利用

trait Person {
// val kind:String = "person" // ここに持たせる?
val name:Option[Property[String]]
val age:Option[Property[Int]]
}

val e = new Entity with Person
e.name = "Taro" // Property[String].valueに"Taro"を設定する or varにする
e.age = 10
Datastore.store("kind", e)

定義(trait)と実装(with)で分かれてるし、これはこれでありかも?と思ってる。 with使ったときのオーバーヘッドってどうなるんだろ?ってことを調べてない。

最近はこんなことも考えてる。

· 9 min read

今日(7/6 水)は勉強会で発表してきました。 資料は社名や人名が含まれてるところがあるので、調整後に後日公開するかも? 参加してくださった方には別途お送りする予定。

もくじ

話した内容はこんな感じ。
  1. Google App Engine概要(の概要)
  2. Scalaの紹介
  3. Google App Engine + Scalaで作ったTwitter bot
  4. ジオサービス
  5. apps script紹介

きっかけ

勉強会で話すきっかけになったのは職場で一緒に仕事をしている人に、 「勉強会で話してみない?」 と言われたこと。 いい機会だし、話してみるか…ということで話すことにしました。 この勉強会で聞いてくださったのは他社の方々。会社間の契約はあるし、数名は面識があるので、知らないわけじゃないけど、聞いてくださる方々は面識ないし、そもそも自社ではないのです。

初めは「20人くらいだし、話す内容はなんでもいいよ」と気楽に言われたので、気楽に考えてました。 「他の人は何を話すんだろ〜?」くらい気楽に。

少しずつ話が具体的になるに連れ、勉強会に近づくに連れ、すこ〜しずつ話が大きくなり、30人ほど出席するという反響ぶり!(人が増えたらビビるやん) 告知メールでは "講師" と書いてあるし、社内Ustreamするとか…広がりすぎですっ!(機器の都合でUst配信無くなったけど) 講師っていうか、情報共有しましょうよ〜みたいな感じにしか捉えてなかったのに、話す人俺だけ。

さらに、追い打ちをかけるかの如く、社内から3人ほど聞きにくると…Σ(゚Д゚) 社長来るし、Google API Expert来るし、賢い海藻猫来るし、もう大変。 Expertいる前でApp Engineの話をするってどうなのよ!? …と思っていたけど、実際、当日になったら、あまり顔を合わせないといえども自社の人だし、心強くも感じられるものでしたε-(´∀`*)ホッ

資料作成

今回はPreziを使って発表したんだけど、資料作成には結構時間かかりました。 まずはiPad2に思っていることを描き出し、それをマインドマップにまとめ、最終的にPreziに落としこむという手順。 iPad2に書いた時点で40ページ超えてて、それをマインドマップに書いたら結構広がった。 さらにPreziにしたらパスの数は130くらいに行きそうな勢いだったので、急遽方法を変え、Scalaの説明はソースコードのみで行いました。 これでも、パスの数は129…って、130くらいになりそうなのを抑えてもまだまだ多かったか...orz

発表

発表自体は、個人的には最低ラインは確保できたかな…と思ってる。 最低ラインですみません…なんだけど、自分としてはなんとか最低ラインまで持って行けて一安心…的な感じ。

事前に2回ほど通しで話してみたけど、ちょっとこれでは質がいいとは言えないな…と思っていたし、自分でも納得出来ていなかった。 今日は自分なりに気になっていたことを気を付けていたこともあって、気になっていた部分はだいぶ減ったと思ってる。 時間配分は前半少し取り過ぎた。聞いてくれる方がいるからには、伝えるところは伝えておきたいな…と思って、追加でちょっと話をした部分が追加の時間だろう。 そんなわけで、後半はちょっと急ぎ気味に進め、ほぼ1時間。 時間的にはよかったけど、時間的にも精神的にも、もう少し落ち着いて話をしたいところだ。 それでも、事前に話した時よりは落ち着いて話せたと思っている。

内容は目次に書いた項目を1時間くらいで話す予定だったため、どうしても説明が薄くなりがち。 今回のターゲットはApp EngineもScalaもほとんど知らない人だろうという想定だったから、あまり深いところは話さず、それらを組み合わせたbotの話や、ジオサービスの話を取り入れ、少しは楽しんでもらえたら…と思っていたんだけど、どうだったんだろう?

内容の薄さと話をカバーすべく、Preziを使ってよかったのかも?これについては少しは楽しめてもらえたと思う。 最後に話したapps scriptは興味がないのか、馴染みがないのか、懇親会でも話が出なかったなぁ。 App Engineよりも、Scalaよりも、Apps Scriptが一番お手軽なんだけど、そんな話をしなかったからか(^^;

まとめ

内容はともかく、練習していた時よりも本番の方が安定して話せたということがよかった。練習の方がよかったら悔やまれる。

仮に、発表がうまくいかなかったとしても、やらないよりやった方がいい経験になるし、自分が楽しまないと見ている人も楽しくないだろうし…ということで、ネガティブなことは考えず、一緒に楽しむことを考えていたのが一番大きいかも。

そんなわけで、自分本位に考えていたところもあり、お聞き苦しいところも多々あったと思いますが、ありがとうございました!

解放

6月はほぼ資料作成ばかりやってたから、やっと解放された感じ(笑) インラインのフレームを交換したいし、スラックラインを注文したいし、サイト構成などなど、色々と考えねば…。 少しずつ色々と進める予定。

· 6 min read

先日、Google Apps ScriptからGoogle App Engineのサービスを利用する際に管理者の判断を行いたかったのでそれについて調べていた。 自分ではある程度解決したと思っている。

発端

そんなとき、こんなmentionが飛んできた。

来月辺り、@vvakameにふやかされる可能性があるので、今のうちに親切に恩を売っておく目的でこれ書いてる。

今のところこうなのかな?と思っている

以下の確認はスクリプトエディタから実行したので、トリガーなどからの実行は未確認です。 テスト中なので一部は "???" 表記にしてます。

まずはOAuthによる認証について。

  • ???.appspot.comではOAuthによる認証が出来た
  • ???.mydomain.xyzではOAuthによる認証が出来なかった

続いて、OAuthが通った場合のユーザ情報について。

  • AppEngine側ではOAuthServiceFactoryからユーザ情報が取得できた
  • AppEngine側ではUserServiceFactoryからユーザ情報が取得できなかった
  • UserServiceFactoryからUser情報が取得できなかったので、管理者かどうか判断できない

所感

mydomain.xyzで認証が通らないのはそのドメインの信頼性を確保できないからということなのだろうか? だとしたら、証明書を登録することによってmydomain.xyzでもOAuthによる認証が通るのかな?と思いつつ、試してない。時間があったらやってみたいところだけど、優先度が下がってる。 mydomain.xyzのToken(key, secret)使ってても、appspot.comでの認証が通ってる。mydomain.xyzはDNSでgoogleの方を向いているから結局は同じということなのだろうか?これはなんとなくありのような、無しのような、微妙な感覚。

ソースコード(apps script)

以下がapps scriptのソースコード。
function initApps_() {
ScriptProperties.setProperty("http", "https://");
ScriptProperties.setProperty("appid", "?????");
ScriptProperties.setProperty("d", "appspot.com");
ScriptProperties.setProperty("consumerKey", "?????.appspot.com");
ScriptProperties.setProperty("consumerSecret", "appssecret");
}

function initMydomain_() {
ScriptProperties.setProperty("http", "https://");
ScriptProperties.setProperty("appid", "?????");
ScriptProperties.setProperty("d", "mydomain.xyz");
ScriptProperties.setProperty("consumerKey", "?????.mydomain.xyz");
ScriptProperties.setProperty("sonsumerSecret", "mydomainsecret");
}

function initOAuthUrl_() {
var http = ScriptProperties.getProperty("http");
var appid = ScriptProperties.getProperty("appid");
var domain = ScriptProperties.getProperty("d");

var ah = http + appid + "." + domain + "/_ah/";
ScriptProperties.setProperty("accessTokenUrl", ah + "OAuthGetAccessToken");
ScriptProperties.setProperty("requestTokenUrl", ah + "OAuthGetRequestToken");
ScriptProperties.setProperty("authUrl", ah + "OAuthAuthorizeToken");
}

// appspotへOAuth --> oauth: ken@mydomain.xyz / user: unknown
function oAuthAppspot() {
initApps_();
var url = "http://?????.appspot.com/oauth/auth";
oAuthTest_(url);
}

// mydomainへOAuth --> Unknown(OAuthRequestExceptionが発生している)
function oAuthmydomain.xyz() {
initMydomain_();
var url = "http://?????.mydomain.xyz/oauth/auth";
oAuthTest_(url);
}

// appspotへOAuth(mydomainのtoken) --> oauth: ken@mydomain.xyz / user: unknown
function oAuthAppspotMyKey() {
initMydomain_();
var url = "http://?????.appspot.com/oauth/auth";
oAuthTest_(url);
}

// mydomainへOAuth(appspotのtoken) --> Unknown(OAuthRequestExceptionが発生している)
function oAuthmydomain.xyzAppspotKey() {
initApps_();
var url = "http://?????.mydomain.xyz/oauth/auth";
oAuthTest_(url);
}

function oAuthTest_(url) {
url += "?" + Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd HH:mm:ss");
Logger.log(url);
try {
var response = UrlFetchApp.fetch(url, option_());
Browser.msgBox(response.getContentText());
} catch(e) {
var msg = "";
for (var i in e) {
msg += e[i] + "n";
}
Browser.msgBox(msg);
}
}

function option_() {
initOAuthUrl_();
var oAuthServiceName = "apps";
var accessTokenUrl = ScriptProperties.getProperty("accessTokenUrl");
var requestTokenUrl = ScriptProperties.getProperty("requestTokenUrl");
var authUrl = ScriptProperties.getProperty("authUrl");
var key = ScriptProperties.getProperty("consumerKey");
var secret = ScriptProperties.getProperty("consumerSecret");

var oAuthConfig = UrlFetchApp.addOAuthService(oAuthServiceName);
oAuthConfig.setAccessTokenUrl(accessTokenUrl);
oAuthConfig.setRequestTokenUrl(requestTokenUrl);
oAuthConfig.setAuthorizationUrl(authUrl);
oAuthConfig.setConsumerKey(key);
oAuthConfig.setConsumerSecret(secret);

var options = {
"oAuthServiceName" : oAuthServiceName,
"oAuthUseToken" : "always"
};

return options;
}

oAuthTest_メソッドでURLに時刻を付けてるのは、キャッシュを返されるような動作があったので、それを回避するため。

スクリプトでひとつ疑問。 ScriptPropertiesで "domain" をキーに指定した場合、getPropertyするとnullになる。これはうちだけ?

ソースコード(App Engine)

以下がApp Engineのソースコード。 言語はJavaじゃなくて、Scala使ってるし、オレオレフレームワーク使ってる。
class OauthController(request:Request, response:Response) extends Controller(request, response) {

def auth = {
try {
val oauth = OAuthServiceFactory.getOAuthService();
val oauthUser = oauth.getCurrentUser match {
case user if user != null => user.getNickname;
case _ => "unknown"
}
val user = UserServiceFactory.getUserService.getCurrentUser match {
case user if user != null => user.getNickname
case _ => "unknown"
}
val msg = "oauth: %s / user: %s".format(oauthUser, user)
response.getWriter.write(msg)
} catch {
case e:OAuthRequestException =>
response.getWriter.write(e.getMessage)
}
}
}

まとめ

今のところ、管理者かどうか判断は出来ていないけど、ユーザは判断できているので、それで凌ごうと思っている。必ずしも開発者(管理者)がアプリの管理者とは限らないので、これはこれでいいや…と思ってる。 お仕事じゃないので、うるさく言う人いないし(笑)