Corredor

ウェブ、プログラミングの勉強メモ。

Oracle Java Cloud Service (JCS) を PSM CLI で操作してみる

Oracle Java Cloud Service (JCS) という PaaS を使ってみた。サーバの台数を指定するだけで、クラスタリングされた WebLogic Server が立ち上がり、あとはアプリをデプロイするだけというサービスだ。

Oracle Cloud の「PaaS」は、Oracle Cloud Infrastructure という IaaS 環境に、PaaS が自動的に作ったリソースを間借りして配備する形になる。JCS インスタンスは「ManagedCompartmentForPaaS」というコンパートメント内に自動配備される。

PaaS といいながらほとんど IaaS で、SSH 接続はできるし、OCI 管理画面から Load Balancer や Security List などのネットワーク構成を設定できたりするし、通常は「WLS をプリインストールした VM を払い出してくれるだけのサービス」としか思えない。一応、スケールアウト (台数増)・スケールイン (台数減) をボタン一つで簡単にできるといったメリットもあるが、WLS クラスタを保つためなのか、謎に管理用の Oracle DB を作る必要があったりして、課金がエグい。

そんな残念ポイントの多い、愛されキャラの JCS だが、コイツも、以前紹介した PSM CLI で操作できる。

neos21.hatenablog.com

以前紹介した時は、Oracle Application Container Cloud (ACC) という別の PaaS (コチラは Heroku とかに近いかな) を操作するために PSM CLI を使ったが、PSMPaaS Service Manager の略なので、このコマンドラインツールでその他の Oracle PaaS も操作できるというワケだ。

PSM CLI のダウンロード方法

以前の記事でも紹介したが、PSM CLI のダウンロード方法が若干分かりにくいので、改めて今回はスクリーンショット込みで紹介する。

まずは Oracle Cloud My Services より「Java」サービスを選び、Java Cloud Service の管理コンソール画面に遷移する。

そしたら右上のユーザアイコンを押下し、「ヘルプ」から「Download Center」を選択する。

f:id:neos21:20190922211143p:plain

この「ダウンロード・センター」さえ出せれば後は流れでイケるのだが、ココが分かりにくい。

Download Center のダイアログが以下のように開いたら、ダウンロードアイコンを押せば、PSM CLI の Zip ファイルがダウンロードできる。

f:id:neos21:20190922211151p:plain

あとはダウンロードした psmcli.zip を、pip3 でインストールすれば良い。

f:id:neos21:20190922211158p:plain

$ sudo pip3 install -U psmcli.zip

$ psm --version でバージョンが確認できたらインストールは完了。本稿執筆時点では v1.1.28 だった。

PSM CLI の初期設定

次に、CLI が操作する対象の環境を指定しないといけない。コマンドは $ psm setup で開始できるのだが、この中で特に迷うのは __「idcs- から始まるアイデンティティ・ドメイン文字列」とやらをどうやって知ったら良いか、という点だろう。

$ psm setup
Username:  # 【ユーザ名】
Password:  # 【パスワード】
Retype Password:  # 【パスワード 再入力】
Identity domain:  # 【「idcs-」から始まるアイデンティティ・ドメイン文字列】
Region [us]:  # リージョン。US ならこのまま Enter、日本リージョンにしたければ「aucom」と入力する
Output format [short]:  # 結果の出力形式。空白のまま Enter で良い、JSON 形式にしたければ「json」と入力する
Use OAuth? [n]:  # 空白のまま Enter
----------------------------------------------------
'psm setup' was successful. Available services are:

いくつか方法があるので、簡単な方法を2つほど紹介しておく。

1. IDCS (Identity Cloud Service) の URL から取得する

「Oracle Cloud アカウントのサインイン」画面や、IDCS 管理画面などにアクセスした時の、URL 文字列から取得できる。JCS 管理コンソール画面に到達するまでの間に通り過ぎている画面の URL から確認できるであろう、ということだ。

f:id:neos21:20190922211206p:plain

https://idcs-00000000000000.identity.oraclecloud.com/ というような URL になっていると思うので、この文字列から idcs-00000000000000 部分を抜き取れば良い。

2. JCS インスタンス詳細画面の「Instance Details」から取得する

JCS のアプリケーションインスタンスを作ったあと、詳細画面に移動し、右上にある「縦に並んだ3点リーダ みたいなアイコン」、コレが「Instance Details」アイコンなのだが、コレを押下する。

すると「Instance Details」というダイアログが表示され、その中に「アイデンティティ・ドメイン:」という項目があるので、ココから idcs- で始まる文字列を取得できる。

f:id:neos21:20190922211212p:plain

コレを $ psm setup 時に指定すれば良い。

JSON ファイルを読み込ませて psm setup を一発で終わらせる

