Viper Configuration Solutions - Backup Files Software From Scratch Written in Golang Tutorial #4

Опубликовано: 02 Ноябрь 2024
на канале: Maharlikans Code
740
15

In this tutorial series #4, we know how to use the Viper complete configuration solutions for Go.

Installed Packages:
https://github.com/common-nighthawk/g...
https://github.com/fsnotify/fsnotify
https://github.com/mitchellh/go-homedir
https://github.com/spf13/viper

If you go with extra mile for buying me a cup of coffee, I appreciate it guys: https://ko-fi.com/maharlikanscode

#MaharlikansCode
#Viper
#Golang
#LifeAsSoftwareDeveloper
#Maharlikans
#FilipinoSoftwareDeveloper
#ReadConfigurationFileInGolang

Source Codes:
main.go
package main

import (
"gokopy/cmd"
)

func main() {
cmd.Execute()
}

root.go
package cmd

import (
"errors"
"fmt"
"gokopy/config"
"os"
"strings"

"github.com/common-nighthawk/go-figure"
"github.com/fatih/color"
"github.com/fsnotify/fsnotify"
"github.com/itrepablik/itrlog"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

// AppInfo ...
type AppInfo struct {
Name, Version string
}

// ConfigComDir is the collection of the comdir config values
type ConfigComDir struct {
Ignore []string
Log bool
}

var appCon []AppInfo
var conComDir []ConfigComDir
var comdirIgnore []string
var comdirLog bool = false
var cfgFile string

var logDTFormat string = config.DefaultDTFormat

var rootCmd = &cobra.Command{
Use: config.AppName,
Short: config.AppDesc,
Long: config.AppDesc,
Version: config.AppVersion,
// Run: func(cmd *cobra.Command, args []string) {
// // Do Stuff Here
// fmt.Println("Hello Cobra CLI application")
// },
}

// Execute ...
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
// Display the app ASCII logo
myFigure := figure.NewFigure(config.AppDisplayName, "", true)
myFigure.Print()

LoadViperCofig()
viper.WatchConfig() // Tell the viper to watch any new changes to the config file.
viper.OnConfigChange(func(e fsnotify.Event) {
fmt.Println("Config file changed:", e.Name)
itrlog.Warn("Config file changed:", e.Name)
LoadViperCofig()
})
}

// LoadViperCofig reads the viper 'config.yaml' file
func LoadViperCofig() {
//********************************************************************************************
// Recall this block of scripts to re-initialize the viper instance and gets the latest values
// from any config name value that has changes in real-time.
//********************************************************************************************
cobra.OnInitialize(initConfig)
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath(".") // optionally look for config in the working directory

// Handle errors reading the config file
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// Config file not found; create the "config.yaml" asap.
f, err := os.OpenFile("config.yaml", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
itrlog.Fatalf("error opening file: %v", err)
}
defer f.Close()
} else {
// Config file was found but another error was produced
itrlog.Fatalf("fatal error config file: %v", err)
}
}

var err error

err = viper.UnmarshalKey("app", &appCon)
if err != nil {
itrlog.Error(err)
}
for _, a := range appCon {
if len(strings.TrimSpace(a.Name)) == 0 || strings.TrimSpace(a.Name) != config.AppName {
errMsg := "app name must be " + config.AppName + ", please follow this naming convention to your config.yaml file under 'app'."
color.Red(errMsg)
itrlog.Fatal(errors.New(errMsg))
}
if len(strings.TrimSpace(a.Version)) == 0 || strings.TrimSpace(a.Version) != config.AppVersion {
errMsg := "app version must be " + config.AppVersion + ", please follow this naming convention to your config.yaml file under 'app'."
color.Red(errMsg)
itrlog.Fatal(errors.New(errMsg))
}
}

// Get the config values for the 'default.command_properties.comdir' keys from the config.yaml file
err = viper.UnmarshalKey("default.command_properties.comdir", &conComDir)
if err != nil {
itrlog.Error(err)
}
for _, a := range conComDir {
comdirIgnore = a.Ignore
comdirLog = a.Log
}
}

func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.

home, err := homedir.Dir()
if err != nil {
color.Red(err.Error())
itrlog.Error(err)
os.Exit(1)
}

// Search config in home directory with name ".gokopy" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".gokopy")
}
viper.AutomaticEnv() // read in environment variables that match

// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
color.Red("Using config file: " + viper.ConfigFileUsed())
}
}

config.yaml
app:
name: gokopy
version: 1.0.0

default:
command_properties:
comdir:
ignore: [.jpg, .png, folder_name]
log: true # true or false, true to enable the log