Adding a new Teller provider is very easy, but you still need to know where to start. We summarize the steps very shortly to make your life easier
- Copy the file example.go from examples/providers/example.go and make sure to implement all the required behaviors. The example.go file is a skeleton for adding a new provider, it contains stubs for an interface which declares the required functionality that any provider must have.
- Go to pkg/providers.go and add your provider name to the
ProviderHumanToMachine
HashMap (this function maps between the provider display name and internal name).
func (p *BuiltinProviders) ProviderHumanToMachine() map[string]string {
return map[string]string{
"Heroku": "heroku",
...
"Example": "example",
}
}
- Add your provider to the switch case block in pkg/providers.go (this function returns the provider handler by provider key).
func (p *BuiltinProviders) GetProvider(name string) (core.Provider, error) {
logger := logging.GetRoot().WithField("provider_name", name)
switch name {
case "heroku":
return providers.NewHeroku(logger)
case "example":
return providers.NewExample(logger) // <--- your new provider
default:
return nil, fmt.Errorf("provider '%s' does not exist", name)
}
}
- Add a provider template configuration in path: pkg/wizard_template.go. This will be used to auto-generate a configuration.
{{- if index .ProviderKeys "example" }}
# Add here some authentication requirements, like a token that should be in the user's environment.
example:
env_sync:
path: redis/config
env:
ETC_DSN:
path: redis/config/foobar
{{end}}
You're done! 🚀
Run the command go run main.go new
and run through the flow in the wizard.
Ensure that you see your provider in the Select your secret providers
question.
After the teller.yml
file is created, run the command go run main.go yaml
, you should see the message :
FATA[0000] could not load all variables from the given existing providers error="provider \"Example\" does not implement write yet"
This means that you configured the provider successfully and are ready to implement the functions in it.
- Since each provider uses some kind of system behind it (e.g. Hashicorp Vault provider connects to the Hashicorp Vault itself) try to wrap the access to the backend or system with your own abstract client-provider with an interface. It will help you to test your provider easier.
- Use provider logger for better visibility when an error occurs.
- Add the new provider to provider mapping in README.md.
We vendor
our dependencies and push them to the repo. This creates an immutable, independent build, that's also free from risks of fetching unknown code in CI/release time.
After adding your packages to import in your provider file, run the commands:
$ go mod tidy
$ go mod vendor
Create an example_test.go
file in pkg/providers folder.
In case you warp the client-provider with an interface you can run a mock generator with the mock framework and add this command to the Makefile
mockgen -source pkg/providers/example.go -destination pkg/providers/mock_providers/example_mock.go
Test guidelines:
- Create a
TestExample
function and call AssertProvider for testing main functionality. - Create a
TestExampleFailures
for testing error handling. - You can also add more tests for testing private functions.
- Run
make lint
to validate linting. - Run
make test
for make sure that all the test pass.