Skip to content

Commit

Permalink
Add Config API Service & Refactor Config Implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
JackDallas committed Jun 4, 2022
1 parent 3cd946e commit 46130f8
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 44 deletions.
13 changes: 8 additions & 5 deletions cmd/premiumizearrd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"flag"
"path"
"time"

"github.com/jackdallas/premiumizearr/internal/arr"
Expand All @@ -21,10 +22,12 @@ func main() {
//Flags
var logLevel string
var configFile string
var loggingDirectory string

//Parse flags
flag.StringVar(&logLevel, "log", utils.EnvOrDefault("PREMIUMIZEARR_LOG_LEVEL", "info"), "Logging level: \n \tinfo,debug,trace")
flag.StringVar(&configFile, "config", utils.EnvOrDefault("PREMIUMIZEARR_CONFIG_PATH", ""), "Config file path")
flag.StringVar(&configFile, "config", utils.EnvOrDefault("PREMIUMIZEARR_CONFIG_DIR_PATH", "./"), "The directory the config.yml is located in")
flag.StringVar(&loggingDirectory, "logging-dir", utils.EnvOrDefault("PREMIUMIZEARR_LOGGING_DIR_PATH", "./"), "The directory logs are to be written to")
flag.Parse()

lvl, err := log.ParseLevel(logLevel)
Expand All @@ -35,7 +38,7 @@ func main() {
log.SetLevel(lvl)
hook, err := lumberjackrus.NewHook(
&lumberjackrus.LogFile{
Filename: "/opt/premiumizearrd/premiumizearr.general.log",
Filename: path.Join(loggingDirectory, "premiumizearr.general.log"),
MaxSize: 100,
MaxBackups: 1,
MaxAge: 1,
Expand All @@ -46,15 +49,15 @@ func main() {
&log.TextFormatter{},
&lumberjackrus.LogFileOpts{
log.InfoLevel: &lumberjackrus.LogFile{
Filename: "/opt/premiumizearrd/premiumizearr.info.log",
Filename: path.Join(loggingDirectory, "premiumizearr.info.log"),
MaxSize: 100,
MaxBackups: 1,
MaxAge: 1,
Compress: false,
LocalTime: false,
},
log.ErrorLevel: &lumberjackrus.LogFile{
Filename: "/opt/premiumizearrd/premiumizearr.error.log",
Filename: path.Join(loggingDirectory, "premiumizearr.error.log"),
MaxSize: 100, // optional
MaxBackups: 1, // optional
MaxAge: 1, // optional
Expand All @@ -80,7 +83,7 @@ func main() {
}

if config.PremiumizemeAPIKey == "" {
panic("premiumizearr API Key is empty")
log.Warn("Premiumizeme API key not set, application will not work until it's set")
}

// Initialisation
Expand Down
71 changes: 36 additions & 35 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package config
import (
"errors"
"io/ioutil"
"log"

log "github.com/sirupsen/logrus"

"os"
"path"

Expand Down Expand Up @@ -31,6 +33,8 @@ type ArrConfig struct {
}

type Config struct {
altConfigLocation string

PremiumizemeAPIKey string `yaml:"PremiumizemeAPIKey"`

Arrs []ArrConfig `yaml:"Arrs"`
Expand All @@ -48,9 +52,9 @@ type Config struct {
SimultaneousDownloads int `yaml:"SimultaneousDownloads"`
}

func loadConfigFromDisk() (Config, error) {
func loadConfigFromDisk(altConfigLocation string) (Config, error) {
var config Config
file, err := ioutil.ReadFile("config.yaml")
file, err := ioutil.ReadFile(path.Join(altConfigLocation, "config.yaml"))

if err != nil {
return config, ErrFailedToFindConfigFile
Expand All @@ -63,15 +67,31 @@ func loadConfigFromDisk() (Config, error) {

config = versionUpdateConfig(config)

data, err := yaml.Marshal(config)
if err == nil {
//Save config to disk to add missing fields
ioutil.WriteFile("config.yaml", data, 0644)
}
config.Save()

config.altConfigLocation = altConfigLocation
return config, nil
}

func (c *Config) Save() bool {
log.Trace("Marshaling & saving config")
data, err := yaml.Marshal(*c)
if err != nil {
log.Error(err)
return false
}

log.Tracef("Writing config to %s", path.Join(c.altConfigLocation, "config.yaml"))
err = ioutil.WriteFile(path.Join(c.altConfigLocation, "config.yaml"), data, 0644)
if err != nil {
log.Errorf("Failed to save config file: %+v", err)
return false
}

log.Trace("Config saved")
return true
}

func versionUpdateConfig(config Config) Config {
// 1.1.3
if config.SimultaneousDownloads == 0 {
Expand All @@ -81,12 +101,12 @@ func versionUpdateConfig(config Config) Config {
return config
}

func createDefaultConfig() error {
config := Config{
func defaultConfig(altConfigLocation string) Config {
return Config{
PremiumizemeAPIKey: "xxxxxxxxx",
Arrs: []ArrConfig{
{URL: "http://localhost:8989", APIKey: "xxxxxxxxx", Type: Sonarr},
{URL: "http://localhost:7878", APIKey: "xxxxxxxxx", Type: Radarr},
{Name: "Sonarr", URL: "http://localhost:8989", APIKey: "xxxxxxxxx", Type: Sonarr},
{Name: "Radarr", URL: "http://localhost:7878", APIKey: "xxxxxxxxx", Type: Radarr},
},
BlackholeDirectory: "",
DownloadsDirectory: "",
Expand All @@ -96,35 +116,16 @@ func createDefaultConfig() error {
WebRoot: "",
SimultaneousDownloads: 5,
}

file, err := yaml.Marshal(config)
if err != nil {
return err
}

err = ioutil.WriteFile("config.yaml", file, 0644)
if err != nil {
return err
}

return nil
}

func LoadOrCreateConfig(altConfigLocation string) (Config, error) {
if altConfigLocation != "" {
if _, err := ioutil.ReadFile(altConfigLocation); err != nil {
log.Panicf("Failed to find config file at %s Error: %+v", altConfigLocation, err)
}
}

config, err := loadConfigFromDisk()
config, err := loadConfigFromDisk(altConfigLocation)
if err != nil {
if err == ErrFailedToFindConfigFile {
err = createDefaultConfig()
if err != nil {
return config, err
}
panic("Default config created, please fill it out")
config = defaultConfig(altConfigLocation)
log.Warn("No config file found, created default config file")
config.Save()
}
if err == ErrInvalidConfigFile {
return config, ErrInvalidConfigFile
Expand Down
5 changes: 3 additions & 2 deletions internal/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ func GetDownloadsFolderIDFromPremiumizeme(premiumizemeClient *premiumizeme.Premi
folders, err := premiumizemeClient.GetFolders()
if err != nil {
log.Errorf("Error getting folders: %s", err)
log.Fatalf("Cannot read folders from premiumize.me, exiting!")
log.Errorf("Cannot read folders from premiumize.me, application will not run!")
return ""
}

const folderName = "arrDownloads"
Expand All @@ -102,7 +103,7 @@ func GetDownloadsFolderIDFromPremiumizeme(premiumizemeClient *premiumizeme.Premi
if len(downloadsFolderID) == 0 {
id, err := premiumizemeClient.CreateFolder(folderName)
if err != nil {
log.Fatalf("Cannot create downloads folder on premiumize.me, exiting! %+v", err)
log.Errorf("Cannot create downloads folder on premiumize.me, application will not run correctly! %+v", err)
}
downloadsFolderID = id
}
Expand Down
57 changes: 57 additions & 0 deletions internal/web_service/config_routes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package web_service

import (
"encoding/json"
"fmt"
"net/http"

"github.com/jackdallas/premiumizearr/internal/config"
)

type ConfigChangeResponse struct {
Succeeded bool `json:"succeeded"`
Status string `json:"status"`
}

func (s *server) ConfigHandler(w http.ResponseWriter, r *http.Request) {

switch r.Method {
case http.MethodGet:
data, err := json.Marshal(s.config)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Write(data)
case http.MethodPost:
var newConfig config.Config
err := json.NewDecoder(r.Body).Decode(&newConfig)
if err != nil {
EncodeAndWriteConfigChangeResponse(w, &ConfigChangeResponse{
Succeeded: false,
Status: fmt.Sprintf("Config failed to update %s", err.Error()),
})
return
}
s.config = &newConfig
s.config.Save()
EncodeAndWriteConfigChangeResponse(w, &ConfigChangeResponse{
Succeeded: true,
Status: "Config updated",
})
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}

}

func EncodeAndWriteConfigChangeResponse(w http.ResponseWriter, resp *ConfigChangeResponse) {
data, err := json.Marshal(resp)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Write(data)
}
13 changes: 11 additions & 2 deletions internal/web_service/web_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ var indexBytes []byte
type server struct {
transferManager *service.TransferManagerService
directoryWatcherService *service.DirectoryWatcherService
config *config.Config
}

// http Router
func StartWebServer(transferManager *service.TransferManagerService, directoryWatcher *service.DirectoryWatcherService, config *config.Config) {
log.Info("Starting web server...")
tmpl, err := template.ParseFiles("./static/index.html")
if err != nil {
log.Fatal(err)
Expand All @@ -47,6 +49,7 @@ func StartWebServer(transferManager *service.TransferManagerService, directoryWa
s := server{
transferManager: transferManager,
directoryWatcherService: directoryWatcher,
config: config,
}
spa := spaHandler{
staticPath: "static",
Expand All @@ -59,27 +62,33 @@ func StartWebServer(transferManager *service.TransferManagerService, directoryWa
transferPath := "/api/transfers"
downloadsPath := "/api/downloads"
blackholePath := "/api/blackhole"
configPathBase := "/api/config"

if config.WebRoot != "" {
transferPath = path.Join(config.WebRoot, transferPath)
downloadsPath = path.Join(config.WebRoot, downloadsPath)
blackholePath = path.Join(config.WebRoot, blackholePath)
configPathBase = path.Join(config.WebRoot, configPathBase)
}

r.HandleFunc(transferPath, s.TransfersHandler)
r.HandleFunc(downloadsPath, s.DownloadsHandler)
r.HandleFunc(blackholePath, s.BlackholeHandler)
r.HandleFunc(configPathBase, s.ConfigHandler)

r.PathPrefix("/").Handler(spa)

address := fmt.Sprintf("%s:%s", config.BindIP, config.BindPort)

srv := &http.Server{
Handler: r,
Addr: fmt.Sprintf("%s:%s", config.BindIP, config.BindPort),
Addr: address,
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}

log.Infof("Web server started on %s", address)
srv.ListenAndServe()
}

Expand Down Expand Up @@ -173,7 +182,7 @@ func (s *server) BlackholeHandler(w http.ResponseWriter, r *http.Request) {
w.Write(data)
}

// Shamlessly stolen from mux examples https://github.com/gorilla/mux#examples
// Shamelessly stolen from mux examples https://github.com/gorilla/mux#examples
type spaHandler struct {
staticPath string
indexPath string
Expand Down

0 comments on commit 46130f8

Please sign in to comment.