[Identity] Oracle Identity Cloudを使ってJiraとSSOを構成する方法/How to set up SSO Integration with Jira using Oracle Identity Cloud

原文はこちら。
https://blogs.oracle.com/cloud-platform/how-to-set-up-sso-integration-with-jira-using-oracle-identity-cloud

以前の記事では、Oracle Identity Cloud Serviceを利用して数分のうちにSlackとシングルサインオン(SSO)を構成する方法を実演しました。今回の記事では同様に、多くの人が使っているイシュー/プロジェクトトラッキングツールであるJira SoftwareとID統合を行う方法を実演します。
最初のステップはIdentityプロバイダのメタデータから署名証明書にアクセスすることです。証明書の情報を取得したら、次にJiraに管理者としてアクセスし、ユーザー管理コンソールからSAMLシングルサインオン接続を構成しましょう。
この接続の構成の際、Identity Provider Entity IDやSSO URLなどの基本的な情報が必要になります。最初のステップで取得した署名証明書を使い、パブリックx509証明書をこのページで生成しましょう。設定を保存したら、Oracle Identity Cloudに戻って、App CatalogからJiraを選び、アプリケーションとして追加しましょう。最後のステップとして、統合をアクティベートし、JiraにSSOを使ってアクセスできるようにしたいユーザーを追加しましょう。
Oracle Learning Library YouTubeチャンネルのこの動画では、SSOでのJiraとのID統合を行う方法を、ステップバイステップで説明しています。

包括的なセキュリティおよびアイデンティティプラットフォームについて知りたい方は、以下のURLにアクセスしてください。無料でお試しいただけます。
Oracle Identity Cloud Service
https://cloud.oracle.com/ja_JP/identity
Try for Free!
https://cloud.oracle.com/tryit

[Cloud]Oracle Developer Cloudのビルドパイプラインの一部としてコードマージを行う方法/Code Merge as part of a Build Pipeline in Oracle Developer Cloud

原文はこちら。
https://blogs.oracle.com/developers/code-merge-as-part-of-a-build-pipeline-in-oracle-developer-cloud























この記事ではOracle Developer Cloudでのパイプライン構成の一部として、コードのマージを行う方法を説明します。簡単に使えるビルド・ジョブ機能だけをこれを使って実現することができます。また、開発者が日々の開発作業を行う際に、どのようにこの機能が役立つかについても理解することができるでしょう。

新規Gitリポジトリの作成

ナビゲーションバーのProject Homeをクリックします。Projectページで使用するプロジェクトを選び(例ではDemoProjectを選択しています)、+ Create Repositoryボタンを押すと新規リポジトリが作成されます。この記事では、このリポジトリを使ってcode mergeを行います。
New Repositoryダイアログでは、リポジトリ名を入力します。例ではMyMergeRepoとしていますが、好きな名前を使ってください。Initialize repository with README fileオプションを選び、Createボタンを押しましょう。

新規ブランチの作成

ナビゲーションバーのGitをクリックします。GitページのRefsビューで、RepositoriesドロップダウンからMyMergeRepo.gitを選びます。+ New Branchボタンを押すと新規ブランチが作成されます。
New Branchダイアログでは、一意になるブランチ名を入力します。例ではchangeを使っていますが、好きな名前にしてください。適切なBaseブランチをドロップダウンリストから指定しましょう。例ではmasterブランチのみしか選択肢がありません。Createボタンを押し、新規ブランチを作成しましょう。

ビルドジョブ設定を作成する

ナビゲーションバーからBuildsをクリックします。Jobsタブで、+ Create Jobボタンを押すと、新規ビルドジョブが作成されます。
New Jobダイアログでは、ジョブ名として一意となる名前を指定しましょう。例ではMergeCodeとしていますが、好きな名前を入力してください。Use for Merge Requestチェックボックスにチェックを入れ、Create Newオプションを選択したら、ドロップダウンリストから任意のソフトウェアテンプレートを選んでください。マージを行う際に特に必要となる特定のソフトウェアバンドルなく、いずれのソフトウェアテンプレートにもデフォルトで含まれているソフトウェアバンドルだけで十分です。最後にCreate Jobボタンをクリックしましょう。
注意:VMテンプレートの構成とVMの構築に詳しくない場合、Set Up the Build Systemを参照してください。

Use for Merge Requestにチェックを入れてビルドジョブを作成すると、Source ControlタブのRepositoryBranchフィールドにマージリクエストパラメータが格納されます。そのままAutomatically perform build on SCM commitチェックボックスにチェックを入れましょう。

Build Parametersタブを見ると、GIT_REPO_URLやGIT_REPO_BRANCHなどのマージリクエストパラメータが自動的に追加されていることにお気づきでしょう。確認したら、Saveボタンを押しましょう。

マージリクエストの作成

ナビゲーションバーのMerge Requestsをクリックし、+ Create Merge Requestボタンを押しましょう。
New Merge Requestウィザードでは、Gitリポジトリ(MyMergeRepo)を選択し、ターゲットブランチ(master)とレビューブランチ(change)を選択します。まだ何もコミットしてないので、何も表示されません。Nextボタンをクリックして次のページに進みましょう。
Detailsページでは、Linked BuildフィールドでMergeCodeを選択し、また、レビュアーを設定します。このマージリクエストに紐づけたいissueがある場合は、Linked Issuesフィールドで設定しましょう。Nextボタンをクリックし、最後のページに移動します。
マージリクエストの説明欄のコメントは、デフォルトのものを使うこともできますし、編集することもできます。では、Createボタンを押してマージリクエストを作成しましょう。
Linked Buildsタブでは、MergeCodeビルドジョブがリンクされたビルドジョブとして表示されます。

