LoginSignup
3
2

More than 5 years have passed since last update.

gopher-lua でサーバーの設定を動的に変更する

Last updated at Posted at 2017-05-01

gopher-lua は Go で書かれた Lua 処理系です。
net/http で書かれたサーバーの設定を Lua で記述し、それを動的に変更してみます。

基本的な使い方

lua で設定ファイルを記述する場合は gopher-lua の作者が作成した gluamapperを使用すると簡単にできます。

package main

import (
    "fmt"

    "github.com/yuin/gluamapper"
    "github.com/yuin/gopher-lua"
)

type dbConfig struct {
    URL  string
    Port int
}

type Config struct {
    Name string
    Age  int
    DB   dbConfig
}

var configLua = `
config = {
  name = "hoge",
  age  = "31",
  db = {
    url = "localhost",
    port = "3306"
  }
}
`

func main() {
    L := lua.NewState()
    if err := L.DoString(configLua); err != nil {
        panic(err)
    }

    var config Config
    if err := gluamapper.Map(L.GetGlobal("config").(*lua.LTable), &config); err != nil {
        panic(err)
    }

    fmt.Printf("%s\n%d\n%#v", config.Name, config.Age, config.DB)
}

実行結果

$ go run example.go 
hello
hoge
31
main.dbConfig{URL:"localhost", Port:3306}%    

設定を動的に変更する

サーバーに設定ファイルを受け取るURLを作成して、設定ファイルの内容を変えてみます。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"

    "github.com/yuin/gopher-lua"
    "github.com/yuin/gluamapper"
)

type dbConfig struct {
    URL  string
    Port int
}

type Config struct {
    Name string
    Age  int
    DB   dbConfig
}

var initialConfig = `
config = {
  name = "hoge",
  age  = "31",
  db = {
    url = "localhost",
    port = "3306"
  }
}
`

var (
    L = lua.NewState()
    config = Config{}
)

func DumpLuaConfig(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Name=%s\nAge=%d\nDB=%#v\n", config.Name, config.Age, config.DB)
}

func UpdateLuaConfig(w http.ResponseWriter, r *http.Request) {
    luaScript, err := ioutil.ReadAll(r.Body)
    defer r.Body.Close()
    if err != nil {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "%v", err)
        return
    }

    if err := L.DoString(string(luaScript)); err != nil {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "%v", err)
        return
    }

    if err := gluamapper.Map(L.GetGlobal("config").(*lua.LTable), &config); err != nil {
        w.WriteHeader(http.StatusBadRequest)
        fmt.Fprintf(w, "%v", err)
        return
    }
    fmt.Fprint(w, "ok")
}

func main() {
    if err := L.DoString(initialConfig); err != nil {
        panic(err)
    }

    if err := gluamapper.Map(L.GetGlobal("config").(*lua.LTable), &config); err != nil {
        panic(err)
    }

    http.HandleFunc("/config/dump", DumpLuaConfig)
    http.HandleFunc("/config/update", UpdateLuaConfig)

    http.ListenAndServe(":8080", nil)
}

実行結果

  • 初期設定
$ curl localhost:8080/config/dump
Name=hoge
Age=31
DB=main.dbConfig{URL:"localhost", Port:3306}
  • 設定を変更する
$ curl -X POST 'localhost:8080/config/update' -d 'config =
{
  name = "test",
  age = "123123",
    db = {
      url = "localhoooooost",
      port  = "12345"
    }
}'
ok
  • 設定を確認する
$ curl localhost:8080/config/dump                
Name=test
Age=123123
DB=main.dbConfig{URL:"localhoooooost", Port:12345}

サーバーを再起動せず設定ファイルを変更できました。

その他

同様の手法を使えば、恐らく hcl や toml でも可能だと思います。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2