PHPUnitのバージョン上げようとして嵌った

環境

  • Laravel 5.3.x / Laravel 5.5.x の2つのアプリケーションが存在
  • PHP 7.2.x

やりたいこと

どちらも最新バージョンのPHPUnit(8.x)が使いたい

事象と原因

Laravel 5.3.xのアプリケーション

PHP Fatal error:  Class 'PHPUnit_Framework_TestCase' not found in application/path/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php on line 11

このエラーが発生

Laravel5.4からPHPUnitのクラス名の名前空間化?に対応したらしく、 以下の記述をするLaravel5.3でエラーが発生

use PHPUnit_Framework_TestCase;

abstract class TestCase extends PHPUnit_Framework_TestCase

Laravel5.4以降

use PHPUnit\Framework\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase

対応策

PHPUnitのバージョンを上げない

細かく言うと

  • vendor配下のモジュールのためオーバーライドする必要がある(と思う)
  • バージョンを上げることはwantであり、mustではない

Laravel 5.5.xのアプリケーション

PHP Fatal error:  Declaration of Illuminate\Foundation\Testing\TestCase::setUp() must be compatible with PHPUnit\Framework\TestCase::setUp(): void in application/path/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php on line 12

ググってもよく分からなくて、後輩に聞いたら教えてくれた。

phpunit.de

Return Type of Template Methods The methods listed below now have a void return type declaration:

PHPUnit\Framework\TestCase::setUpBeforeClass() PHPUnit\Framework\TestCase::setUp() PHPUnit\Framework\TestCase::assertPreConditions() PHPUnit\Framework\TestCase::assertPostConditions() PHPUnit\Framework\TestCase::tearDown() PHPUnit\Framework\TestCase::tearDownAfterClass() PHPUnit\Framework\TestCase::onNotSuccessfulTest() Your implementations of the methods listed above now must be declared void, too, otherwise you will get a compiler error.

この一文にびっくり「otherwise you will get a compiler error.」

ということで、上記に当てはまるメソッドに対して、

: void を記述したらエラーが解消された。

/**
 * Setup the test environment.
 *
 * @return void
 */