ファイルを更新し変更をGitリポジトリにコミット

GitページでリポジトリのドロップダウンリストからMyMergeRepo.gitリポジトリを選択し、ブランチのドロップダウンリストからchangeブランチを選択します。そしてREADME.mdファイルのリンクをクリックしましょう。
鉛筆のアイコンをクリックしてファイルを編集します。
任意のテキストを追記し、Commitボタンをクリックします。

コードのコミットによりMergeCodeビルドジョブがトリガーされます。

リンクされたジョブのビルドが起動されると、Conversationタブに自動的にコメントが追加されます。MergeCodeのビルドが完了すると、マージリクエストが自動的に承認され、MergeCode自身がReview StatusリストのApproveセクションに追加され、マージリクエストにアサインされているレビュアーの承認待ちの状態になります。
レビュアーがマージリクエストを承認すると、レビューブランチにあるコードをターゲットブランチにマージできる状態になります。Mergeボタンをクリックすると、コードがマージされます。
注意:この例のマージリクエストではログインしているユーザーであるAlex Adminがレビュアーです。
ビルドジョブにMerge Requestパラメータを含めておくことにより、全てのコミットに対してコンフリクトが発生していないか、承認されているかのチェックを自動的に行うようにすることができます。マージリクエスト用のビルドジョブをリンクしておくと、ひとつのマージリクエストに複数のコミットが紐付られているような場合に有用です。マージリクエストに対してアサインされたレビュアーからのコードレビューと変更の承認が行われたのち、コードがターゲットブランチにマージされます。
日々の開発作業において開発者がチームメンバーと効率的に協働することを手助けしてくれるような機能です。
良いコーディングを!

[Cloud]Joining an Oracle Linux Client to an Active Directory Domain

原文はこちら。

これまでに思い出せないくらい多くの方法でLinuxユーザーアカウントを管理してきましたが、その中で一番良い方法だと思うのはWindowsを少々活用することです。Active Directoryは大規模なコンピューター、ユーザー、そしてグループを簡単に扱えるのと同様に、小規模なそれらを管理するのにも適しています。セットアップも簡単です。

始める前に

Active Directoryをすでにセットアップしてあり、また、そのドメインに参加させたいOracle Linuxが稼働するインスタンスが起動してある必要があります。まだActive Directoryを構成していない場合は、Creating Your Windows Active Directory Domain Servers in Oracle Cloud Infrastructureのホワイトペーパーに記載されている、Oracle Cloud Infrastructure上に素早く、また堅牢にActive Directoryを構成する詳細な方法を参照してください。
インスタンス上で以下の情報を収集します:
変数説明
ip-addressインスタンスのIPアドレス10.0.0.14
hostnameインスタンスの短縮ホストネームunicorn-painter-998
domainインスタンスのドメイン名(また、Active Directory realm)lilwoods.us
fqdnインスタンスのfully qualified domain name (上記IPアドレスに対しての)unicorn-painter-998.lilwoods.us
dns-ip-addressActive DirectoryのIPアドレス10.0.0.13
join-userドメインに参加する権限のあるActive Directoryユーザーmia427
admin-groupsudo権限を付与するActive DirectoryグループUnicorn-Admins

手順
  1. 以降のコマンドは全てスーパーユーザーを必要とするため、root権限に昇格します
    sudo -i
    
  2. /etc/resolv.confファイルを編集し、nameserverとしてActive DirectoryのIPアドレスを使用するようにしましょう。また、他のnameserverレコードは削除しておきます。デフォルトのnameserver (169.254.169.254)を、以下のように変更します。
    nameserver {dns-ip-address}
    例:
    nameserver 10.0.0.14
  3. /etc/hostsファイルの先頭行を以下のように編集し、インスタンスのip-address、fqdnおよびhostnameを記載しておきましょう。
    {ip-address} {fqdn} {hostname}
    
    注意:Oracle Cloud Infrastructureインスタンスでは、インスタンス生成時にインスタンス名からデフォルトのFQDNとhostnameが生成されます。ファイル内にインスタンスのIPアドレスに対して別のレコードが存在していないことを確かめてください。
    例:
    10.0.0.14 unicorn-painter-998.lilwoods.us unicorn-painter-998
    
  4. Acrive Directoryに接続するために使われているrealmdツールとその依存パッケージをインストールしましょう。
    yum -y install realmd sssd krb5-workstation krb5-lids samba-common-tools
  5. Active Directory realm (また、DNS domainでもあります)をdiscoverしましょう。
    realm discover ${DOMAIN}
    
    例:
    realm discover lilwoods.us
    
  6. Active Directory realmにjoinしましょう。
    realm join --verbose ${REALM} -U ${JOIN_USER}
    
    例:
    realm join --verbose lilwoods.us -U mia427@lilwoods.us
    
    プロンプトが出るので、adminパスワードを入力してください。
    Linuxサーバーが管理ドメインへの参加に成功すると、以下のようなメッセージが表示されます。
    Successfully enrolled machine in realm
    
  7. sudoersファイルを編集し、Adminsグループのメンバーにsudo権限を付与しましょう。
    visudo
    
    wheelグループがあるファイルの半分ほどのところまで移動し、このグループの下にActive Directoryグループ名をsudoers設定ファイルに追記しておきましょう。将来参照するときのために説明も追記しておきます。
    # Allow users in the admin group to run all commands
    {REALM}\\{AD-Group-Name} ALL=(ALL) ALL
    
    例:
    # Allow users in the Unicorn-Admins group to run all commands     
    %LILWOODS.US\\Unicorn-Admins ALL=(ALL) ALL
  8. /etc/ssh/sshd_configファイルを編集し、Active Directoryからの認証情報を受け入れるためにSSHサービス内でのパスワード認証を許可しておきましょう。PasswordAuthentication noPasswordAuthentication yesに変更します。
  9. 設定変更を適用するため、sshdを再起動します。
    systemctl restart sshd
    
