少し工夫してGoogle Cloud Storage連携した話

この記事は [ウェブクルー Advent Calendar 2017](https://qiita.com/advent-calendar/2017/webcrew)の9日目の記事です。
昨日は@kadotaさんの「[WEBプッシュ通知の実装方法について](https://qiita.com/kadota/items/e83b853a4014234555eb)」でした。

## 背景
アプリケーションサーバーとして動いているCentOS 5上で動いているJavaアプリケーション(Java6)でGoogle Cloud Storage(以下、GCS)との連携が必要になったのですが、
すこしアクロバティックな方法で実現したので今回記事にしてみました。

## 一般的な連携方法
Javaアプリケーションでの一般的な連携方法は[Google Cloud Client Library for Java](https://github.com/GoogleCloudPlatform/google-cloud-java)を用いてGCSとの連携させることでしょう。  
実際に他アプリケーションでGCS連携が必要な機能を実装したときはGoogle Cloud Client Library for Javaを用いてGCSとの連携を図りました。

ただし、Google Cloud Client Library for JavaはJava 7以上の実行環境が求められます。  
今回、連携するアプリケーションのJavaのバージョンがJava 6だったので別の手段が求められました。

## 採用した連携方法
**CentOS5に[CLOUD SDK](https://cloud.google.com/sdk/)をインストールしてJavaの外部呼出しでCLOUD SDKコマンドを実行する**

## Cent OS 5へのCLOUD SDKのインストール
Cent OS 5に対してCLOUD SDKをインストールする手順は大きく分けて以下になります。

1. Python2.7のインストール
2. CLOUD SDKのインストール

それぞれ注意点踏まえて説明します。

### Python2.7のインストール

CLOUD SDKではPython2.7がインストールされていることが求められます。
Cent OS 5にデフォルトで設定されているPythonのバージョンは2.4です。
なのでまずはPythonのバージョンアップから始めます。

#### 注意点
**Cent OS 5でyumを使ったPythonアップデートはできないと思ったほうが良い**
**Cent OS 5でyumを使ったPythonアップデートはできないと思ったほうが良い**
**Cent OS 5でyumを使ったPythonアップデートはできないと思ったほうが良い**

大切なことなので3回言いました。

google先生に「centos python アップデート」で検索するとyumを用いた方法がヒットすることもありますが、Cent OS 5ではyumリポジトリを用いたPythonアップデートはできないと思ったほうが良いです。

Cent OS 5の公式yumリポジトリはEOLになっていますし、
リポジトリをミラーサイトに置き換えても`centos-release-scl-rh(Software Collections for CentOS)`などのyum installでこけます。

地道に圧縮ファイルから解凍するやり方でアップデートを目指しましょう。

#### 実際の手順

1. 圧縮ファイルのダウンロードと解凍

    ```
    wget --no-check-certificate  https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz
    tar xvzf Python-2.7.9.tgz
    ```

2. Pythonのインストール

    ```
    cd Python-2.7.9
    ./configure --prefix=/usr/local
    make
    make altinstall
    ```

3. Pythonの置き換え

    ```
    mv /usr/bin/python /usr/bin/python_bk
    ※既存Pythonモジュールのバックアップ
    cp -r ./python2.7 /usr/bin/python
    python -V
    ※「Python 2.7.9」が表示されればよい
    ```

### CLOUD SDKのインストール

1. 圧縮ファイルのダウンロードと解凍

    ```
    cd /usr/local
    ※CLOUD SDKの配置場所を上記とする

    wget https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-158.0.0-linux-x86_64.tar.gz?hl=ja
    tar xfvz google-cloud-sdk-158.0.0-linux-x86_64.tar.gz\?hl\=ja
    ```

2. CLOUD SDKのインストール

    ```
    ./google-cloud-sdk/install.sh
    ※パス補完の設定は実行しないでよい
    ```

3. CLOUD SDKインストール確認

    ```
    /usr/local/google-cloud-sdk/bin/gcloud --help
    ※スクリプトが表示されればインストールできている
    ```

## Javaアプリケーションでの外部呼出し
アプリケーションサーバーにCLOUD SDKをインストールしたら、あとはJavaアプリケーションでSDKコマンドを外部呼出しで実行します。

アプリケーションサーバーからGCSへのファイルアップロードの手順を記載します。

1. gcloud authによる承認付与
2. gsutilによるアプリケーションサーバーからGCSへのアップロード

### 実際のJavaソース

1. gcloud authによる承認付与

    サービスアカウントを使用して承認付与を実施している
    詳しくは[Cloud SDK ツールの承認](https://cloud.google.com/sdk/docs/authorizing?hl=ja)を参照

    ```java
    ProcessBuilder pb = new ProcessBuilder({"/usr/local/google-cloud-sdk/bin/gcloud", "auth", "activate-service-account", "--key-file", "[サービスアカウントキーファイル]"});
    process =pb.start();
    processRes = process.waitFor();
    // processResの結果によってエラーハンドリング実施
    ```


2. gsutilによるアプリケーションサーバーからGCSへのアップロード


    ```java
    ProcessBuilder pb = new ProcessBuilder({"/usr/local/google-cloud-sdk/bin/gsutil","mv","[アップロードファイルのパス]","[アップロード先GCSバケットURL]"});
    process =pb.start();
    processRes = process.waitFor();
    // processResの結果によってエラーハンドリング実施
    ```

## 結び
「Google Cloud Client Library for Javaが使えない状態でGCS連携!? どうしよう！！」という多少のパニックから始まり、「CentOS 5、デフォルトのPythonが2.4!? どうしよう！！」、「yumつかえない!? どうしよう！！」、「SDKコマンド外部呼出の成功判定がわからない!? どうしよう！！」といったことが多々ありましたが、色々サイトをあさったり、上司からアドバイスを受けたりして結果的にはしっかりと実装できました。  
当たり前のことですが、「～できない」で思考停止するのではなく、「じゃあ～のアプローチを試そう」といった試みる姿勢ってやっぱり大切ですね。  
今回の事例はあまり一般的な事例ではないかもしれませんが、同じような現象で困っている誰かの助けに慣れれば幸いです。

明日は[@t-itou](https://qiita.com/t-itou)さんです。よろしくお願いします。


## 最後に
ウェブクルーでは一緒に働いていただける方を随時募集しております。
お気軽にエントリーくださいませ。

[開発エンジニアの募集](https://hrmos.co/pages/1004681658307198976/jobs/0000005)
[フロントエンドエンジニアの募集](http://www.webcrew.co.jp/recruit/creative.html)
[データベースエンジニアの募集](https://hrmos.co/pages/1004681658307198976/jobs/0000023)