Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go Applicationでの設定情報の扱い方

Go Applicationでの設定情報の扱い方

エムスリー株式会社のTech Talkにて発表した内容です。
https://corporate.m3.com/

https://qiita.com/Khigashiguchi/items/525a5920b3953bfbf5fa

Kazuki Higashiguchi

August 22, 2018
Tweet

More Decks by Kazuki Higashiguchi

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • ౦ޱ ࿨ᏻ @Khigashiguchi • BASE, Inc / BASE

    Product Division • Server Side EngineerʢPHP / Goʣ • Works • EίϚʔεϓϥοτϑΥʔϜʮBASEʯͷ ܾࡁྖҬ • PHP/CakePHPͷόʔδϣϯΞοϓ • BASE BANKʹͯۚ༥ࣄۀͷ্ཱͪ͛
  2. ઃఆ৘ใ ͱ͸ • σʔλϕʔεͷ઀ଓઌ΍ύεϫʔυͳͲ • 12factor.net ͷఆٛ • σʔλϕʔεɺMemcachedɺଞͷόοΫΤϯυαʔ ϏεͳͲͷϦιʔε΁ͷϋϯυϧ

    • Amazon S3΍TwitterͳͲͷ֎෦αʔϏεͷೝূ৘ใ • σϓϩΠ͞Εͨϗετͷਖ਼نԽ͞Εͨϗετ໊ͳͲɺ σϓϩΠ͝ͱͷ஋ https://12factor.net/ja/config
  3. ίϯςφҎ֎ͷ৔߹ͩͱ • /etc/environmentʹॻ͘ -> ඞཁͳϓ ϩηεҎ֎΋ݟΕΔ • ApacheͷSetEnvઃఆͳͲ -> ϛυϧ

    ΢ΣΞ͝ͱͷઃఆඞཁʹͳΔʢcronʣ • 1ΞϓϦέʔγϣϯɾ1Ϣʔβʔͷલఏ Ͱ͋Ε͹ɺϢʔβʔ୯Ґͷ؀ڥม਺Ͱ΋ ͍͍ʢ.profileʁʣ
  4. ஫ೖ͢Δ؀ڥม਺͸Ͳ͏؅ཧʁ • ✍ΞϓϦέʔγϣϯͳΒdotenvʹॻ͔͘ʁ • ։ൃ؀ڥ͚ͩ࢖͏ʁ • →։ൃ/ຊ൪Ͱ؀ڥม਺ͷѻ͍ํ͕ҧ͏ҧ࿨ײ • ຊ൪؀ڥ΋࢖͏ͳΒdotenvϑΝΠϧΛͲ͏؅ཧ͢Δʁ •

    →.env.production ϑΝΠϧΛgit؅ཧ಺ʹɾɾɾ • ✍ECSͳΒʁ • ௚઀؀ڥม਺Λઃఆ͸ආ͚ͨͦ͏ • KMS & ssm parameter storeͷ૊Έ߹Θͤʁ
  5. TOML [database] user = "sample_user" host = "master_mysql" port =

    3306 name = "sample" databaseͷ઀ଓ৘ใΛఆٛ tomlϑΝΠϧΛ؀ڥ͝ͱʹ༻ҙ localhost.toml
  6. Load Configuration // DBConfig represents database connection configuration information. type

    DBConfig struct { User string `toml:"user"` Password string // tomlϑΝΠϧ͔Β෼཭͢ΔͨΊλάΛ࡟আ Host string `toml:"host"` Port int `toml:"port"` Name string `toml:"name"` } // Config represents application configuration. type Config struct { DB DBConfig `toml:"database"` } ConfigΛߏ଄ମͱͯ͠ఆٛ structλάʹtomlͷfield໊Λࢦఆ config.go
  7. Load Configuration // DBConfig represents database connection configuration information. type

    DBConfig struct { User string `toml:"user"` Password string // tomlϑΝΠϧ͔Β෼཭͢ΔͨΊλάΛ࡟আ Host string `toml:"host"` Port int `toml:"port"` Name string `toml:"name"` } // Config represents application configuration. type Config struct { DB DBConfig `toml:"database"` } ύεϫʔυͷΈ؀ڥม਺͔Βऔಘ config.go
  8. Load Configuration // NewConfig return configuration struct. func NewConfig(path string,

    appMode string) (Config, error) { var conf Config confPath := path + appMode + ".toml" if _, err := toml.DecodeFile(confPath, &conf); err != nil { return conf, err } conf.DB.Password = os.Getenv("DB_PASSWORD") // ؀ڥม਺͔ΒಡΈࠐΉ return conf, nil } ࢖༻͢ΔtomlϑΝΠϧͷࢦఆ localhost -> localhost.toml production -> production.toml config.go
  9. Load Configuration // NewConfig return configuration struct. func NewConfig(path string,

    appMode string) (Config, error) { var conf Config confPath := path + appMode + ".toml" if _, err := toml.DecodeFile(confPath, &conf); err != nil { return conf, err } conf.DB.Password = os.Getenv("DB_PASSWORD") // ؀ڥม਺͔ΒಡΈࠐΉ return conf, nil } tomlϑΝΠϧͷσίʔυ config.go
  10. Load Configuration // NewConfig return configuration struct. func NewConfig(path string,

    appMode string) (Config, error) { var conf Config confPath := path + appMode + ".toml" if _, err := toml.DecodeFile(confPath, &conf); err != nil { return conf, err } conf.DB.Password = os.Getenv("DB_PASSWORD") // ؀ڥม਺͔ΒಡΈࠐΉ return conf, nil } ύεϫʔυΛ؀ڥม਺͔Βऔಘ config.go
  11. Use Configuration const confDir = "./config/env/" //ɹઃఆϑΝΠϧ΁ͷ࣮ߦϑΝΠϧ͔Βͷ૬ରύεΛࢦఆ func main() {

    var err error appMode := os.Getenv("APP_MODE") // ಈ࡞؀ڥΛAPP_MODEͱ͍͏ܗͰ؀ڥม਺ʹ֨ೲ͢Δ if appMode == "" { panic("failed to get application mode, check whether APP_MODE is set.") } // Get configuration conf, err := config.NewConfig(confDir, appMode) // Ҿ਺ʹ౉͢ if err != nil { panic(err.Error()) } // Ҏ߱ଓ͘... } ઃఆ৘ใͷऔಘ main.go
  12. Test Loading Configuration func TestNewConfig(t *testing.T) { cases := []struct

    { name string appMode string expected config.Config }{ { name: "localhost", appMode: "localhost", expected: config.Config{ DB: config.DBConfig{ User: "sample_user", Password: "sample_password", Host: "master_mysql", Port: 3306, Name: "sample", }, }, }, } //ଓ͘ } ؀ڥ͝ͱͷࠩҟɾաෆ଍ɾߟྀෆ ଍ʹ͍ͭͯͷϦεΫܰݮͷͨΊɺ ରԠ͢Δ؀ڥ͝ͱʹςετ config_test.go
  13. Test Loading Configuration ɹɹ // લճͷଓ͖ for _, c :=

    range cases { t.Run(c.name, func(t *testing.T) { confDir := "./env/" os.Setenv("DB_PASSWORD", c.expected.DB.Password) // ؀ڥม਺ʹظ଴͢ΔύεϫʔυΛηοτ ͢Δ res, err := config.NewConfig(confDir, c.appMode) assert.Equal(t, nil, err) assert.Equal(t, c.expected.DB.User, res.DB.User) assert.Equal(t, c.expected.DB.Password, res.DB.Password) assert.Equal(t, c.expected.DB.Host, res.DB.Host) assert.Equal(t, c.expected.DB.Port, res.DB.Port) assert.Equal(t, c.expected.DB.Name, res.DB.Name) }) } } config_test.go