これで完了です!インスタンスは以下の設定になりました:
  • Active Directoryに登録済
  • Active Directory内のユーザーがSSHログインアクセス可能
  • 新規ログイン時、ホームディレクトリスケルトンが生成される
  • Active Directoryのあるグループに所属するユーザーは、sudoアクセスが可能
  • このインスタンスからのKerberos認証が可能

[Cloud, Functions] Serverless Image Classification with Oracle Functions and TensorFlow

原文はこちら。
https://blogs.oracle.com/cloud-infrastructure/serverless-image-classification-with-oracle-functions-and-tensorflow

画像分類は、機械学習技術の実証でよく使われます。このエントリでは、最近発表されたクラウドサービスのOracle FunctionsでTensorFlowベースの画像分類アプリケーションを実行する方法をご紹介します。
TensorFlow
https://www.tensorflow.org/
Announcing Oracle Functions
https://blogs.oracle.com/cloud-infrastructure/announcing-oracle-functions
https://orablogs-jp.blogspot.com/2018/12/announcing-oracle-functions.html

Oracle Functions

Oracle Functionsはフルマネージドで高い拡張性を備える、オンデマンドのFunction as a Serviceプラットフォームで、エンタープライズクラスのOracle Cloud Infrastructure上に構築されています。
Oracle Cloud Infrastructure
https://cloud.oracle.com/ja_JP/cloud-infrastructure
基盤となるインフラストラクチャを気にせずにビジネスニーズを満たすコードを書くことに集中でき、実行中に消費されるリソースに対してのみ課金される、サーバーレス製品です。コードをデプロイして直接またはトリガーに応じて呼び出すことができ、アプリケーションの高可用性、スケーラビリティ、安全かつ監視対象とするために必要な、背後のすべての作業はOracle Functionsが担います。

Oracle Functionsはオープンソース、コンテナネイティブ、任意の環境、つまりクラウドまたはオンプレミスで実行できるサーバーレスのプラットフォームであるFn Projectをベースにしています。
Fn Project
http://fnproject.io/
Fn Projectのオープンソースディストリビューションをダウンロード、インストールし、functionをローカルで開発およびテストしてから、同じツールを使用してそのfunctionをOracle Functionsにデプロイできます。

What to Expect

詳細に入る前に、サーバーレス機械学習関数から期待できるものを見ていきましょう。セットアップして動作させると、アプリケーションを画像にポイントし、画像がどのようなものかを想定し、そしてその想定の確からしさをあわせて返します。

例えば、分類関数に渡した場合、以下の画像では次のように返します。
This is a ‘pizza’ Accuracy—100%

Photo by Alan Hardman on Unsplash

The Code

イメージ分類関数は既存のTensorFlowのサンプルをベースにしています。
Image Classification Example
https://github.com/tensorflow/models/tree/master/samples/languages/java/label_image
この関数はTensorFlow Java SDKを使っていて、この中ではJNI(Java Native Interface)を介してネイティブC++実装を利用しています。
Install TensorFlow for Java
https://www.tensorflow.org/install/lang_java

Function Image Input

画像分類関数はFn Java FDKを利用しており、このおかげでJavaでのfunctionの開発および実行プロセスがシンプルになります。

Java JDKを使う利点の1つは、functionに送られた入力をJavaのオブジェクトと型にシームレスに変換できることです。これには以下のものが含まれます。
Java API and runtime for fn
https://github.com/fnproject/fdk-java/
  • 文字列入力処理のようなシンプルなデータバインディング
  • JSONデータ型をPOJOにバインド。Jacksonを使って内部で実装しているため、カスタマイズ可能。
    Main Portal page for the Jackson project
    https://github.com/FasterXML/jackson
  • functionが受信もしくは返す生のFn Java FDKイベントの抽象化によって、生の入力を操作可能。
入力データと出力データのマーシャリング方法をカスタマイズしたい場合は、バインディングをさらに拡張できます。
Extending the Data Binding functionality
https://github.com/fnproject/fdk-java/blob/master/docs/ExtendingDataBinding.md
既存のTensorFlowのサンプルでは、入力として画像名のリスト(コード実行マシンに画像が存在する必要があります)を想定しています。この関数も同様に動作しますが、Fn Java FDKがもたらす柔軟なバインディング機能を使用している点が重要な違いです。classifyメソッドはfunctionのエントリポイントとして機能し、functionに渡されるイメージのraw byteを表すJavaバイト配列(byte[])を受け入れます。このバイト配列は、staticなTensor.create(byte[])メソッドを使ってTensorオブジェクトを作成するために利用されます。
Tensor
https://www.tensorflow.org/api_docs/java/reference/org/tensorflow/Tensor
public static Tensor<String> create (byte[])
https://www.tensorflow.org/api_docs/java/reference/org/tensorflow/Tensors#create(byte%5B%5D)
public class LabelImageFunction {
 public String classify(byte[] image) {
 ...
 Tensor<String> input = Tensors.create(image);
 ...
  }
}
完全なソースコードはGitHubからご覧いただけます。
Serverless image classification with functions & TensorFlow
https://github.com/abhirockzz/fn-hello-tensorflow