protected function setUp(): void
{

対応策

PHPUnitのバージョンを上げない

細かく言うと

  • Laravel5.3のときと同様に、vendor配下のモジュールのためオーバーライドする必要がある(と思う)
  • 既存のテストコードに対しても修正が必要で、意外と工数が掛かることが判明

既存のテストコードでのエラー

/**
 * XXXXXTest constructor.
 *
 * @param string|null $name
 * @param array       $data
 * @param string      $dataName
 */
public function __construct(string $name = null, array $data = [], string $dataName = '')
{

__constructをこう実装していたのだが、

PHP Fatal error:  Uncaught TypeError: Argument 3 passed to Tests\Feature\XXXXXTest::__construct() must be of the type string, integer given

エラーが発生してしまった。

/**
 * GetUserTest constructor.
 *
 * @param string|null $name
 * @param array       $data
 * @param             $dataName
 */
public function __construct(string $name = null, array $data = [], $dataName = '')
{

こう直したら動いたのだが、Warningが発生しててあまり綺麗とは言えなかった。

PHPUnit 8.0.4 by Sebastian Bergmann and contributors.

  Warning - The configuration file did not pass validation!
  The following problems have been detected:

  Line 26:
  - Element 'log', attribute 'logIncompleteSkipped': The attribute 'logIncompleteSkipped' is not allowed.

  Test results may not be as expected.


.........                                                           9 / 9 (100%)

Time: 3.07 seconds, Memory: 24.00 MB

補足

戻り値の型問題は、Laravel5.8で修正されているので、

Laravel5.7 以下ではPHPUnit8.xは使わない方がよさそう。という見解を得られた。

github.com

Laravelのセッションが消えて困った

概要

画面間で遷移させているときに、一部のセッションキーが消えてしまったときの話 (Laravelのバージョンは5.3)

ざっくりと

(先に断っておくが、変数やメソッド名は仮)

少し雑だが、こんなformからPOSTで画面Aに遷移しようとする際に

<form action="https://abc.com/" method="post"  name="">
    <input type="input" name="client_id" value="hoge"><br>
    <input type="input" name="redirect_uri" value="https://yyy.com"><br>
    <input type="submit" value='BUTTON'>
</form>

こんな形でセッションに突っ込んでたら、

/**
 * /に対応するControllerのAction
 */
public function index(Request $request)
{
    session()->put('client_id', $request->input('client_id'));
    session()->put('redirect_uri', $request->input('redirect_uri'));

    return view('index');
}

以下のようにsessionからgetができなくて困った

/**
 * indexのviewからPOST送信先のControllerのAction
 */
public function add(Request $request)
{
    session()->get('client_id');  // ←取得できずnullになる
    session()->get('redirect_uri'); // ←取得できずnullになる

調査内容

このように、view遷移前、POST送信直後のそれぞれに dd(session()->all()); を入れてみて、

セッションの構造がどうなっているかを調べた

    dd(session()->all()); // 追加
    return view('index');
}

public function add(Request $request)
{
    dd(session()->all()); // 追加

結果

return view直前での詳細

array:11 [▼
  "_previous" => array:1 [▼
    "url" => "http://******"
  ]
  "_flash" => array:2 [▼
    "old" => [
        "client_id" => "hoge",
        "redirect_uri" => "https://yyy.com",
    ]
    "new" => []
  ]
  "_token" => "**************************"
  "client_id" => "hoge",
  "redirect_uri" => "https://yyy.com",
  "hoge" => "hoge",
  "fuga" => "fuga",
  "id" => 111111111,
]

function addでの詳細

array:11 [▼
  "_previous" => array:1 [▼
    "url" => "http://******"
  ]
  "_flash" => array:2 [▼
    "old" => []
    "new" => []
  ]
  "_token" => "**************************"
  "hoge" => 'hoge'
  "fuga" => "fuga"
  "id" => 111111111
]

という感じだった

考察

現在のところは原因が分かってないが、

_flashold に入ってると、処理終了時(response返却後?)にセッションからそのキーを抹消するのでは?と思っている

Illuminate\Session\Store.php を読んだら、結果が分かりそう)

補足

たしかに以下のように reflash() を追加したらセッションは維持された

/**
 * /に対応するControllerのAction
 */
public function index(Request $request)
{
    session()->put('client_id', $request->input('client_id'));
    session()->put('redirect_uri', $request->input('redirect_uri'));
    $request->session()->reflash();

    return view('index');
}

追記

LaravelのSessionはここ

github.com

この terminate つまり、処理終了後にSessionが削除されていた。

/**
 * Perform any final actions for the request lifecycle.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Symfony\Component\HttpFoundation\Response  $response
 * @return void
 */
public function terminate($request, $response)
{
    if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions()) {
        $this->manager->driver()->save();
    }
}

で、実処理はこれ

github.com

考察は間違っていなかったようだった。

Laravelの「integer」ルールのバリデーション

概要

LaravelのValidationルールで「integer」があるが、これは型までチェックしているのか?と思ったのが調べるきっかけ。

どういうことかというと、

'id' => 'required|integer',

と書いていたバリデーションルールに対して、string型での数値が通っていた。

LaravelにおけるValidationの流れ

そもそもの話

ざっくり書くとControllerでこのようにValidationを実行しているが、

use ValidatesRequests;

$this->validate($request, $this->validator->getRules(), $this->validator->getMessage(), $this->validator->getAttribute());

このときの処理の流れは、

vendor\laravel\framework\src\Illuminate\Foundation\Validation\ValidatesRequests.php: validate()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: validate()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: fails()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: passes()

vendor\laravel\framework\src\Illuminate\Validation\Validator.php: validateAttribute()

Validationの実体

validateAttributeの中身がこんな感じ

/**
 * Validate a given attribute against a rule.
 *
 * @param  string  $attribute
 * @param  string  $rule
 * @return void
 */
protected function validateAttribute($attribute, $rule)
{
    $this->currentRule = $rule;

    list($rule, $parameters) = ValidationRuleParser::parse($rule);

    if ($rule == '') {
        return;
    }

    // First we will get the correct keys for the given attribute in case the field is nested in
    // an array. Then we determine if the given rule accepts other field names as parameters.
    // If so, we will replace any asterisks found in the parameters with the correct keys.
    if (($keys = $this->getExplicitKeys($attribute)) &&
        $this->dependsOnOtherFields($rule)) {
        $parameters = $this->replaceAsterisksInParameters($parameters, $keys);
    }

    $value = $this->getValue($attribute);

    // If the attribute is a file, we will verify that the file upload was actually successful
    // and if it wasn't we will add a failure for the attribute. Files may not successfully
    // upload if they are too large based on PHP's settings so we will bail in this case.
    if ($value instanceof UploadedFile && ! $value->isValid() &&
        $this->hasRule($attribute, array_merge($this->fileRules, $this->implicitRules))
    ) {
        return $this->addFailure($attribute, 'uploaded', []);
    }

    // If we have made it this far we will make sure the attribute is validatable and if it is
    // we will call the validation method with the attribute. If a method returns false the
    // attribute is invalid and we will add a failure message for this failing attribute.
    $validatable = $this->isValidatable($rule, $attribute, $value);

    if ($rule instanceof RuleContract) {
        return $validatable
                ? $this->validateUsingCustomRule($attribute, $value, $rule)
                : null;
    }

    $method = "validate{$rule}";

    if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
        $this->addFailure($attribute, $rule, $parameters);
    }
}

これを見ると、integerの場合、validateInteger でvalidationが実行されそう。

なので追ってみた。

$method = "validate{$rule}";

if ($validatable && ! $this->$method($attribute, $value, $parameters, $this)) {
    $this->addFailure($attribute, $rule, $parameters);
}
/**
 * Validate that an attribute is an integer.
 *
 * @param  string  $attribute
 * @param  mixed   $value
 * @return bool
 */
public function validateInteger($attribute, $value)
{
    return filter_var($value, FILTER_VALIDATE_INT) !== false;
}

ということで、結局は filter_var($value, FILTER_VALIDATE_INT)

FILTER_VALIDATE_INTを調べた

とりあえず読んでみた

php.net

It's good to remember that using filter_var is primarily for filtering input values when doing boolean logic comparisons. Take the following:

$value = "12";
if(filter_var($value, FILTER_VALIDATE_INT))
{
    // validated as an int
}

これを読むと Stringっぽくクォートで囲った値を送っても、intとして処理が通りそう。

結論

型というより、整数形式の表現だったら、何でも通るのではないかと思った。

補足

1ヶ月くらい前に下書きで書いてて、公開するの忘れてたやつ。

LaravelのPHPUnitで「PDOException: SQLSTATE[HY000] [1040] Too many connections」が起きた

概要

Laravelでテスト実行中に以下のエラーが出るようになり、少し悩んだ

※バージョンは「Laravel 5.5.44」

PDOException: SQLSTATE[HY000] [1040] Too many connections
  • エラーの発生箇所はPHPUnitで流しているケースの後半
  • エラーが起きたテストクラスを単独で実行するとエラーは発生しない

という状況のため、単純にテストケースごとにConnectionを切る方向で考えた。

参考

とりあえず他に悩んでる人がいないかググった。

qiita.com

github.com

対応

上記のQiitaの方は PDO::ATTR_PERSISTENT で対応したみたいだったが、

本番稼働中のサービスもあり、迂闊にConfigを変えるのは良くない気もしたので、

当初の想定通りに、テストケースごとにConnectionを切ることにした。

/*
 * @return void
 */
public function tearDown()
{
    \DB::connection()->disconnect(); // 追加
    parent::tearDown();
}

終わりに

RefreshDatabaseTrait をいろいろカスタマイズしており、$this->beginDatabaseTransaction(); が実行されていないことが原因だと思う

PHP7.2からのcount()の挙動に悩んだ

概要

PHPのバージョンを7.0(7.0.15)から7.2(latest)に上げたときに起きた問題

エラーの内容

php7.2 count でググればたくさん出てくるので、細かいことは省略するが、 count()の仕様変更により、配列などCountable なものではないとエラーを返すようになった。

PHP Warning:  count(): Parameter must be an array or an object that implements Countable

PHP7.0での挙動

いくつか試してみた。思いつく限り。

var_dump(count(''));
// →int(1)
var_dump(count('hoge'));
// →int(1)
var_dump(count('0'));
// →int(1)
var_dump(count('1'));
// →int(1)
var_dump(count('2'));
// →int(1)
var_dump(count(0));
// →int(1)
var_dump(count(1));
// →int(1)
var_dump(count(2));
// →int(1)
var_dump(count([]));
// →int(0)
var_dump(count(['']));
// →int(1)
var_dump(count(['','']));
// →int(2)
var_dump(count(['1','']));
// →int(2)
var_dump(count(null));
// →int(0)
var_dump(count(true));
// →int(1)
var_dump(count(false));
// →int(1)

やりたかったこと

誰かが作った既存のメソッドがあって、

public function getHoge($fuga)
{
    return count($fuga->getPiyo());
}

これのI/Fを担保したかった。影響範囲がよくわからないから。

どうしたのか

上記の挙動を見る限り、

  • 配列かどうか
  • NULLかどうか

の判定で済みそうだと思ったので、いったんは以下にしてみる。 本当はもっと厳密にあらゆることを想定する必要があるはず。

public function getHoge($fuga)
{
    if (is_array($fuga->getPiyo())) {
        return count($fuga->getPiyo());
    }

   return is_null($fuga->getPiyo()) ? 0 : 1;
}

まとめ

そもそもなぜこのエラーに出くわしたかというと、新規で開発をしてたときに、過去のテストコードが通らなくなったから。

要はテストコードって大事だよね、という話なのかもしれない。

リトライ処理のTraitを作ってみた

ずいぶん前に個人的に作ってたものを備忘録で記載。

Exponential Backoff and Jitterで。 TODOで残してるとこがダサいけど、ベスプラがよくわからず。

こういうところを極めるなら、まずは数学をおさらいしなければかなと思う。

trait RetryTrait
{
    /**
     * リトライ処理回数内部カウント用
     * @var int
     */
    private $retryCount = 0;
 
    /**
     * @var bool
     */
    private $jitterEnabled = true;
 
    /**
     * @param string $function
     * @param array  $options
     * @param int    $maxAttempts
     * @param int    $interval micro_sec
     * @return mixed
     * @throws \Exception
     */
    public function retry(string $function, array $options = [], int $maxAttempts = 5, int $interval = 1000000)
    {
        $result = false;
 
        for ($i = 0; $i < $maxAttempts + 1; $i++) {
            try {
                // 成功時にはそのまま処理終了
                $result = $this->$function($options);
                break;
            } catch (\Exception $e) {
                // 失敗時にはExceptionを返却
                $result = $e;
            }
 
            // リクエスト上限到達でリトライ中止
            if ($this->retryCount == $maxAttempts) {
                throw $result;
            }
            $this->retryCount++;
 
            // インターバルをおいて、次回処理へ
            $this->interval($interval);
        }
 
        return $result;
    }
 
    /**
     * リトライ回数から遅延秒数を決定し、処理を止める(sleep)
     *
     * @param int $maxAttempts
     * @param int $interval
     */
    public function interval(int $interval)
    {
        /**
         * TODO 根拠のない数式のため、ベスプラがあればそちらに差し替える
         */
        $waitTime = pow(2, $this->retryCount) / ($this->retryCount + 1) * $interval;
        usleep($this->jitter($waitTime));
    }
 
    /**
     * ±10%のばらつきを与える
     * Jitterが不要な場合はそのまま返却
     *
     * @param int $waitTime
     * @return int
     */
    public function jitter(int $waitTime): int
    {
        return $this->jitterEnabled
            ? mt_rand($waitTime * 0.9, $waitTime * 1.1)
            : $waitTime;
    }
}

実際に使うときはこんな感じ

use RetryTrait;

const MAX_ATTEMPTS = 5;
 
/**
 * リトライ時のインターバル(初期秒数:micro_sec)
 */
const RETRY_INTERVAL = 1000000;


$this->retry('callback', [$param1, $param2], self::MAX_ATTEMPTS, self::RETRY_INTERVAL);

/**
 * @param array $options
 * @return mixed
 * @throws \Exception
 */
public function callback(array $options)
{
    // 何かしらの処理
}

※動作保証はしてない

ServerlessFrameworkでのdeploy時にエラーが出る

概要

serverless deploy でデプロイした際に、エラーメッセージが出るのだが、

-v-verbose で違いがあった(調べた感じではどっちも同じだと思ってた)

StackTraceを見る感じ、Serverless内でエラーになってるっぽいからバグなのかなぁ。。

環境

  Your Environment Information -----------------------------
     OS:                     linux
     Node Version:           8.12.0
     Serverless Version:     1.32.0

Cannot read property 'replace' of undefined

$ serverless deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
 
  Type Error ---------------------------------------------
 
  Cannot read property 'replace' of undefined
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information -----------------------------
     OS:                     linux
     Node Version:           8.12.0
     Serverless Version:     1.32.0

デバッグをしてみる

$ SLS_DEBUG=* serverless deploy -v
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command create
Serverless: Load command install
Serverless: Load command package
Serverless: Load command deploy
Serverless: Load command deploy:function
Serverless: Load command deploy:list
Serverless: Load command deploy:list:functions
Serverless: Load command invoke
Serverless: Load command invoke:local
Serverless: Load command info
Serverless: Load command logs
Serverless: Load command login
Serverless: Load command logout
Serverless: Load command metrics
Serverless: Load command print
Serverless: Load command remove
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command slstats
Serverless: Load command plugin
Serverless: Load command plugin
Serverless: Load command plugin:install
Serverless: Load command plugin
Serverless: Load command plugin:uninstall
Serverless: Load command plugin
Serverless: Load command plugin:list
Serverless: Load command plugin
Serverless: Load command plugin:search
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Invoke deploy
Serverless: Invoke package
Serverless: Invoke aws:common:validate
Serverless: Invoke aws:common:cleanupTempDir
Serverless: Packaging service...
Serverless: Excluding development dependencies...
 
  Type Error ---------------------------------------------
 
  Cannot read property 'replace' of undefined
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Stack Trace --------------------------------------------
 
TypeError: Cannot read property 'replace' of undefined
    at Object.normalizeNameToAlphaNumericOnly (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/lib/naming.js:32:36)
    at Object.getStreamLogicalId (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/lib/naming.js:236:13)
    at functionObj.events.forEach.event (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/stream/index.js:119:16)
    at Array.forEach (<anonymous>)
    at serverless.service.getAllFunctions.forEach (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/stream/index.js:41:28)
    at Array.forEach (<anonymous>)
    at AwsCompileStreamEvents.compileStreamEvents (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/compile/events/stream/index.js:16:47)
    at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55)
