Golang StatikでViperのConfigファイルとかFirebaseのCredentialとかをまとめてビルド


Viper

GoのConfig用ライブラリ。プロジェクトの外に置いて監視するつくりっぽいが、バイナリに含めたかったため調べて実装した。
Firebaseの方はセキュリティ的にどうなんだろうか・・・
https://github.com/spf13/viper

全体構成

プロジェクトルート/
 ├ asset/
 │  ├ environment/環境名.yaml
 │  └ firebase/クレデンシャル.json
 │
 ├ statik/statik.go
 ├ config/config.go
 ├ firebase.firebase.go
 └ main.go


statikを導入
$ go get github.com/rakyll/[email protected]


プロジェクトルート/assetの下にenvironment/環境名.yamlとfirebase/credential.jsonを設置する。


コマンドを実行。statik/statik.goが生成される。
$ statik -src asset


以下Staticでファイル読むための処理
main.go
package main

import (
  "flag"

  "プロジェクトルート/config"
  "プロジェクトルート/firebase"
  "github.com/facebookgo/grace/gracehttp"
  "github.com/labstack/echo/v4"
  //statik バイナリ化したassetファイルのPATH
  _ "プロジェクトルート/statik"
)

func main() {
  // 環境設定取得 パラメータ名, デフォルト, 説明
  env := flag.String("e", "develop", "環境名")
  //flag.Parseで値が入る
  flag.Parse()
  //パラメータを渡してconfigの初期化を行う
  config.Init(*env, "environment")
  //Firebase初期化
  firebase.Init()

  // サーバースタート(echo)
  e := echo.New()
  e.HideBanner = true
  e.HidePort = true

  e.POST("/", handler.function)

  e.Server.Addr = ":8000"
  e.Logger.Fatal(gracehttp.Serve(e.Server))
}


config.go
package config

import (
  "bytes"
  "io/ioutil"

  "github.com/rakyll/statik/fs"
  "github.com/spf13/viper"
)

var c *viper.Viper

// Init Configの初期化
func Init(env string, path string) {
  //Viperという設定ファイル用ライブラリを使う
  c = viper.New()
  c.SetConfigType("YAML")
  // statik
  fileSystem, _ := fs.New()
  //statikコマンド時に指定したディレクトリ以下を指定
  f, err := fileSystem.Open("/" + path + "/" + env + ".yaml")
  if err != nil {
  }
  // fileを読んでbyteに 
  r, _ := ioutil.ReadAll(f)
  if err := c.ReadConfig(bytes.NewBuffer(r)); err != nil {
    panic(err)
  }
}

// GetConfig returns config
func GetConfig() *viper.Viper {
  return c
}


firebase.go
package firebase

import (
  "context"
  "io/ioutil"

  firebase "firebase.google.com/go"
  "firebase.google.com/go/auth"
  "firebase.google.com/go/messaging"
  "github.com/labstack/echo/v4"
  "github.com/rakyll/statik/fs"
  "google.golang.org/api/option"
)

var fb *firebase.App
var message *messaging.Client
var authenticate *auth.Client

//Init firebase 初期化
func Init() {
  c := config.GetConfig()
  ctx := context.Background()
  config := &firebase.Config{ProjectID: プロジェクトID}
  //
  fileSystem, _ := fs.New()
  f, openErr := fileSystem.Open(firebase/クレデンシャル名.json)
  if openErr != nil {
    panic(openErr)
  }
  // 同じくbyteに
  r, readErr := ioutil.ReadAll(f)
  if readErr != nil {
    panic(readErr)
  }
  // WithCredentialsJSONでClientOptionを生成
  opt := option.WithCredentialsJSON(r)
  var err error
  fb, err = firebase.NewApp(ctx, config, opt)
  if err != nil {
    panic(err)
  }

  message, err = fb.Messaging(ctx)
  if err != nil {
    panic(err)
  }
  authenticate, err = fb.Auth(ctx)
  if err != nil {
    panic(err)
  }
}