Machine Learning Model

通常、機械学習ベースのシステムは以下のフェーズで構成されています。
  • Training(学習):アルゴリズムに過去のデータ(履歴データ)を食わせて学習(パターンを導出)させ、モデルを構築する。多くの場合このプロセスは継続して実行される。
  • Predicting(予測):生成されたモデルを使い、学習フェーズで学んだ事実に基づき、新たな入力に対応する予測や出力を生成する。
このアプリケーションでは事前学習済みのモデルを使います。さらに便利なことに、分類ロジックが必要とするこのモデル(およびラベル)はfunctionそのもの(Dockerイメージの一部)と共にパッケージされています。これらはソースコードのresourcesフォルダにあります。

このことは、TensorFlow Servingのような専用のモデル提供コンポーネントを設定する必要がない、ということです。
TensorFlow Serving for model deployment in production
https://www.tensorflow.org/serving/

Function Metadata

func.yaml ファイルには、メモリ割り当てやタイムアウトのような属性値(このfunctionではそれぞれ1024MB、120秒が設定されています)を含む、functionのメタデータが記述されています。このメタデータは、(より単純な計算とは対照的に)画像分類アルゴリズムの(かなり)厳しい性質のために必要な値になっています。
schema_version: 20180708
name: classify
version: 0.0.1
runtime: java
memory: 1024
timeout: 120
triggers:
- name: classify
  type: http
  source: /classify
以下は設定している属性のサマリです。
  • schema_version:このファイルが従う仕様のバージョン
  • name:このfunctionをプッシュする際の名前とタグ
  • version:functionの現在のバージョン。デプロイ時にタグとしてイメージに追加する。
  • runtime:プログラミング言語ランタイム。この例ではJava。
  • memory (optional) :このfunctionの最大メモリ閾値。このfunctionが実行時にこの上限を超えると、functionは停止し、エラーメッセージをログ出力する。
  • timeout (optional) :function実行の最大許容時間
  • triggers (optional) :functionのトリガーを指定するためのトリガー・エンティティの配列。この例では、HTTPトリガーを使用。

Function Dockerfile