From previous event:
    at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22)
    at PluginManager.spawn (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:408:17)
    at Deploy.BbPromise.bind.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:123:50)
From previous event:
    at Object.before:deploy:deploy [as hook] (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:113:10)
    at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55)
From previous event:
    at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22)
    at PluginManager.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:421:17)
    at variables.populateService.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:157:33)
    at runCallback (timers.js:810:20)
    at tryOnImmediate (timers.js:768:5)
    at processImmediate [as _immediateCallback] (timers.js:745:5)
From previous event:
    at Serverless.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:144:8)
    at serverless.init.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/bin/serverless:43:50)
    at <anonymous>
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information -----------------------------
     OS:                     linux
     Node Version:           8.12.0
     Serverless Version:     1.32.0

region.toLowerCase is not a function

$ serverless deploy -verbose
 
  Type Error ---------------------------------------------
 
  region.toLowerCase is not a function
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information -----------------------------
     OS:                     linux
     Node Version:           8.12.0
     Serverless Version:     1.32.0

デバッグをしてみる

$ SLS_DEBUG=* serverless deploy -verbose
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command create
Serverless: Load command install
Serverless: Load command package
Serverless: Load command deploy
Serverless: Load command deploy:function
Serverless: Load command deploy:list
Serverless: Load command deploy:list:functions
Serverless: Load command invoke
Serverless: Load command invoke:local
Serverless: Load command info
Serverless: Load command logs
Serverless: Load command login
Serverless: Load command logout
Serverless: Load command metrics
Serverless: Load command print
Serverless: Load command remove
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Load command slstats
Serverless: Load command plugin
Serverless: Load command plugin
Serverless: Load command plugin:install
Serverless: Load command plugin
Serverless: Load command plugin:uninstall
Serverless: Load command plugin
Serverless: Load command plugin:list
Serverless: Load command plugin
Serverless: Load command plugin:search
Serverless: Load command config
Serverless: Load command config:credentials
Serverless: Load command rollback
Serverless: Load command rollback:function
Serverless: Invoke deploy
Serverless: Invoke package
Serverless: Invoke aws:common:validate
Serverless: Invoke aws:common:cleanupTempDir
 
  Type Error ---------------------------------------------
 
  region.toLowerCase is not a function
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Stack Trace --------------------------------------------
 
