Golang parsing template from third party lib - go

I am writing a library which is parsing templates from its template package. When I am using it within a sample application its reading the template from its own directory but the code in libary is failing.
Here is the libary - https://github.com/bangarharshit/bigpipe-golang and I am facing issues with this line - https://github.com/bangarharshit/bigpipe-golang/blob/master/Application.go#L66
Copying code from lib -
templates, err := template.ParseFiles("templates/bigpipe.html")
if err != nil {
return
}

One alternative soultion is to copy content from file into a variable and use template.parse instead of template.parsefiles

Related

How to use go:embed to read application properties

I use viper to load runtime environment specific property files (located under ./configs/*.conf). I am looking to see how I can embed these files in the binary.
Following snippet that loads the files
viper.AddConfigPath("./configs")
viper.SetConfigName("app_dev.conf")
viper.ReadInConfig()
I have tried using the following embed directive
//go:embed configs/*.conf
var resources embed.FS
However getting an error that it cannot load the property files. It works, as expected, if I add the config folder in the same location as the binary.
I realized that I can use io.reader to load Viper config
data, _ := _configFile.ReadFile("configs/app_dev.conf")
err = viper.ReadConfig(strings.NewReader(string(data)))

Portable Go module with bundled files that must be read [duplicate]

This question already has answers here:
What's the best way to bundle static resources in a Go program?
(5 answers)
Closed last year.
I'm trying to create a portable Go module that will be re-used in many different projects. This module, in order to function, needs to be able to read non-Go files that are bundled as part of the module. In this case, they're some certificate bundles. The selection of which file to load is dynamic and based on input arguments.
What is the best way to specify the path to these files when loading them? I can't seem to find any Go functions to get a path relative to the module (vs. relative to the executable that is using this module). For example, if my module structure looks like this:
mymodule/
go.mod
go.sum
loadcerts.go
certs/
cert_A.pem
cert_B.pem
And I need to do something like this:
// loadcerts.go
package mymodule
func LoadCerts(useB bool) error {
newCertPool := x509.NewCertPool()
// This is just to show that the selection is dynamic, and since
// there are many different potential files to load, we can't
// embed them all
bundleName := "cert_A.pem"
if useB {
bundleName = "cert_B.pem"
}
pem, err := ioutil.ReadFile(fmt.Sprintf("./certs/%s", bundleName))
if err != nil {
return err
}
if ok := newCertPool.AppendCertsFromPEM(pem); !ok {
return err
}
...
}
Referencing this file with a relative path (./certs/cert1.pem) doesn't work, since Go uses the executable's working directory for relative paths, and this imported module is somewhere entirely different.
How can I load this .pem file that is bundled with the portable module, regardless of where this module is being imported to?
Embed the files in the executable as a file system:
//go:embed certs
var f embed.FS
Read the files from the file system:
pem, err := f.ReadFile(fmt.Sprintf("certs/%s", bundleName))

How to read env files by runnnig Go application?

I have an application which is developed in Go. I have a config.env file and get some critical variables from it by using the godotenv library. Here is the code:
func InitializeEnvVars() error {
err := godotenv.Load("./config.env")
return err
}
When I build my project with go build . on MacOS and I want to run the application, the app gives an error about reading the .env file:
2021/03/07 17:42:21 [ERROR]: Error loading .env file
But when I run my app with go run main.go command, everything works well.
How can I solve this problem?
As per the comments godotenv.Load("./config.env") will attempt to load the .env file from the working directory. The method used to set the working directory depends upon how you are starting the application (i.e. command line/gui).
If you would prefer that the .env be loaded from the folder holding the executable then try the following (note that there are some caveats).
ex, err := os.Executable()
if err != nil {
panic(fmt.Sprintf("Failed to get executable path: %s", err))
}
envPath := filepath.Join(filepath.Dir(ex), ".env")
err = godotenv.Load(envPath)
You can find the solution below step by step:
Create a folder like cmd
Move executable file to the folder
Create env file with written named in the code into this folder
Open terminal (zsh - MacOS) and run this command: open <executableFileName>
Output file should be in separated folder.

How to load local assets within a GCP cloud function?

I'm building a tiny GCP cloud function in Golang that returns a generated PNG file when calling it via HTTP. I deployed my code via ZIP-Upload in the Google Cloud Console.
Currently it gets called properly and the code gets compiled etc. But in my code I have to load several local files - a font and a .png image.
I bundled those in the ZIP I uploaded and the files are visible in the Source-View in GCP. All files (images, fonts and go-files) are within the same directory.
When calling the cloud function the log states the following:
2019/01/21 14:59:31 open /english.png: no such file or directory
I tried to change the way i build the path to the file in go. I already used /german.png statically, used several attempts to build the path dynamically.
I'm not 100 percent sure if this is the way to go, but it is my first experiment with "serverless" and i am willing to get it done the "right" way.
import "github.com/fogleman/gg"
func main() {
ex, err := os.Executable()
if err != nil {
panic(err)
}
executableDir := filepath.Dir(ex)
img, err :=gg.LoadPNG(path.Join(executableDir, "./english.png"))
if err != nil {
log.Fatal(err)
}
}
Currently the file can not be found in any attempt i made. Maybe the path the images get "deployed" into are different from the ones i tried - i have not found any note on that in the documentation.
I'd obviously expect it to be loaded properly.
For the Go 1.13 according to the documentation, as of today (Jul 2020), source code is located in the ./serverless_function_source_code directory.
A good reference to follow is the buildpack.
I created http functions with the following structure:
api
|--test.txt
|--api.go
And wrote simple function to reply with file content:
package api
import (
"io/ioutil"
"net/http"
)
// FileTest func
func FileTest(w http.ResponseWriter, r *http.Request) {
content, err := ioutil.ReadFile("./test.txt")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(content)
}
It returns the file content without any problems. https://us-central1-clickshield24m.cloudfunctions.net/api
So in your case I would try change the path to gg.LoadPNG("./english.png")
./serverless_function_source_code didn't work for me using go113 runtime with vendoring. I wanted to locate a file in the vendor directory.
My file structure is:
myfn
|- main.go
|- go.mod
|- .gcloudignore
My deployment steps are:
cd myfn
go mod vendor
gcloud functions deploy MyFunction --runtime go113 --set-env-vars "PATH_FILES=./src/myfn/vendor/static"
I found this out by deploying a function that listed all files to a certain depth starting with "." and didn't see a serverless_function_source_code directory. But there was src/myfn.

No such file or directory error from os.Open

I am struggling to figure out an issue with os.Open. I keep getting a 'no such file or directory' error when using os.Open on a folder named templates. So I have my folder MVCApp with bin pkg src and templates in it. Then I have main in the src folder. So I have this code:
basePath := "templates"
templateFolder, err := os.Open(basePath)
if err != nil {
log.Fatal(err)
}
defer templateFolder.Close()
I think it has something to do with the basePath that I am using with the open, but I cannot figure out how I need to preface "templates" in order for it to find this directory. I am sure this is an easy fix, but it has me perplexed. Any help would be greatly appreciated.
Per our discussion in the comments, it turned out that the issue was caused by the application running in an incorrect working directory.
The fix was to modify the path, as such:
basePath := "../../templates"
You can also use os.Chdir to change the working directory permanently (for the duration of the process), and avoid using the ../... More info here: https://golang.org/pkg/os/#File.Chdir

Resources