Oracle Functionsは、ビルドおよび実行時フェーズで一連の事前ビルド済みかつ言語固有のDockerイメージを使います。例えばJava functionの場合、fn-java-fdk-buildをビルドフェーズで利用し、実行時にはfn-java-fdkを使います。
fn-java-fdk-build
https://hub.docker.com/r/fnproject/fn-java-fdk-build/
fn-java-fdk
https://hub.docker.com/r/fnproject/fn-java-fdk/
以下はfunction用のDockerイメージ作成で使うデフォルトのDockerfileです。
FROM fnproject/fn-java-fdk-build:jdk9-1.0.75 as build-stage
WORKDIR /function
ENV MAVEN_OPTS -Dhttp.proxyHost= -Dhttp.proxyPort= -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.nonProxyHosts= -Dmaven.repo.local=/usr/share/maven/ref/repository
ADD pom.xml /function/pom.xml
RUN ["mvn", "package", "dependency:copy-dependencies", "-DincludeScope=runtime", "-DskipTests=true", "-Dmdep.prependGroupId=true", "-DoutputDirectory=target", "--fail-never"]
ADD src /function/src
RUN ["mvn", "package"]
FROM fnproject/fn-java-fdk:jdk9-1.0.75
WORKDIR /function
COPY --from=build-stage /function/target/*.jar /function/app/
CMD ["com.example.fn.HelloFunction::handleRequest"]
このDockerfileはマルチステージDockerビルドを使って(標準で)以下のアクションを実行します。
  • maven package およびmaven build
  • (COPYコマンドを使って)functionのJARファイルと依存関係をランタイムイメージにコピー
  • functionのコンテナが生成されたら、(CMDコマンドを使って)実行コマンドを設定
しかし、例えば3rdパーティのネイティブライブラリを組み込むために、Dockerイメージの作成をさらに制御する必要がある場合があるでしょう。そのような場合は、カスタムDockerfileを使いたいと思うでしょう。あなたのfunctionのレシピを定義する自由を手に入れるため、非常に強力です。やるべきことは、基本のDockerイメージ拡張する、これだけです。
Docker base images for various programming languages
https://github.com/fnproject/dockers
以下はこのfunctionで利用しているDockerfileです。
FROM fnproject/fn-java-fdk-build:jdk9-1.0.75 as build-stage
WORKDIR /function
ENV MAVEN_OPTS -Dhttp.proxyHost= -Dhttp.proxyPort= -Dhttps.proxyHost= -Dhttps.proxyPort= -Dhttp.nonProxyHosts= -Dmaven.repo.local=/usr/share/maven/ref/repository
ADD pom.xml /function/pom.xml
RUN ["mvn", "package", "dependency:copy-dependencies", "-DincludeScope=runtime", "-DskipTests=true", "-Dmdep.prependGroupId=true", "-DoutputDirectory=target", "--fail-never"]'
ARG TENSORFLOW_VERSION=1.12.0
RUN echo "using tensorflow version " $TENSORFLOW_VERSION
RUN curl -LJO https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-$TENSORFLOW_VERSION.jar
RUN curl -LJO https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow_jni-cpu-linux-x86_64-$TENSORFLOW_VERSION.tar.gz
RUN tar -xvzf libtensorflow_jni-cpu-linux-x86_64-$TENSORFLOW_VERSION.tar.gz
ADD src /function/src
RUN ["mvn", "package"]
FROM fnproject/fn-java-fdk:jdk9-1.0.75
ARG TENSORFLOW_VERSION=1.12.0
WORKDIR /function
COPY --from=build-stage /function/libtensorflow_jni.so /function/runtime/lib
COPY --from=build-stage /function/libtensorflow_framework.so /function/runtime/lib
COPY --from=build-stage /function/libtensorflow-$TENSORFLOW_VERSION.jar /function/app/
COPY --from=build-stage /function/target/*.jar /function/app/
CMD ["com.example.fn.LabelImageFunction::classify"]
maven buildのようなデフォルトのステップに加え、組み込んでいる追加のカスタマイズに着目してください。
  • (指示に従って)TensorFlowのセットアップを自動化し、TensorFlow Java SDKとネイティブJNI(.so)ライブラリを展開
    Install TensorFlow for Java
    https://www.tensorflow.org/install/lang_java
  • (Docker buildの第2段階の一部として)JNIライブラリーを/function/runtime/libにコピーし、SDK JARを/function/appにコピーして、実行時にこのfunctionで使用できるようにする

Deploying to Oracle Functions

先述の通り、オープンソースのFn CLIを使ってOracle Functionsをデプロイできます。最新バージョンであることを確認してください。
CLI tool for fnproject
https://github.com/fnproject/cli/
curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh
​以下のURLから直接ダウンロードすることもできます。
fnproject/cli - Releases
https://github.com/fnproject/cli/releases

Oracle Functions Context

Oracle Functionsを使用する前に、Oracle Cloud Infrastructureテナントに接続するようにFn Project CLIを構成する必要があります。

Fn Project CLIを最初にインストールすると、ローカル開発コンテキスト用に設定されます。そうではなく、Fn Project CLIをOracle Cloud Infrastructureテナントに接続するように設定するには、新しいコンテキストを作成する必要があります。コンテキスト情報は~/.fn/contextディレクトリ内の.yamlファイルに格納されます。このファイル内で、Oracle Functionsのエンドポイント、デプロイされた機能が属するコンパートメントのOCID、Oracle Cloud Infrastructureの構成ファイル、およびイメージのプッシュ先およびプル元のDockerレジストリのアドレスを指定します。

以下はコンテキストファイルの例です。
api-url: https://functions.us-phoenix-1.oraclecloud.com
oracle.compartment-id: <OCI_compartment_OCID>
oracle.profile: <profile_name_in_OCI_config>
provider: oracle
registry: <OCI_docker_registry> 

Oracle Cloud Infrastructure Configuration

Oracle Cloud Infrastructureの構成ファイルには、ユーザーの資格証明とテナントのOCIDが含まれています。
SDK and CLI Configuration File
https://docs.cloud.oracle.com/iaas/Content/API/Concepts/sdkconfig.htm
これらのエントリに対して異なる値を持つ複数のプロファイルを作成できます。そのため、oracle.profile属性を使ってCLIが利用するプロファイルを定義できます。

以下は構成ファイルの例です。
[DEFAULT]
user=ocid1.user.oc1..exampleuniqueID
fingerprint=20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34
key_file=~/.oci/oci_api_key.pem
tenancy=ocid1.tenancy.oc1..exampleuniqueID
pass_phrase=tops3cr3t
region=us-ashburn-1
[ORACLE_FUNCTIONS_USER]
user=ocid1.user.oc1..exampleuniqueID
fingerprint=72:00:22:7f:d3:8b:47:a4:58:05:b8:95:84:31:dd:0e
key_file=/.oci/admin_key.pem
tenancy=ocid1.tenancy.oc1..exampleuniqueID
pass_phrase=s3cr3t
region=us-phoenix-1
複数のコンテキストを定義でき、それぞれは異なるコンテキストファイルに保存されます。Functions開発環境に従って、正しいコンテキストに切り替えてください。
fn use context <context_name>

Create the Application

GitHubリポジトリのコンテンツをクローンするところから始めます。
git clone https://github.com/abhirockzz/fn-hello-tensorflow
以下はアプリケーションデプロイ時に必要なコマンドです。
fn create app <app_name> --annotation oracle.com/oci/subnetIds='["<subnet_ocid>"]'
  • <app_name>:新たなアプリケーションの名前
  • <subnet_ocid> :functionを実行するサブネットのOCID
以下は例です。
fn create app fn-tensorflow-app --annotation oracle.com/oci/subnetIds='["ocid1.subnet.oc1.phx.exampleuniqueID","ocid1.subnet.oc1.phx.exampleuniqueID","ocid1.subnet.oc1.phx.exampleuniqueID"]'

Deploy the Function

アプリケーション作成後、以下のコマンドでfunctionをデプロイできます。
fn deploy --app <app_name>
<app_name>はfunctionを追加するOracle Functionsのアプリケーションの名前です。

(Java SDKと対応するネイティブライブラリで)TensorFlow v 1.12.0を使いたい場合、以下のコマンドを使います。
fn -v deploy --app fn-tensorflow-app
特定のバージョンを選択することもできます。その場合は、functionのビルド前にpom.xmlファイルで指定することをお忘れなく。例えば、v 1.11.0を使いたい場合、以下のように設定してください。
<dependency>
 <groupId>org.tensorflow</groupId>
 <artifactId>tensorflow</artifactId>
 <version>1.11.0</version>
 <scope>provided</scope>
</dependency>
Tofunctionのデプロイ時にバージョンを指定したい場合、以下のように--build-arg(ビルド引数)を使います。
fn -v deploy --app fn-tensorflow-app --build-arg TENSORFLOW_VERSION=<version>
例えばv1.11.0を使う場合は以下のようです。
fn -v deploy --app fn-tensorflow-app --build-arg TENSORFLOW_VERSION=1.11.0
デプロイが無事に成功すると、functionは利用可能になっています。fn ls appsコマンドを使って現在デプロイされているアプリケーションをリスト表示すると、n-tensorflow-appが出てくるはずです。

Time to Classify Images!

前述の通り、このfunctionは入力として画像を受け取り、それが何であるかを正確さのパーセンテージと共に伝えます。

推奨された画像のいくつかをダウンロードして試すか、もしくはすでにコンピュータにある画像を使うことができます。呼び出し時にfunctionにイメージを渡すだけでOKです。
download_sample_images.sh
https://github.com/tensorflow/models/blob/master/samples/languages/java/label_image/download_sample_images.sh
cat <path to image> | fn invoke fn-tensorflow-app classify
はい、では試してみましょう。この画像でソンブレロを検出できますか?
cat /Users/abhishek/manwithhat.jpg | fn invoke fn-tensorflow-app classify

“366 • 9 • Gringo” (CC BY-NC-ND 2.0) by Pragmagraphr

結果
This is a ‘sombrero’ Accuracy — 92%
テリアはどうでしょうか。
cat /Users/abhishek/terrier.jpg | fn invoke fn-tensorflow-app classify

“Terrier” (CC BY-NC 2.0) by No_Water

結果
This is a 'West Highland white terrier' Accuracy - 88%
次は何を分類しましょうか?

Summary

シンプルでありながらも完全に機能する機械学習アプリケーションをクラウドにデプロイしました。試してみたいですよね?

Oracle Functionsは2019年に一般提供の予定ですが、現在Cloud Native Limited Availability Programを通じて選ばれたお客様に対してのみご利用いただけるようにしております。Oracle Functionsの詳細ならびにOracle Functionsへのアクセスのリクエストは、こちらから登録をお願いします。Oracle Functionsで使われている、基礎のオープンソーステクノロジーの詳細は、FnProject.ioをご覧ください。
FnProject
http://fnproject.io/

[misc.] Logico v1 is terminated and Logico Mk-Ⅱ is GA

江草家を長らくご愛顧いただきありがとうございます。

ロジ子のステルス性低下が顕著という課題に対処することを目的に江草家で家族会議をした結果、グレードアップが必要との結論にいたり、その結果、ロジ子はv1からMk-Ⅱに生まれ変わることになりました。
  • ブログは引き続きこちらを使いますが、将来移行する可能性があります。その際にはお知らせします。
  • 情報発信のためのTwitterアカウントはLogico Mk-Ⅱ (LogicoMk2)に変わります。
    Logico_jpは今後も継続しますが、江草家からの情報発信目的から離れます。
2011/01/19からおよそ8年間、どうもありがとうございました。今後、どこかでみなさまとお目にかかれる日がありましたら、「ロジ子発見!」とTwitterに書き込んでやってください(その前にステルス性を復活させるので、見つからないようにしますけどねw)。
今後はLogico Mk-Ⅱが皆様に色々情報をお伝えしてまいります。
今後ともどうぞよろしくお願いいたします。

江草ロジ子
Logico Mk-Ⅱ

[Cloud] Automated Generation For OCI IAM Policies

原文はこちら。
https://blogs.oracle.com/developers/automated-generation-for-oci-iam-policies

OracleのCloud Developer Evangelistとして、Oracle CloudのサービスやOracle Cloudの提供機能で遊ぶことがよくあります。これはもちろんOCI (Oracle Cloud Infrastructure) Compute ConsoleのIdentity and Access Management (IAM) のセクションでかなり色々やっているということなのですけどね。
Overview of Oracle Cloud Infrastructure Identity and Access Management
https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/overview.htm
IAMは非常に簡単なコンセプトで、他のクラウドベンダーのIAMを使ったことがあればご存知のことでしょう。IAMについては既に十分に説明されており、ドキュメントが簡潔でわかりやすいので、ここでは完全な概要を説明しませんが、想定より時間がかかってしまうタスクが、IAMポリシーの生成です。
Getting Started with Policies
https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policygetstarted.htm
OCIのIAMポリシーの構文は以下の通りです。
Allow <subject> to <verb> <resource-type> in <location> where <conditions>
構文自体はかなり簡単そうですね。そして実際にそうなのですが、よくある問題は、ポリシーの変数セクションに入れる値を覚えていなければならない、ということです。正確なグループ名、または使用可能な動詞とリソースタイプ、およびポリシーを適用したいコンパートメントの正確な名前を覚えておくのは面倒で、通常は2つまたは3つのタブを開いて正確な綴り、大文字/小文字を調べ、正しい動詞とリソースの種類を知るためにドキュメントをめくっています。そんなわけで、ポリシー生成にあたってもう少し楽にするために何かしようと決めました。そして、この問題に他にも苦しんでいる人がいらっしゃるのであればその方々に共有したいと考えました。

そこで、私のフラストレーションと怠惰から生まれた、OCIのIAMポリシー生成を支援する簡単なプロジェクトをご紹介します。このツールをコマンドラインから実行すると、各変数を選択するように求められます。あなたのOCIアカウントからの実際の値に基づいて利用可能な選択肢を選択できます。例えば、特定のグループを対象にしたポリシーの作成を選択した場合、このツールは選択可能なグループのリストを提示します。ツールには動詞やリソースタイプのリストが組み込まれているので、同様に選択することができます。毎回IAMポリシードキュメントを参照する必要はありません。以下はツールを実行中のイメージです。

コード自体は傑作ではありません。OCI CLIまたはSDKを介して公開されていないため、動詞やリソースタイプはハードコードされているからです。しかしながら動作し、ポリシー生成が少々楽になっています。ツール生成のコードはGitHubにありますので、ツールのアップデートや機能強化目的でプルリクエストを送ってください。
A simple Groovy tool to generate IAM policies for Oracle Cloud Infrastructure.
https://github.com/recursivecodes/oci-policy-generator
ツールはGroovyで書いているので、Groovyスクリプトまたはjava -jarを使って実行できます。もしバイナリを手に入れて試してみたいのであれば、最新のリリースを入手して試してみてください。
oci-policy-generator - releases
https://github.com/recursivecodes/oci-policy-generator/releases
このツールは、裏でOCI CLIを使用しており、必要に応じてOCI APIを照会しています。ポリシーを生成する前に、OCI CLIがマシンにインストールおよび設定されていることを確認しておく必要があります。
Command Line Interface (CLI)
https://docs.cloud.oracle.com/iaas/Content/API/Concepts/cliconcepts.htm
外部の依存関係を最小限に抑え、プロジェクトをできるだけ軽量に保ちながら価値を提供するために、SDKではなくCLIを使用することにしました。それに、OCI CLIは非常に素晴らしいものなので、Oracle Cloudを使用する場合は、間違いなくそれをインストールし、それに精通している必要があります。

是非ツールをチェックいただき、何か質問やフィードバックがありましたらいつも通り(原文の)コメント欄にコメントをお願いします。

[Cloud, Java] Controlling Your Cloud - Uploading Large Files To Oracle Object Storage

原文はこちら。
https://blogs.oracle.com/developers/controlling-your-cloud-uploading-large-files-to-oracle-object-storage

前回のエントリでは、OCI Java SDKでOracle Cloud Infrastructure(OCI)APIを操作する概要を説明しました。
Controlling Your Cloud - A Look At The Oracle Cloud Infrastructure Java SDK
http://blogs.oracle.com/developers/controlling-your-cloud-a-look-at-the-oracle-cloud-infrastructure-java-sdk
https://orablogs-jp.blogspot.com/2019/01/controlling-your-cloud-look-at-oracle.html
エントリ中で、SDKを掘り下げようとしたのは、OCI Object Storageへの大容量ファイルのアップロードを処理するためであると述べました。このエントリでは、実際にマルチパート・アップロードをやってみます。

先に述べたように、HTTP(Hypertext Transfer Protocol)はもともと大きなファイル転送を扱うことを意図しておらず、ファイル転送は通常(そして多くの場合、依然として)FTP(File Transfer Protocol)を使って処理されていました。しかし、Web開発者はグローバルに分散されたクライアントを扱っており、FTPはサーバーのセットアップ、カスタムデスクトップクライアント、さまざまなファイアウォールルール、および認証を必要とするため、最終的に大きなファイルをHTTP/Sを使って転送してしまうのです。状況が許せば、Bit Torrentがより良い解決策になるかもしれませんが、Web開発者が扱っている分散ファイルはほとんどの場合解決策にはなりません。過去数年にわたるHTTPの多くの進歩のおかげで、大きなファイル転送が扱いやすくなりました。主な進歩は、(「チャンク」または「マルチパート」ファイルアップロードとして知られる)Chunked Transfer Encodingです。
Chunked Transfer Encoding
https://en.wikipedia.org/wiki/Chunked_transfer_encoding
マルチパートアップロードに関する Oracleのサポートについては、以下のドキュメントで詳細を説明していますが、できる限り簡単に説明するとすれば、ファイルをいくつかの部分(「チャンク」)に分割し、(必要に応じて同時に)アップロードし、すべての部分がアップロードされたら元のファイルに再構築するというものです。
Using Multipart Uploads
https://docs.cloud.oracle.com/iaas/Content/Object/Tasks/usingmultipartuploads.htm
Java SDKを使ってマルチパートアップロードを実施するには、少なくとも3ステップ必要です。詳細を期したSDKのJavaDocsは以下からご覧いただけます。
Oracle Cloud Infrastructure Java SDK - 1.3.3
https://docs.cloud.oracle.com/iaas/tools/java/latest/
  1. Initiate the multipart upload
  2. Upload the individual file parts
  3. Commit the upload
SDKは上記手順の全てのためのメソッドだけでなく、既存のマルチパートアップロードのリストなどのための追加の手順のためのメソッドも提供しています。個々のファイルは最大50GBになる可能性があります。上記の3つのステップを完了するために必要なObjectClient(前の記事を参照)を使用するSDKプロセスを以下のように説明しています。
1. CreateMultipartUploadRequestDetailsインスタンスを含むCreateMultipartUploadRequestインスタンスを渡してObjectClient.createMultipartUploadを呼び出す。
ステップ1を詳説すると、「ファイルをアップロードしたい。オブジェクト名はfoo.jpg、コンテンツタイプはimage / jpegだ。後でそのファイルの異なるピースを関連付けられるよう、識別子を教えてくれるかな?」とAPIに尋ねれば、APIはCreateMultipartUploadResponseの形で識別子を返してくれる、ということです。以下がそのコード例です。
// route handler (Bootstrap.groovy):
post "/oci/upload-create", { req, res ->
    def objectName = req.queryParams("objectName")
    def contentType = req.queryParams("contentType")
    return JsonOutput.toJson( objectService.createMultipartUpload(objectName, contentType) )
}

// service method (ObjectService.groovy):
def createMultipartUpload(objectName, contentType="application/octet-stream") {
    CreateMultipartUploadDetails createMultipartUploadDetails = CreateMultipartUploadDetails.builder()
            .object(objectName)
            .contentType(contentType)
            .build()
    CreateMultipartUploadRequest createMultipartUploadRequest = CreateMultipartUploadRequest.builder()
            .namespaceName(namespaceName)
            .bucketName(bucketName)
            .createMultipartUploadDetails(createMultipartUploadDetails)
            .build()
    return objectClient.createMultipartUpload(createMultipartUploadRequest)
}
ではアップロードを作成するために、objectNameとcontentTypeという引数を渡して、/oci/upload-createを呼び出します。Postmanを使って呼び出していますが、これはブラウザでfetch()を呼び出すのと同じくらい簡単です。

これで今後の作業のためのアップロード識別子を取得しました(上図の2のuploadIdをご覧ください)。ではプロセスの2番目の手順に入ります。
2. uploadId、objectName、各パーツ用の連番(partNum)、チャンクされたファイルを含むUploadPartRequestのインスタンスを付けてObjectClient.uploadPart()を呼び出し、UploadPartResponseを受け取る。このレスポンスには、この後アップロードを完了するためにパーツの連番と共に保存しておくべきETagが含まれている。
以下は手順2のコード例です。
//route handler (Bootstrap.groovy):
post "/oci/upload-part", { req, res ->
    req.attribute("org.eclipse.jetty.multipartConfig", new MultipartConfigElement("/tmp"))
    HttpRequestWrapper reqRaw = req.raw()
    InputStream is = reqRaw.getPart("uploadPart").getInputStream()
    def objectName = req.queryParams("objectName")
    def partNum = req.queryParams("partNum").toInteger()
    def uploadId = req.queryParams("uploadId")
    return JsonOutput.toJson( objectService.uploadPart(is, objectName, uploadId, partNum) )
}

//service method (ObjectService.groovy):
def uploadPart(InputStream inputStream, String objectName, String uploadId, int partNum) {
    UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
            .namespaceName(namespaceName)
            .bucketName(bucketName)
            .objectName(objectName)
            .uploadPartBody(inputStream)
            .uploadId(uploadId)
            .uploadPartNum(partNum)
            .build()
    return objectClient.uploadPart(uploadPartRequest)
}
これがPostmanのステップ2の呼び出しです。アップロードはファイルの各パートに対して1回実行されました。最後の手順で使用するため、ETag値を各パーツの連番(partNum)と共に保存します。


最後の手順3でアップロードが完了します。
3. objectName、uploadId、そしてCommitMultipartUploadPartDetailsの配列を含むCommitMultipartUploadDetailsインスタンスを含むCommitMultipartUploadRequestインスタンスを渡して、ObjectClient.commitMultipartUpload()を呼び出す。
ややこしそうに見えますが、そnSounds a bit complicated, but it's really not.  The code tells the story here:
//route handler (Bootstrap.groovy):
post "/oci/upload-commit", { req, res ->
    /*
    expects a JSON object in the request body that looks like this:
    {
        uploadId: "",
        objectName: "",
        uploads: [
            {
                partNum: 1,
                ETag: "",
            }
        ]
    }
    */
    Map body = new JsonSlurper().parseText(req.body())
    def details = []
    body.uploads.each { Map file ->
        details << CommitMultipartUploadPartDetails.builder()
                .partNum(file.partNum)
                .etag(file.ETag)
                .build()

    }

    return JsonOutput.toJson( objectService.commitMultipartUpload(body.objectName, body.uploadId, details) )
}