TypeError: region.toLowerCase is not a function
    at getS3EndpointForRegion (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/utils/getS3EndpointForRegion.js:4:28)
    at AwsProvider.isS3TransferAccelerationSupported (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/provider/awsProvider.js:335:22)
    at AwsPackage.generateCoreTemplate (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/lib/generateCoreTemplate.js:27:61)
From previous event:
    at Object.package:initialize [as hook] (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/aws/package/index.js:60:10)
    at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55)
From previous event:
    at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22)
    at PluginManager.spawn (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:408:17)
    at Deploy.BbPromise.bind.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:123:50)
From previous event:
    at Object.before:deploy:deploy [as hook] (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/plugins/deploy/deploy.js:113:10)
    at BbPromise.reduce (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:55)
From previous event:
    at PluginManager.invoke (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:390:22)
    at PluginManager.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/classes/PluginManager.js:421:17)
    at variables.populateService.then.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:157:33)
    at runCallback (timers.js:810:20)
    at tryOnImmediate (timers.js:768:5)
    at processImmediate [as _immediateCallback] (timers.js:745:5)
From previous event:
    at Serverless.run (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/lib/Serverless.js:144:8)
    at serverless.init.then (/usr/local/nvm/versions/node/v8.12.0/lib/node_modules/serverless/bin/serverless:43:50)
    at <anonymous>
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information -----------------------------
     OS:                     linux
     Node Version:           8.12.0
     Serverless Version:     1.32.0