ちなみに、対話形式になる $ psm setup が面倒であれば、以下のような JSON ファイルを用意しておいて、それを流し込むことで初期設定を終えることもできる。

  • psm-setup-payload.json (ファイル名は適当に)
{
  "username"      : "【ユーザ名】",
  "password"      : "【パスワード】",
  "identityDomain": "【「idcs-」から始まるアイデンティティ・ドメイン文字列】",
  "region"        : "【リージョン。「us」とか「aucom」とか】",
  "outputFormat"  : "【結果の出力形式。「short」とか「json」とか】"
}

以下のように -c オプションを使い、ファイル名を指定して実行すれば良い。

$ psm setup -c psm-setup-payload.json

CI/CD パイプラインの中で自動化したりする時にやりやすいかも。

PSM CLI でできる JCS の主な操作

PSM CLI を使えば、JCS の色々な操作ができるが、中でもよく使いそうなモノを挙げておく。

インスタンス一覧を取得する

$ psm jcs services

コレで作成してあるインスタンスの一覧が取得できる。出力形式を JSON にし、jq でパースすると、インスタンス名と状態だけを引っ張ってきたりしやすい。

$ psm jcs services --output='json' | jq -r '.services | to_entries | map(.key + " : " + .value.state)[]'

こんな感じ。

インスタンスを起動する

JCS インスタンスを起動するためのコマンド。実行するためには「ペイロード・JSON ファイル」が必要になる。この JSON ファイル次第で、クラスタ構成のサーバ群のうち、一部だけを起動・停止したりできるらしい。ただ、基本的には何台構成になっていようと、「全部起動する」「全部停止する」だろうから、お決まりの内容で良い。

# ペイロード・JSON ファイルを生成しておく
$ echo '{ "allServiceHosts": true }' > ./payload.json

# インスタンスを起動する
$ psm jcs start --service-name='【インスタンス名】' --config-payload='./payload.json' --output-format='json' --wait-until-complete='true'

--wait-until-completetrue にしておけば、インスタンスの起動が完了するまでプロンプトが返って来なくなる。インスタンスの起動を待って次の処理をしたい、といったスクリプトを書く時には良いかも。起動命令だけ出しておけば良いのであれば false を指定する。

インスタンスを停止する

起動と停止はほとんど同じ。ペイロード・JSON ファイルも同じ内容が使い回せる。

# ペイロード・JSON ファイルを生成しておく
$ echo '{ "allServiceHosts": true }' > ./payload.json

# インスタンスを起動する
$ psm jcs stop --service-name='【インスタンス名】' --config-payload='./payload.json' --output-format='json' --wait-until-complete='true'

以上

とりあえずこんなところか。

コマンドラインで色々操作できるのは大変便利だ。

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかるJava入門 第2版 (スッキリシリーズ)

スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)

スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)

シェルスクリプトの Lint ツール「shellcheck」を使ってみた

日頃、Bash で簡単なスクリプトを書くことがある。何もインストールされていないマシンでも、とりあえず書いて実行できるから、未だ活用する機会は多い。

しかし、シェルスクリプトは独特の構文が多く、現代的な言語に慣れ親しんだ人が片手間に書くには罠が多いと感じている。

以前 bats というテストツールを紹介したが、コレは実際にスクリプトを実行してみて、その結果をテストするツールだった。

neos21.hatenablog.com

そうではなく、実行前にチェックできるような Lint ツールはないのだろうか、と思い調べたところ、shellcheck というツールを見つけた。

様々な環境向けにインストール手順が用意されている。

  • MacOS なら Homebrew で簡単に入る
    • $ brew install shellcheck
  • Windows なら Chocolatey や、Git SDK に付属の pacman でインストールできる
    • PS1> choco install shellcheck
    • $ pacman -S shellcheck

インストール後は、

$ shellcheck ./example.sh

という風に叩くだけで構文チェックができる。

警告の位置や理由も分かりやすく、詳細は shellcheck の GitHub Wiki に記載されているので、それを読みながら修正していけば良い。

shellcheck での警告を無視するには、スクリプト内にコメントで示せば良い。この辺りは TSLint や ESlint の disable-next-line 的な感じだ。

#!/bin/bash

# 変数展開はダブルクォートで囲むべき、というエラーを無視する

# shellcheck disable=SC2086
my_variable=$my_value

なお、ちょっと試すだけなら、公式サイト上にスクリプトを貼り付けての検出もできるので、試しに使ってみると良いだろう。

さらに、GitHub Actions の実行基盤には shellcheck がプリインストールされているので、何の事前準備もなくいきなり

- run: shellcheck ./my-script.sh

と Lint ジョブを実行したりもできてしまう。超絶便利!

シェルスクリプトは書き手のスキルと品質が他の言語よりも密接に比例する言語だと思うので、こうした Linter を活用しての品質向上が大切になってくるだろう。チーム内での水準向上のためにも、活用してみてほしい。

