Cannot update configuration file dynamically in go with viper package

214 Views Asked by At

I'm trying to dynamically load configuration file for my cli application built with go. I'm loading configuration variables from a toml file. I'm using viper package to load the configurations and directly store in a config struct that I have created. config.toml

    ACCOUNT_NAME = "AccountName"
    ACCOUNT_KEY= "AccountKey"
    CONNECTION_STRING="connectionString"
    CONTAINER_NAME="mycontainerName"

    ROOT_DIR="rootDir"
    SUB_DIR_1="subDir1"
    SUB_DIR_2="subDir2"

config.go

type Config struct {
    ACCOUNT_NAME      string
    ACCOUNT_KEY       string
    CONNECTION_STRING string
    CONTAINER_NAME    string

    ROOT_DIR      string
    SUB_DIR_1     string
    SUB_DIR_2     string
}

utils/fileLocation.go

type FileLocation struct {
    ROOT_DIR      string
    SUB_DIR_1     string
    SUB_DIR_2     string
}

func (l FileLocation) GetDirectoryLocation() string {
    return filepath.Join(l.ROOT_DIR, l.SUB_DIR_1, l.SUB_DIR_2)
}

main.go

    func main() {
    var config config.Config
    viper.SetConfigName("config")
    viper.SetConfigType("toml")
    configFilePath := filepath.Join(".", "config")
    viper.AddConfigPath(configFilePath)
    errRIC := viper.ReadInConfig()
    utils.HandleError(errRIC)
    errUM := viper.Unmarshal(&config)
    utils.HandleError(errUM)

    log.Println(config.ACCOUNT_NAME)
    log.Println(config.ACCOUNT_KEY)
    log.Println(config.CONTAINER_NAME)

    fileLocation := utils.FileLocation{
        ROOT_DIR :     string
        SUB_DIR_1:     string
        SUB_DIR_2:     string
    }

    var blob *azureBlob.Blob
    viper.WatchConfig()
    viper.OnConfigChange(func(e fsnotify.Event) {
        err := viper.Unmarshal(&config)
        utils.HandleError(err)
        log.Println("Config Changed")
        blob = &azureBlob.Blob{
            AccountName:   config.ACCOUNT_NAME,
            AccountKey:    config.ACCOUNT_KEY,
            ContainerName: config.CONTAINER_NAME,
        }
        // log.Println(config.ACCOUNT_NAME)
        // log.Println(config.ACCOUNT_KEY)
        // log.Println(config.CONTAINER_NAME)
    })

    blob = &azureBlob.Blob{
        AccountName:   config.ACCOUNT_NAME,
        AccountKey:    config.ACCOUNT_KEY,
        ContainerName: config.CONTAINER_NAME,
    }
    filelocation := fileLocation.GetDirectoryLocation()

    go uploadFilesFromLocation(location, blob)

    func uploadFilesFromLocation(location, blob azblob.Blob) {
      for {
        files, err := os.ReadDir(location)
        utils.HandleError(err)
        for _, file := range files {
           go blob.UploadFile(file)
         }
      }
    }
   fmt.Scanln() # for blocking the main go routing until other go routine finishes task.

azureBlob.go

type Blob struct {
    AccountName                   string
    AccountKey                    string
    AzrPrimaryBlobServiceEndpoint string
    ContainerName                 string
}

func (b *Blob) UploadFileToBLob(file string) {
    log.Printf("Uploading file: %s to cloud....", file)
    openedFile, err := os.Open(file)
    utils.HandleError(err)
    defer openedFile.Close()
    blockBlobURL := b.GetBlockBlobURL()
    blockBlobOptions := b.GetBlockBlobOptions()
    _, errUpload := azblob.UploadFileToBlockBlob(openedFile, blockBlobURL, blockBlobOptions)
    utils.HandleError(errUpload)
    log.Printf("Successfully uploaded file %s to cloud!", file)
    log.Printf("Successfully uploaded file to %v", blockBlobURL)
}

func (b *Blob) GetAccountInfo() (string, string, string, string) {
    return b.AccountKey, b.AccountName, b.AzrPrimaryBlobServiceEndpoint, b.ContainerName
}

func (b *Blob) GetBlobName() string {
    t := time.Now().UTC()
    return fmt.Sprintf("%s/%s.mp4", t.Format("2006_01_02"), t.Format("2006_01_02_15_04_05"))
}

func (b Blob) GetBlockBlobURL() azblob.BlockBlobURL {
    AzrPrimaryBlobServiceEndpoint := fmt.Sprintf("https://%s.blob.core.windows.net/", b.AccountName)
    u, _ := url.Parse(fmt.Sprint(AzrPrimaryBlobServiceEndpoint, b.ContainerName, "/", b.GetBlobName()))
    credential, err := azblob.NewSharedKeyCredential(b.AccountName, b.AccountKey)
    utils.HandleError(err)
    blockBlobURL := azblob.NewBlockBlobURL(*u, azblob.NewPipeline(credential, azblob.PipelineOptions{}))
    return blockBlobURL
}

func (b *Blob) GetBlockBlobOptions() azblob.UploadToBlockBlobOptions {
    o := azblob.UploadToBlockBlobOptions{
        BlobHTTPHeaders: azblob.BlobHTTPHeaders{
            ContentType: "video/mp4",
        },
    }
    return o
}

Whenever I change the CONTAINER_NAME from mycontainerName1 to mycontainerName2 in configuration file (config.toml), It prints "Config Changed" two times but the file is still uploading to mycontainerName1.

I think the issue maybe due to since, the UploadFileToBlob will run as a separate go routine and the main go routine will run separately. So, I'm updating Config and blob structs using the & operator. But still it did'nt worked.

0

There are 0 best solutions below