1

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.

rangarajan
  • 143
  • 5
  • 17
  • For duplication of log lines, it depends on how you're saving the file. If you save it directly within VSCode, it appears two times in the log (I think it's a known [bug](https://github.com/fsnotify/fsnotify/issues/122)). If you save the file with gedit (I'm based on Ubuntu), it prints only a single line. About your load issue, can you adjust the code snippet to be clearer? Maybe add less code only with the relevant part and try to better explain the issue. Thanks a lot! – ossan Nov 07 '22 at 15:43

0 Answers0