encore icon indicating copy to clipboard operation
encore copied to clipboard

Proposal: Provide a way to execute commands inside services with access to secrets and the DB URI

Open Minivera opened this issue 2 years ago • 1 comments

I have a few scripts written in go for things like code generation for ORMs or other tools that need access to the database or secrets. To give an example, if I want to access the database connection URL in a script, I have to do something like this:

package main

import (
	...
)

func main() {
	system := flag.String(
		"system",
		"",
		"Pass the name of the system to use",
	)
	flag.Parse()

	cmd := exec.Command("encore", "db", "conn-uri", *system)
	var out bytes.Buffer
	cmd.Stdout = &out
	err := cmd.Run()
	if err != nil {
		log.Fatalf(
			"failed to find the DB uri from the encore CLI %s",
			err,
		)
	}

	connectionString := strings.Replace(out.String(), "\n", "", 1)
        // Do something with the connection string
}

I can then create a generate.go file with something like //go:generate go run -mod=mod ./some_tool/main.go --system users to use go generate and get the connection URI. I haven't found a way to load the secrets at the moment, so I have to keep a copy in a .env file or use environment variables, but that's less of an issue.

Proposal

I don't have the full context of how services run locally or on the cloud yet, but I would very much like a way to trigger these scripts on either environments, with environment variables or parameters added for things like the secrets and the connection URL. That would be really useful to trigger migrations, scripts that need to run on live environments (like updating billing data), or triggering things without exposing an endpoint (Deleting user data for example).

Maybe we could have a special directory called commands in each system, which contain sub directories each exposing a main package and a main function. Using the CLI or the web app, we could trigger commands by name. For example:

// service/commands/migration/main.go
package main

import (
	...
)

//encore:command migrate 
func main() {
        // The DB URL is injected somehow, along with secrets
}

Then, using the CLI: encore run some_service migrate --param1 foo

Minivera avatar Jul 17 '22 20:07 Minivera

This is a great idea. We should definitely support something like this. Thanks very much for the detailed explanation and rationale!

eandre avatar Jul 23 '22 15:07 eandre