覚えて便利 いますぐ使える!シェルスクリプトシンプルレシピ54

覚えて便利 いますぐ使える!シェルスクリプトシンプルレシピ54

詳解 シェルスクリプト

詳解 シェルスクリプト

Git For Windows SDK に expect コマンドが入っていなかったので pacman でインストールする

パスワードを使って SSH 接続する時に、expect コマンドを使うと、入力を自動化できたりする。

neos21.hatenablog.com

このシェルスクリプトを作ったのは MacOS だったので、Windows でも同じことをしたくなった時に、GitBash に expect コマンドが入っていなくてビックリした。

普通の GitBash にはパッケージ管理ツールの pacman が入っていないが、Git For Windows SDK なら入っているので、コレを使って expect コマンドをインストールしてやる。

neos21.hatenablog.com

$ pacman -S expect

コレで expect コマンドが使えるようになった。expect 内で使える spawnsendinteract なども正常に動く。

レトロアーケード <パックマン>

レトロアーケード <パックマン>

GitHub Actions を触ってみた

GitHub 上で CI/CD を実現できるコンテナ・パイプライン機能である GitHub Actions を使ってみた。

お試ししたリポジトリは以下。

github.com

Effective DevOps ―4本柱による持続可能な組織文化の育て方

Effective DevOps ―4本柱による持続可能な組織文化の育て方

The DevOps ハンドブック 理論・原則・実践のすべて

The DevOps ハンドブック 理論・原則・実践のすべて

  • 作者: ジーン・キム,ジェズ・ハンブル,パトリック・ボア,ジョン・ウィリス
  • 出版社/メーカー: 日経BP
  • 発売日: 2017/07/04
  • メディア: Kindle版
  • この商品を含むブログを見る

DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する (DEV Engineer’s Books)

DevOps導入指南 Infrastructure as Codeでチーム開発・サービス運用を効率化する (DEV Engineer’s Books)

  • 作者: 河村聖悟,北野太郎,中山貴尋,日下部貴章,株式会社リクルートテクノロジーズ
  • 出版社/メーカー: 翔泳社
  • 発売日: 2016/10/14
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

まずはテキトーに動かしてみる

使い方がよく分からないが、いきなり解説記事を読んでもやっぱりよく分からないので、試しに動かしてみる。

新規リポジトリを作り、「Actions」タブに移動する。

f:id:neos21:20191118140935p:plain

「Simple workflow」というサンプルっぽいヤツを試してみる。「Set up this workflow」ボタンを押す。

すると次のようなエディタ画面に移動する。自分で調べながらコメントを付け足してみた。

f:id:neos21:20191118140948p:plain

GitHub 画面上でこのファイルをコミットしてみると、早速ワークフローが動いた。トリガーとなるイベントを on: [push] と実装していたので、GitHub 画面上でコミットした場合は git push と同じ扱いになり、動作したというワケ。

f:id:neos21:20191118140958p:plain

ジョブを選択し、右端の3点リーダアイコン から View raw logs を押下すると、詳細なログが見える。

f:id:neos21:20191118141008p:plain

見てみると、確かにワークフローで実装していた echo コマンドの動作が確認できた。

f:id:neos21:20191118141015p:plain

Secret : クレデンシャル情報を渡してみる

続いて、よくありそうな仕組みとして、アクセストークンやパスワードなどのクレデンシャル情報を別に定義しておいて、ジョブ内で使用するというモノだ。

GitHub 画面の「Settings」タブより「Secrets」メニューに進み、「Add a new secret」リンクを押してシークレットを追加する。

f:id:neos21:20191118141022p:plain

今回はサンプルとしてどうでもいい文字列を追加した。my-password-value が、パスワードとして使用する文字列の「テイ」だ。

f:id:neos21:20191118141029p:plain

追加するとこのような画面になる。一度追加したシークレットは、中身を参照したり変更したりできないので注意。値を変更したい場合は一度「Remove」してから同名で作成することになる。

f:id:neos21:20191118141035p:plain

このシークレットを、ワークフロー内のシェルスクリプトで利用してみる。シェルスクリプト内の環境変数として利用できるようにするには、env プロパティにてシークレットを渡しておく必要がある。

f:id:neos21:20191118141042p:plain

- name: Run a multi-line script
  env:
    NEOS_EXAMPLE_PASSWORD: ${{ secrets.NEOS_EXAMPLE_PASSWORD }}
  run: |
    echo "This is Secret : [ ${NEOS_EXAMPLE_PASSWORD} ]"
    echo "${NEOS_EXAMPLE_PASSWORD}" > ./test.txt
    cat ./test.txt
    echo 'Finished'

ちょっとイジワルだが、シークレット情報を echo したり、ファイルに書き出して cat したりしてみる例だ。