//service method (ObjectService.groovy):
def commitMultipartUpload(String objectName, String uploadId, List partDetails) {
    CommitMultipartUploadDetails commitMultipartUploadDetails = CommitMultipartUploadDetails.builder().partsToCommit(partDetails).build()
    CommitMultipartUploadRequest commitMultipartUploadRequest = CommitMultipartUploadRequest.builder()
            .namespaceName(namespaceName)
            .bucketName(bucketName)
            .objectName(objectName)
            .uploadId(uploadId)
            .commitMultipartUploadDetails(commitMultipartUploadDetails)
            .build()
    return objectClient.commitMultipartUpload(commitMultipartUploadRequest)
}
呼び出すと、マルチパート・アップロードのコミットの完了を確認するシンプルなレスポンスが返ってきます。Object Storageのバケットに移動すると、アップロードされ再構築されたファイルの詳細を確認できます。



そして、私たちがあらかじめ決められたURLで当該URL(もしくはバケットが公開されていれば直接)アクセスすれば、その画像を見ることができます。今回の場合は、ペットのMosesの写真です。



説明した通り、マルチパート・アップロード用のOracle SDKは、必要な手順に分類されていればかなり簡単に利用できます。適切なバックエンドサービスを利用できるのであれば、マルチパートアップロードを支援するためのフロントエンドライブラリが多数あります(今回は、MacBookのsplitコマンドを使って単純に分割しました)。