RFC-0004: core-lib-repo
- RFC PR: iver-wharf/rfcs#4
- Feature name:
core-lib-repo
- Author: Kalle Jillheden (@jilleJr)
- Implementation issue: iver-wharf/wharf-core#1
- Implementation status:
Summary
Proposed location to place utility code, such as loading config values or serving version endpoints, so that our other repositories can take use of it.
Motivation
We start seeing some duplication of code in our repositories. Instead of duplicating that code throughout the repos, we can collect them into a single repository that the other repos then depend on.
This issue has been planned for a while, but put into motion by the review comment by @Pikabanga on iver-wharf/wharf-provider-github.
Explanation
The utility repository, https://github.com/iver-wharf/wharf-core, holds code that does not solve any particular problems that’s specific for the different component’s domains.
Instead, it is a place of common utility code. What you will find in this utility repository is Go code that features:
- Reading configuration from files and/or environment variables
- Logging in a unified manner
- Serving common endpoints such as
GET /version
What you will not find in this repository:
- ❌ Parsing
.wharf-ci.yml
files - ❌ Abstractions over Kubernetes
- ❌ Abstractions over AMQP (already found in iver-wharf/messagebus-go)
- ❌ Common database or HTTP JSON models
Sample:
package main
import (
"io/ioutil"
_ "embed"
"github.com/iver-wharf/wharf-core/pkg/app"
"github.com/iver-wharf/wharf-core/pkg/config"
"github.com/iver-wharf/wharf-core/pkg/ginutils"
"github.com/iver-wharf/wharf-core/pkg/log"
"github.com/gin-gonic/gin"
)
type DBConfig struct {
Host string `yaml:"host" env:"HOST"`
Port int `yaml:"port" env:"PORT"`
Username string `yaml:"username" env:"USERNAME"`
Password string `yaml:"password" env:"PASSWORD"`
}
type Config struct {
Logging log.Config `yaml:"logging" env:"LOGGING"`
API ginutils.Config `yaml:"api" env:"API"`
DB DBConfig `yaml:"db" env:"DB"`
}
type Version struct {
app.Version
}
// go:embed version.yaml
var versionFile []byte
// @title Sample program
// @description This program takes use of the utility repository to load in
// @description the config and version of the app.
func main() {
var version Version
config.UnmarshalYAML(versionFile, &version, config.Options{})
log.Infof("sample-program version=%s", version.AppVersion)
var config Config
configFile, _ := ioutil.ReadFile("config.yaml")
config.UnmarshalYAML(configFile, &config, config.Options{
AllowEnvironmentVariables: true,
})
log.SetConfig(config.Logging)
log.Info("Successfully read config.")
r := gin.Default()
// func ApplyConfig(engine *gin.Engine, ginutils.Config)
ginutils.ApplyConfig(r, config.API)
// func AddVersionEndpoint(engine *gin.Engine, version interface{})
ginutils.AddVersionEndpoint(r, version)
r.Run()
}
# config.yaml
logging:
level: debug
blacklist:
- gin
- gorm
api:
allowCors: true
db:
host: localhost
port: 5432
username: postgres
password: changeit # Can be overritten with WHARF_DB_PASSWORD environment variable
# version.yaml
$schema: https://github.com/iver-wharf/wharf-core/raw/master/pkg/app/version-schema.json
appVersion: v1.0.0
buildGitCommit: 5971d3b585a722536730c39a22aa3148993f2985
buildRef: 123
buildDate: 2021-05-12T13:55:00+02:00
Compatibility
In architectural terms, this utility repository has to be “stable”. Meaning it will be a hassle to update as there will be so many components relying on it.
This may not be that big of an issue for added features though. It may induce issues from time to time where we have to make 4 PRs each time we update the logging library, but I [Kalle] don’t think that’s a major issue as those components should not rely on the logic from the utilities repo to cooperate.
Alternative solutions
Placing this inside the https://github.com/iver-wharf/wharf-api repository. While this would work for most of the logic here, it does not play well later when the cmd
project wants to take use of these utilities as well, such as the logging.
Future possibilities
It allows for a unified way of configuring the services. If we can set a unified convention of setting configs via files and being able to override them with environment variables, then that would lift the operations-experience of using Wharf to a much better level. Heavily inspired by the appsettings.json
solution for configuring ASP.NET Core apps
Unresolved questions
-
What should be the name of the repo?
Suggestion Votes github.com/iver-wharf/wharf-core @jilleJr, @Pikabanga github.com/iver-wharf/wharf-core-lib github.com/iver-wharf/wharf-extra github.com/iver-wharf/wharf-utility github.com/iver-wharf/wharf-util github.com/iver-wharf/wharf-utils @iverestefans