terraform: multierrors
This commit is contained in:
parent
45a8deb388
commit
45c168bb5b
|
@ -0,0 +1,50 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MultiError is an error type to track multiple errors. This is used to
|
||||||
|
// accumulate errors in cases such as configuration parsing, and returning
|
||||||
|
// them as a single error.
|
||||||
|
type MultiError struct {
|
||||||
|
Errors []error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *MultiError) Error() string {
|
||||||
|
points := make([]string, len(e.Errors))
|
||||||
|
for i, err := range e.Errors {
|
||||||
|
points[i] = fmt.Sprintf("* %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"%d error(s) occurred:\n\n%s",
|
||||||
|
len(e.Errors), strings.Join(points, "\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiErrorAppend is a helper function that will append more errors
|
||||||
|
// onto a MultiError in order to create a larger multi-error. If the
|
||||||
|
// original error is not a MultiError, it will be turned into one.
|
||||||
|
func MultiErrorAppend(err error, errs ...error) *MultiError {
|
||||||
|
if err == nil {
|
||||||
|
err = new(MultiError)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch err := err.(type) {
|
||||||
|
case *MultiError:
|
||||||
|
if err == nil {
|
||||||
|
err = new(MultiError)
|
||||||
|
}
|
||||||
|
|
||||||
|
err.Errors = append(err.Errors, errs...)
|
||||||
|
return err
|
||||||
|
default:
|
||||||
|
newErrs := make([]error, len(errs)+1)
|
||||||
|
newErrs[0] = err
|
||||||
|
copy(newErrs[1:], errs)
|
||||||
|
return &MultiError{
|
||||||
|
Errors: newErrs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package terraform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMultiError_Impl(t *testing.T) {
|
||||||
|
var raw interface{}
|
||||||
|
raw = &MultiError{}
|
||||||
|
if _, ok := raw.(error); !ok {
|
||||||
|
t.Fatal("MultiError must implement error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiErrorError(t *testing.T) {
|
||||||
|
expected := `2 error(s) occurred:
|
||||||
|
|
||||||
|
* foo
|
||||||
|
* bar`
|
||||||
|
|
||||||
|
errors := []error{
|
||||||
|
errors.New("foo"),
|
||||||
|
errors.New("bar"),
|
||||||
|
}
|
||||||
|
|
||||||
|
multi := &MultiError{errors}
|
||||||
|
if multi.Error() != expected {
|
||||||
|
t.Fatalf("bad: %s", multi.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiErrorAppend_MultiError(t *testing.T) {
|
||||||
|
original := &MultiError{
|
||||||
|
Errors: []error{errors.New("foo")},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := MultiErrorAppend(original, errors.New("bar"))
|
||||||
|
if len(result.Errors) != 2 {
|
||||||
|
t.Fatalf("wrong len: %d", len(result.Errors))
|
||||||
|
}
|
||||||
|
|
||||||
|
original = &MultiError{}
|
||||||
|
result = MultiErrorAppend(original, errors.New("bar"))
|
||||||
|
if len(result.Errors) != 1 {
|
||||||
|
t.Fatalf("wrong len: %d", len(result.Errors))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiErrorAppend_NonMultiError(t *testing.T) {
|
||||||
|
original := errors.New("foo")
|
||||||
|
result := MultiErrorAppend(original, errors.New("bar"))
|
||||||
|
if len(result.Errors) != 2 {
|
||||||
|
t.Fatalf("wrong len: %d", len(result.Errors))
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,6 +31,8 @@ type Config struct {
|
||||||
// time, as well as richer checks such as verifying that the resource providers
|
// time, as well as richer checks such as verifying that the resource providers
|
||||||
// can be properly initialized, can be configured, etc.
|
// can be properly initialized, can be configured, etc.
|
||||||
func New(c *Config) (*Terraform, error) {
|
func New(c *Config) (*Terraform, error) {
|
||||||
|
var errs []error
|
||||||
|
|
||||||
// Validate that all required variables have values
|
// Validate that all required variables have values
|
||||||
required := make(map[string]struct{})
|
required := make(map[string]struct{})
|
||||||
for k, v := range c.Config.Variables {
|
for k, v := range c.Config.Variables {
|
||||||
|
@ -42,14 +44,10 @@ func New(c *Config) (*Terraform, error) {
|
||||||
delete(required, k)
|
delete(required, k)
|
||||||
}
|
}
|
||||||
if len(required) > 0 {
|
if len(required) > 0 {
|
||||||
errs := make([]error, 0, len(required))
|
|
||||||
for k, _ := range required {
|
for k, _ := range required {
|
||||||
errs = append(errs, fmt.Errorf(
|
errs = append(errs, fmt.Errorf(
|
||||||
"Required variable not set: %s", k))
|
"Required variable not set: %s", k))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mitchellh): Return multi-error
|
|
||||||
return nil, errs[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through each resource and match it up to a provider
|
// Go through each resource and match it up to a provider
|
||||||
|
@ -90,14 +88,19 @@ func New(c *Config) (*Terraform, error) {
|
||||||
|
|
||||||
if provider == nil {
|
if provider == nil {
|
||||||
// We never found a matching provider.
|
// We never found a matching provider.
|
||||||
return nil, fmt.Errorf(
|
errs = append(errs, fmt.Errorf(
|
||||||
"Provider for resource %s not found.",
|
"Provider for resource %s not found.",
|
||||||
r.Id())
|
r.Id()))
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping[r] = provider
|
mapping[r] = provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we accumulated any errors, then return them all
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return nil, &MultiError{Errors: errs}
|
||||||
|
}
|
||||||
|
|
||||||
return &Terraform{
|
return &Terraform{
|
||||||
config: c.Config,
|
config: c.Config,
|
||||||
mapping: mapping,
|
mapping: mapping,
|
||||||
|
|
Loading…
Reference in New Issue