AWS SDK for PHPのVersion 3に更新して、EC2自動起動処理を書き換えてみた

[EC2インスタンスを業務時間だけ自動起動する処理をAWS SDK for PHP 2で作成する](http://qiita.com/shojimotio/items/0fe9e81da40524ffafc0)を使っているので、これを早速 AWS SDK for PHPのVersion 3で動かした時に、ハマった所を紹介したいと思います。

# 感想

* 単純にSDKをVersion3に変更しただけではエラー吐いて動かない。後方互換はほぼ無し。
* クライアント生成時に引数 'Version' の指定が必須になったのと、factoryじゃなくnewで生成するように変更されたので、変更コストがでかい。
* API実行後の戻り値のデータ取得方法も変更されたので、そのままだとエラー吐くよ。getPathがsearchになって、渡す引数も変更された。
* RDSとかの戻り値が違うらしいので、戻り値確認しての作り直しが大変そう。
* SDK自体の更新はcomposer.jsonを書き換えてupdateするだけなので簡単。

# SDKをVersion 2からVersion 3に更新

* composer.jsonを書き換える

```file:composer.json
{
    "require": {
        "aws/aws-sdk-php": "3.*"
    }
}
```

* composer updateすると依存関係とAWS SDK for PHP Version 3がインストールされる

```
$ php composer.phar update

Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Removing guzzle/guzzle (v3.9.2)
  - Removing symfony/event-dispatcher (v2.6.3)
  - Installing mtdowling/jmespath.php (2.2.0)
    Downloading: 100%

  - Installing guzzlehttp/promises (1.0.0)
    Downloading: 100%

  - Installing psr/http-message (1.0)
    Downloading: 100%

  - Installing guzzlehttp/psr7 (1.0.0)
    Downloading: 100%

  - Installing guzzlehttp/guzzle (6.0.1)
    Downloading: 100%

  - Removing aws/aws-sdk-php (2.6.16)
  - Installing aws/aws-sdk-php (3.0.1)
    Downloading: 100%

Writing lock file
Generating autoload files

```

# Version 2の記述スタイルのまま、EC2自動起動処理のphpを実行してみる（エラー出る）

* Ec2Clientを生成する時に必須の引数 'Version' に'2015-04-15'(日付スタイル)を指定しろとエラー。
* Versionはどこに書いてあるの？→ここhttp://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html
* 各サービスのクライアントでそれぞれ日付がちがう！マジか！

各サービスのAPIバージョンの一部
Amazon Elastic Compute Cloud 2015-04-15
Amazon Simple Storage Service 2006-03-01
Amazon DynamoDB 2012-08-10
Amazon Glacier 2012-06-01


```
$ php ec2_start.php
...省略...
PHP Fatal error:  Uncaught exception 'InvalidArgumentException' with message 'Missing required client configuration options:

version: (string)

  A "version" configuration value is required. Specifying a version constraint
  ensures that your code will not be affected by a breaking change made to the
  service. For example, when using Amazon S3, you can lock your API version to
  "2006-03-01".

  Your build of the SDK has the following version(s) of "ec2": * "2015-04-15"

  You may provide "latest" to the "version" configuration value to utilize the
  most recent available API version that your client's API provider can find.
  Note: Using 'latest' in a production application is not recommended.

  A list of available API versions can be found on each client's API documentation
  page: http://docs.aws.amazon.com/aws-sdk-php/v3/api/index.html. If you are
  unable to load a specific API version, then you may need to update your copy of
  the SDK.'...省略
```

# Ec2Clientの生成のスタイル比較

* Version 3ではfactoryは非推奨 → newを使おう。
* 必須の引数 'version' を指定する。

```php:
// Version 2
$ec2client = Ec2Client::factory([
    'region'  => 'us-east-2'
 ]);

// Version 3
$ec2client = new Ec2Client([
    'region'  => 'us-east-2',
    'version' => '2015-04-15'
]);

```

# 処理実行後の戻り値の処理方法の比較

* まず戻り値の$instancesには大量の他のデータやら何やらが入れ子の配列で格納されている。
* この中からインスタンスIDを取得したい場合便利なデータ取得関数(getPathとかsearch)を利用する。
* Version 3 では戻り値getPathじゃなくて、searchで取得する。
* getPathをそのまま使うとエラーを吐いたよ。

```
PHP Fatal error:  Uncaught exception 'JmesPath\SyntaxErrorException' with message 'Syntax error at character 25
Reservations.*.Instances.0.InstanceId
                         ^
```

## 記述スタイル比較

```php
// インスタンスの一覧を取得
$instances = $ec2client->describeInstances();

// version 2 このまま実行するとVersion 3ではエラー
$ids_v2 = $instances->getPath('Reservations/*/Instances/0/InstanceId');

// version 3
$ids_v3 = $instances->search('Reservations[].Instances[].InstanceId');

```

## searchの使い方

* 取得方法の例とサンプル
http://jmespath.org/tutorial.html

# まとめ

* SDKはcomposerで簡単にVersion 3 に更新できる。
* 変更すべき箇所はクライアント生成処理と戻り値のデータから目的のIDを取得する箇所など。
* APIの呼び出し方法は変更無いのでそのまま使えた。

自分の[技術ブログ](https://blog-c.cloudlance-motio.work/)ではフリーランス界隈の情報や最新のIT情報の発信していますので、よろしくお願いします。