HackToTech

Hack To Technology

Terraform detected the following changes made outside of Terraformを無視することにした

実質メモ書き
尚、未だに公式的に回避する手立てがあるわけではないので、そこは実装されるのを待つしかない。

Terraform0.15.4 以降、これが出てくるようになった。
現状 ignore_changes するぐらいしかろくな回避手段がないが、ignore_changes は別にその為に使うもんでもないので悩んでいた。
(IAMとかのPolicyの変更ノイズが個人的にとてもつらいし、長いログが出力されてしまうのがきつい)
それでまあ Issue を眺めてたら言及されている Issue を見つけた。

github.com

荒れに荒れて10月にはIssue自体がロックされてしまったらしい。
(追記) 1.2でなんか対応入ったっぽい

個人的にはリフレッシュに対する差分が長すぎて、
変更差分を見落とすほうがつらいのでIssueのコメントにかかれているように、sed で無視することにした。
lockされているとコメントにスタンプ押せないのでこの場で感謝。
早くリソースの Attribute レベルで更新差分を無視することが出来るようになってほしい。

terraform plan | grep -v "Refreshing state..." | sed '/Objects have changed outside of Terraform/,/────────────/d'

auroraでフェイルオーバーした際にコネクションの接続がぜんぜん切り替わらなくて色々見てたのでメモ

環境

  • Aurora postgresql
  • Spring Boot
    • driver は org.postgresql.driver
  • Doma

メモ

AWSのベストプラクティスにも書かれているやつで、targetServerTypeprimary に指定しておけばFOした際に自動的にコネクションが再接続される

jdbc:postgresql://myauroracluster.cluster-c9bfei4hjlrd.us-east-1-beta.rds.amazonaws.com:5432,myauroracluster.cluster-ro-c9bfei4hjlrd.us-east-1-beta.rds.amazonaws.com:5432/postgres?user=<primaryuser>&password=<primarypw>&loginTimeout=2&connectTimeout=2&cancelSignalTimeout=2&socketTimeout=60&tcpKeepAlive=true&targetServerType=primary

docs.aws.amazon.com

targetServerType = String

Allows opening connections to only servers with required state, the allowed values are any, primary, master, slave, secondary, preferSlave and preferSecondary. The primary/secondary distinction is currently done by observing if the server allows writes. The value preferSecondary tries to connect to secondary if any are available, otherwise allows falls back to connecting also to primary. jdbc.postgresql.org

ただAWS公式だと参照系クエリをreplicaに逃がす部分の話はなかったので、一応pgjdbcの実装を確認した github.com

HostStatus hostStatus = HostStatus.ConnectOK;
if (candidateHost.targetServerType != HostRequirement.any) {
  hostStatus = isPrimary(queryExecutor) ? HostStatus.Primary : HostStatus.Secondary;
}
GlobalHostStatusTracker.reportHostStatus(hostSpec, hostStatus);
knownStates.put(hostSpec, hostStatus);
if (!candidateHost.targetServerType.allowConnectingTo(hostStatus)) {
  queryExecutor.close();
  continue;
}

pgjdbc/ConnectionFactoryImpl.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub

Tuple results = SetupQueryRunner.run(queryExecutor, "show transaction_read_only", true);

で接続先がreadonlyかどうかチェックしているらしい

pgjdbc/ConnectionFactoryImpl.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub

  primary {
    public boolean allowConnectingTo(@Nullable HostStatus status) {
      return status == HostStatus.Primary || status == HostStatus.ConnectOK;
    }
  },
  secondary {
    public boolean allowConnectingTo(@Nullable HostStatus status) {
      return status == HostStatus.Secondary || status == HostStatus.ConnectOK;
    }
  },

allowConnectingTo でコネクションが接続先の条件(targetServerType で指定した HostStatus )にマッチしているかを確かめて、マッチしていなければクローズするみたいな実装にしているらしい

pgjdbc/HostRequirement.java at a966396c5e2ac3398ba5196d5e9baed705cf593e · pgjdbc/pgjdbc · GitHub

最終的に 書き込み用のコネクションプールの接続をjdbc:postgresql://<cluster_endpoiont>?targetServerType=primary
参照用のコネクションプールの接続をjdbc:postgresql://<cluster_readonly_endpoint>?targetServerType=secondary
にしていい感じになった
他にもベストプラクティスのパラメータ足したり、SpringBoot使ってるのでHikariCP周りの設定した

semverが正しいかを確認する

仕事でタグの棚卸しをしていてこのsemver記法的に正しいんだっけみたいなのぱぱっと見る必要があったので備忘録がてら残しとく

オンラインでぱぱっと見れたらいいんだけど、
なんか探し方が悪かったのかsemverとは何かみたいなサイトばっかりひっかかったので
大人しくnpmのsemverパッケージ使う方が早そうだった
www.npmjs.com
package.jsonとか書いてるならnpm semantic version calculatorとかのほうが良い

# 適当に入れる(node.js入ってる前提)
$ npm install semver
$ node
> const semver = require('semver')
// ただ正しいかどうかならvalidでnullが返ってこなければOK
> semver.valid('1.0.0')
'1.0.0'
> semver.valid('1.2.3.4')
null


// どこがどれだっけ的なのを確認するならparseで見るのが手っ取り早かった
> semver.parse('1.0.0-beta')
SemVer {
  options: {},
  loose: false,
  includePrerelease: false,
  raw: '1.0.0-beta',
  major: 1,
  minor: 0,
  patch: 0,
  prerelease: [ 'beta' ],
  build: [],
  version: '1.0.0-beta'
}

Pythonで辞書の配列から新たに辞書を作成する

pythonのreduceたまにどこにあるかよくわかんなくて迷う

from functools import reduce

ld = [{'Key': 'Key1', 'Value': 'Value1'}, {'Key': 'Key2', 'Value': 'Value2'}, {'Key': 'Key3', 'Value': 'Value3'}]
reduce(lambda acc, x: dict(acc, **{x['Key']: x['Value']}) , ld, {})
# {'Key1': 'Value1', 'Key2': 'Value2', 'Key3': 'Value3'}

ld2 = [{'Key1': 'Value1'}, {'Key2': 'Value2'}, {'Key3': 'Value3'}]
reduce(lambda acc, x: dict(acc, **x), ld2, {})
# {'Key1': 'Value1', 'Key2': 'Value2', 'Key3': 'Value3'}