Config: Add Docker env string to backend requests (develop, prod)

For easier debugging so that development environments can be identified.
This commit is contained in:
Michael Mayer 2022-03-02 14:16:49 +01:00
parent 6fb0eb2abe
commit 6bebf9043b
9 changed files with 69 additions and 34 deletions

View file

@ -12,6 +12,8 @@ import (
"github.com/gin-gonic/gin"
)
// SendFeedback sends a feedback message.
//
// POST /api/v1/feedback
func SendFeedback(router *gin.RouterGroup) {
router.POST("/feedback", func(c *gin.Context) {

View file

@ -74,6 +74,7 @@ type Config struct {
hub *hub.Config
token string
serial string
env string
}
func init() {
@ -118,6 +119,7 @@ func NewConfig(ctx *cli.Context) *Config {
c := &Config{
options: NewOptions(ctx),
token: rnd.Token(8),
env: os.Getenv("DOCKER_ENV"),
}
if configFile := c.ConfigFile(); c.options.ConfigFile == "" && fs.FileExists(configFile) {
@ -209,8 +211,8 @@ func (c *Config) Init() error {
log.Infof("config: make sure your server has enough swap configured to prevent restarts when there are memory usage spikes")
}
// Set User Agent for HTTP requests.
places.UserAgent = fmt.Sprintf("%s/%s", c.Name(), c.Version())
// Set HTTP user agent.
places.UserAgent = c.UserAgent()
c.initSettings()
c.initHub()
@ -285,9 +287,9 @@ func (c *Config) Version() string {
return c.options.Version
}
// UserAgent returns a HTTP user agent string based on app name & version.
// UserAgent returns an HTTP user agent string based on the app config and version.
func (c *Config) UserAgent() string {
return fmt.Sprintf("%s/%s", c.Name(), c.Version())
return fmt.Sprintf("%s/%s (%s)", c.Name(), c.Version(), strings.Join(c.Flags(), "; "))
}
// Copyright returns the application copyright.
@ -598,7 +600,7 @@ func (c *Config) UpdateHub() {
// initHub initializes PhotoPrism hub config.
func (c *Config) initHub() {
c.hub = hub.NewConfig(c.Version(), c.HubConfigFile(), c.serial, c.options.PartnerID)
c.hub = hub.NewConfig(c.Version(), c.HubConfigFile(), c.serial, c.env, c.UserAgent(), c.options.PartnerID)
if err := c.hub.Load(); err == nil {
// Do nothing.

View file

@ -16,35 +16,40 @@ import (
"strings"
"time"
"gopkg.in/yaml.v2"
"github.com/photoprism/photoprism/internal/hub/places"
"github.com/photoprism/photoprism/pkg/fs"
"github.com/photoprism/photoprism/pkg/sanitize"
"gopkg.in/yaml.v2"
)
// Config represents backend api credentials for maps & geodata.
type Config struct {
Version string `json:"version" yaml:"Version"`
FileName string `json:"-" yaml:"-"`
Key string `json:"key" yaml:"Key"`
Secret string `json:"secret" yaml:"Secret"`
Session string `json:"session" yaml:"Session"`
Status string `json:"status" yaml:"Status"`
Version string `json:"version" yaml:"Version"`
Serial string `json:"serial" yaml:"Serial"`
FileName string `json:"-" yaml:"-"`
Env string `json:"-" yaml:"-"`
UserAgent string `json:"-" yaml:"-"`
PartnerID string `json:"-" yaml:"-"`
}
// NewConfig creates a new backend api credentials instance.
func NewConfig(version, fileName, serial, partner string) *Config {
func NewConfig(version, fileName, serial, env, userAgent, partnerId string) *Config {
return &Config{
Version: version,
FileName: fileName,
Key: "",
Secret: "",
Session: "",
Status: "",
Version: version,
Serial: serial,
FileName: fileName,
PartnerID: partner,
Env: env,
UserAgent: userAgent,
PartnerID: partnerId,
}
}
@ -147,16 +152,26 @@ func (c *Config) Refresh() (err error) {
log.Debugf("config: requesting new api key for maps and places")
}
if j, err := json.Marshal(NewRequest(c.Version, c.Serial, c.PartnerID)); err != nil {
// Create request.
if j, err := json.Marshal(NewRequest(c.Version, c.Serial, c.Env, c.PartnerID)); err != nil {
return err
} else if req, err = http.NewRequest(method, url, bytes.NewReader(j)); err != nil {
return err
}
// Set user agent.
if c.UserAgent != "" {
req.Header.Set("User-Agent", c.UserAgent)
} else {
req.Header.Set("User-Agent", "PhotoPrism/Test")
}
// Add Content-Type header.
req.Header.Add("Content-Type", "application/json")
var r *http.Response
// Send request.
for i := 0; i < 3; i++ {
r, err = client.Do(req)
@ -165,6 +180,7 @@ func (c *Config) Refresh() (err error) {
}
}
// Ok?
if err != nil {
return err
} else if r.StatusCode >= 400 {
@ -172,6 +188,7 @@ func (c *Config) Refresh() (err error) {
return err
}
// Decode JSON response.
err = json.NewDecoder(r.Body).Decode(c)
if err != nil {

View file

@ -8,7 +8,7 @@ import (
func TestConfig_MapKey(t *testing.T) {
t.Run("success", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/new.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/new.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
assert.Equal(t, "", c.MapKey())
})
}

View file

@ -22,28 +22,31 @@ type Feedback struct {
UserEmail string `json:"UserEmail"`
UserAgent string `json:"UserAgent"`
ApiKey string `json:"ApiKey"`
PartnerID string `json:"PartnerID"`
ClientVersion string `json:"ClientVersion"`
ClientSerial string `json:"ClientSerial"`
ClientOS string `json:"ClientOS"`
ClientArch string `json:"ClientArch"`
ClientCPU int `json:"ClientCPU"`
ClientEnv string `json:"ClientEnv"`
PartnerID string `json:"PartnerID"`
}
// NewFeedback creates a new hub feedback instance.
func NewFeedback(version, serial, partner string) *Feedback {
func NewFeedback(version, serial, env, partnerId string) *Feedback {
return &Feedback{
PartnerID: partner,
ClientVersion: version,
ClientSerial: serial,
ClientOS: runtime.GOOS,
ClientArch: runtime.GOARCH,
ClientCPU: runtime.NumCPU(),
ClientEnv: env,
PartnerID: partnerId,
}
}
// SendFeedback sends a feedback message.
func (c *Config) SendFeedback(f form.Feedback) (err error) {
feedback := NewFeedback(c.Version, c.Serial, c.PartnerID)
feedback := NewFeedback(c.Version, c.Serial, c.Env, c.PartnerID)
feedback.Category = f.Category
feedback.Subject = txt.Shorten(f.Message, 50, "...")
feedback.Message = f.Message
@ -66,6 +69,13 @@ func (c *Config) SendFeedback(f form.Feedback) (err error) {
return err
}
// Set user agent.
if c.UserAgent != "" {
req.Header.Set("User-Agent", c.UserAgent)
} else {
req.Header.Set("User-Agent", "PhotoPrism/Test")
}
req.Header.Add("Accept-Language", f.UserLocales)
req.Header.Add("Content-Type", "application/json")

View file

@ -9,7 +9,7 @@ import (
func TestNewFeedback(t *testing.T) {
t.Run("success", func(t *testing.T) {
feedback := NewFeedback("xxx", "zqkunt22r0bewti9", "test")
feedback := NewFeedback("xxx", "zqkunt22r0bewti9", "test", "test")
assert.Equal(t, "xxx", feedback.ClientVersion)
assert.Equal(t, "zqkunt22r0bewti9", feedback.ClientSerial)
})
@ -17,7 +17,7 @@ func TestNewFeedback(t *testing.T) {
func TestSendFeedback(t *testing.T) {
t.Run("success", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/new.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/new.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
feedback := Feedback{
Category: "Bug Report",

View file

@ -49,13 +49,13 @@ func Token(size uint) string {
}
func TestNewConfig(t *testing.T) {
c := NewConfig("0.0.0", "testdata/new.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/new.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
assert.IsType(t, &Config{}, c)
}
func TestNewRequest(t *testing.T) {
r := NewRequest("0.0.0", "zqkunt22r0bewti9", "test")
r := NewRequest("0.0.0", "zqkunt22r0bewti9", "test", "test")
assert.IsType(t, &Request{}, r)
@ -72,7 +72,7 @@ func TestConfig_Refresh(t *testing.T) {
t.Run("success", func(t *testing.T) {
fileName := fmt.Sprintf("testdata/hub.%s.yml", Token(8))
c := NewConfig("0.0.0", fileName, "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", fileName, "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
if err := c.Refresh(); err != nil {
t.Fatal(err)
@ -122,7 +122,7 @@ func TestConfig_Refresh(t *testing.T) {
func TestConfig_DecodeSession(t *testing.T) {
t.Run("hub3.yml", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/hub3.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/hub3.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
err := c.Load()
@ -138,7 +138,7 @@ func TestConfig_DecodeSession(t *testing.T) {
func TestConfig_Load(t *testing.T) {
t.Run("hub1.yml", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/hub1.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/hub1.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
if err := c.Load(); err != nil {
t.Logf(err.Error())
@ -151,7 +151,7 @@ func TestConfig_Load(t *testing.T) {
assert.Equal(t, "0.0.0", c.Version)
})
t.Run("hub2.yml", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/hub2.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/hub2.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
if err := c.Load(); err != nil {
t.Logf(err.Error())
@ -164,7 +164,7 @@ func TestConfig_Load(t *testing.T) {
assert.Equal(t, "200925-f8e2b580-Darwin-i386-DEBUG", c.Version)
})
t.Run("not existing filename", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/hub_xxx.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/hub_xxx.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
if err := c.Load(); err == nil {
t.Fatal("file should not exist")
@ -180,7 +180,7 @@ func TestConfig_Save(t *testing.T) {
t.Run("existing filename", func(t *testing.T) {
assert.FileExists(t, "testdata/hub1.yml")
c := NewConfig("0.0.0", "testdata/hub1.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/hub1.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
if err := c.Load(); err != nil {
t.Logf(err.Error())
@ -219,7 +219,7 @@ func TestConfig_Save(t *testing.T) {
assert.Equal(t, "0.0.0", c.Version)
})
t.Run("not existing filename", func(t *testing.T) {
c := NewConfig("0.0.0", "testdata/hub_new.yml", "zqkunt22r0bewti9", "test")
c := NewConfig("0.0.0", "testdata/hub_new.yml", "zqkunt22r0bewti9", "test", "PhotoPrism/Test", "test")
c.Key = "F60F5B25D59C397989E3CD374F81CDD7710A4FCA"
c.Secret = "foo"
c.Session = "bar"

View file

@ -31,7 +31,7 @@ const ApiName = "places"
var Key = "f60f5b25d59c397989e3cd374f81cdd7710a4fca"
var Secret = "photoprism"
var UserAgent = "PhotoPrism/dev"
var UserAgent = ""
var ReverseLookupURL = "https://places.photoprism.app/v1/location/%s"
var Retries = 3
@ -84,9 +84,11 @@ func FindLocation(id string) (result Location, err error) {
return result, err
}
// Add User-Agent header?
// Set user agent.
if UserAgent != "" {
req.Header.Set("User-Agent", UserAgent)
} else {
req.Header.Set("User-Agent", "PhotoPrism/Test")
}
// Add API key?

View file

@ -9,23 +9,25 @@ var ServiceURL = "https://hub.photoprism.app/v1/hello"
// Request represents basic environment specs for debugging.
type Request struct {
PartnerID string `json:"PartnerID"`
ClientVersion string `json:"ClientVersion"`
ClientSerial string `json:"ClientSerial"`
ClientOS string `json:"ClientOS"`
ClientArch string `json:"ClientArch"`
ClientCPU int `json:"ClientCPU"`
ClientEnv string `json:"ClientEnv"`
PartnerID string `json:"PartnerID"`
}
// NewRequest creates a new backend key request instance.
func NewRequest(version, serial, partner string) *Request {
func NewRequest(version, serial, env, partnerId string) *Request {
return &Request{
PartnerID: partner,
ClientVersion: version,
ClientSerial: serial,
ClientOS: runtime.GOOS,
ClientArch: runtime.GOARCH,
ClientCPU: runtime.NumCPU(),
ClientEnv: env,
PartnerID: partnerId,
}
}