コレをコミットして実行させてみたが、ログには一切パスワード文字列が出力されなかった。コレは安全である。

f:id:neos21:20191118141049p:plain

ちなみに、ワークフローの YAML ファイルに問題があったりすると、次のようにエラーとなる。

f:id:neos21:20191118141055p:plain

成功・失敗・実行中というステータスの他、「手動でジョブを中断 (Cancel)」ということもできる。

f:id:neos21:20191118141103p:plain

もう少し複雑な例として、Node.js スクリプトから、あるサーバに FTP 接続する、というスクリプトを作ってみた。

  • ./.github/workflows/nodejs.yaml
name: Node CI
on: [push]
jobs:
  build:
    name: Node.js Job
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
      uses: actions/checkout@v1
    - name: Use Node.js v10
      uses: actions/setup-node@v1
      with:
        node-version: '10.x'
    - name: Run npm Scripts
      env:
        MY_FTP_PASS: ${{ secrets.MY_FTP_PASS }}
      run: |
        npm install
        npm run ftp

package.jsonscripts にて、npm run ftp が動作するよう npm-run-scripts を定義しておく。

{
  "scripts": {
    "ftp": "node ftp.js"
  }
}

ftp.js 内の実装、promise-ftp という npm パッケージを使って FTP 接続するようにしている。シークレットで定義した MY_FTP_PASS を環境変数から読み取るため、次のように実装している。

const PromiseFtp = require('promise-ftp');
const promiseFtp = new PromiseFtp();

promiseFtp.connect({
  user    : 'example-user',
  password: process.env.MY_FTP_PASS,
  host    : 'example.com'
})
  .then((serverMessage) => {
    console.log('★ Connected ', serverMessage);
  });

Node.js は process.env.MY_FTP_PASS という風に書くことで環境変数を参照できるので、このように書いている。

コレを実行してみると、無事シークレット情報が渡されて正常動作したのだが、全角文字 (上のコードの 部分) が文字化けしていた。

f:id:neos21:20191118141109p:plain

日本語のログ出力には対応していなさそうなので、注意が必要だ。

結構使えるやんけ!

以上がザッと使ってみた例。結構使えそうだ。

構文の勉強

もう少し使い方を調べるため、以下の公式の記事を見てみた。

最初はなかなかとっつきにくかったが、ひとしきりサンプルの Workflow や Action を使ってみた後に読むとよく分かった。

  • ワークフロー (1ファイル・トリガーとなるイベントを定義できる単位) → ジョブ (ワークフロー内で行う処理の塊) → ステップ (ジョブ内の1つの処理) という関係
  • ワークフローは複数作成できる。それぞれのワークフローに同じ on イベントを指定しておくと、並列実行される
  • ジョブはデフォルトで並列実行されるが、jobs.【Job ID】.needs で依存ジョブを指定すれば順序の制御もできる
    • needs: job1 とか needs: [job1, job2] とか書く
  • jobs.【Job ID】.runs-on は、そのジョブを実行するホスト環境
    • コレ自体も仮想環境ではあるが、イメージ的には Jenkins サーバみたいに、1つのジョブを実行するマシン1台、と捉えて良い。CPU や RAM などのスペックが一応公開されている
    • 1つのジョブにつき1つのホスト環境を指定した上で、jobs.【Job ID】.containerjobs.【Job ID】.steps.uses でさらに Docker コンテナを指定したりできる
    • runs-on で指定したデフォルト環境ではグローバルにコマンドが足りなかったりする時は、ジョブ単位やステップ単位で Docker コンテナないしは Actions を利用することで拡張できるイメージ
  • jobs.【Job ID】.steps.name は省略できる
  • Action 1つは、1つの Step として実行することになる
    • Action とは「再利用可能なコードの単位」。コマンドを提供する、もしくはコマンドを実行する Docker コンテナを指定する、ぐらいのイメージでいいかな
    • uses: docker://apline:3.8 のように DockerHub のイメージを直接指定して使ったりもできる
  • jobs.【Job ID】.steps.run でシェルコマンドを実行できる
    • shell プロパティで PowerShell やコマンドプロンプトなども設定できる (runs-on で指定した環境が Windows じゃないとダメ)
    • Windows マシンでも shell: bash は動作する。GitBash が使用されるようだ

その他、構文に関しては以下の記事が参考になった。

他に何ができるの?の参考に

その他にどんなことができそうかは、具体的なコードを見た方がイメージが湧くと思うので、Qiita で色々記事を集めてみた。参考までに。

以上

実行基盤に Ubuntu だけでなく、Windows と MacOS も使えるようなので、クロスブラウザテストや iOS アプリのテストなんかもできそうだ。

無料でガンガン使えるので、どんどん活用していこうと思う。