2014-06-24 04:32:49 +02:00
|
|
|
package resource
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2014-07-03 02:36:07 +02:00
|
|
|
"sort"
|
2014-06-24 04:32:49 +02:00
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Map is a map of resources that are supported, and provides helpers for
|
|
|
|
// more easily implementing a ResourceProvider.
|
|
|
|
type Map struct {
|
|
|
|
Mapping map[string]Resource
|
|
|
|
}
|
|
|
|
|
2014-07-08 19:17:36 +02:00
|
|
|
func (m *Map) Validate(
|
|
|
|
t string, c *terraform.ResourceConfig) ([]string, []error) {
|
|
|
|
r, ok := m.Mapping[t]
|
|
|
|
if !ok {
|
|
|
|
return nil, []error{fmt.Errorf("Unknown resource type: %s", t)}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is no validator set, then it is valid
|
|
|
|
if r.ConfigValidator == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.ConfigValidator.Validate(c)
|
|
|
|
}
|
|
|
|
|
2014-06-24 04:32:49 +02:00
|
|
|
// Apply performs a create or update depending on the diff, and calls
|
|
|
|
// the proper function on the matching Resource.
|
|
|
|
func (m *Map) Apply(
|
|
|
|
s *terraform.ResourceState,
|
|
|
|
d *terraform.ResourceDiff,
|
|
|
|
meta interface{}) (*terraform.ResourceState, error) {
|
|
|
|
r, ok := m.Mapping[s.Type]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Unknown resource type: %s", s.Type)
|
|
|
|
}
|
|
|
|
|
2014-06-26 03:41:40 +02:00
|
|
|
if d.Destroy || d.RequiresNew() {
|
2014-06-24 21:59:50 +02:00
|
|
|
if s.ID != "" {
|
|
|
|
// Destroy the resource if it is created
|
|
|
|
err := r.Destroy(s, meta)
|
|
|
|
if err != nil {
|
|
|
|
return s, err
|
|
|
|
}
|
|
|
|
|
|
|
|
s.ID = ""
|
2014-06-24 21:55:59 +02:00
|
|
|
}
|
|
|
|
|
2014-06-24 21:59:50 +02:00
|
|
|
// If we're only destroying, and not creating, then return now.
|
|
|
|
// Otherwise, we continue so that we can create a new resource.
|
|
|
|
if !d.RequiresNew() {
|
|
|
|
return nil, nil
|
2014-06-24 21:55:59 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-08 00:00:13 +02:00
|
|
|
var result *terraform.ResourceState
|
|
|
|
var err error
|
2014-06-24 04:32:49 +02:00
|
|
|
if s.ID == "" {
|
2014-07-08 00:00:13 +02:00
|
|
|
result, err = r.Create(s, d, meta)
|
2014-06-24 04:32:49 +02:00
|
|
|
} else {
|
2014-07-11 20:20:18 +02:00
|
|
|
if r.Update == nil {
|
|
|
|
return s, fmt.Errorf(
|
|
|
|
"Resource type '%s' doesn't support update",
|
|
|
|
s.Type)
|
|
|
|
}
|
|
|
|
|
2014-07-08 00:00:13 +02:00
|
|
|
result, err = r.Update(s, d, meta)
|
2014-06-24 04:32:49 +02:00
|
|
|
}
|
2014-07-08 00:00:13 +02:00
|
|
|
if result != nil {
|
2014-07-08 05:45:09 +02:00
|
|
|
if result.Attributes == nil {
|
|
|
|
result.Attributes = make(map[string]string)
|
|
|
|
}
|
|
|
|
|
2014-07-08 00:06:17 +02:00
|
|
|
result.Attributes["id"] = result.ID
|
2014-07-08 00:00:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result, err
|
2014-06-24 04:32:49 +02:00
|
|
|
}
|
|
|
|
|
2014-06-24 19:27:39 +02:00
|
|
|
// Diff peforms a diff on the proper resource type.
|
|
|
|
func (m *Map) Diff(
|
|
|
|
s *terraform.ResourceState,
|
|
|
|
c *terraform.ResourceConfig,
|
|
|
|
meta interface{}) (*terraform.ResourceDiff, error) {
|
|
|
|
r, ok := m.Mapping[s.Type]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Unknown resource type: %s", s.Type)
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Diff(s, c, meta)
|
|
|
|
}
|
|
|
|
|
2014-06-24 04:32:49 +02:00
|
|
|
// Refresh performs a Refresh on the proper resource type.
|
|
|
|
//
|
|
|
|
// Refresh on the Resource won't be called if the state represents a
|
|
|
|
// non-created resource (ID is blank).
|
|
|
|
//
|
|
|
|
// An error is returned if the resource isn't registered.
|
|
|
|
func (m *Map) Refresh(
|
|
|
|
s *terraform.ResourceState,
|
|
|
|
meta interface{}) (*terraform.ResourceState, error) {
|
|
|
|
// If the resource isn't created, don't refresh.
|
|
|
|
if s.ID == "" {
|
|
|
|
return s, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
r, ok := m.Mapping[s.Type]
|
|
|
|
if !ok {
|
|
|
|
return nil, fmt.Errorf("Unknown resource type: %s", s.Type)
|
|
|
|
}
|
|
|
|
|
|
|
|
return r.Refresh(s, meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resources returns all the resources that are supported by this
|
|
|
|
// resource map and can be used to satisfy the Resources method of
|
|
|
|
// a ResourceProvider.
|
|
|
|
func (m *Map) Resources() []terraform.ResourceType {
|
2014-07-03 02:36:07 +02:00
|
|
|
ks := make([]string, 0, len(m.Mapping))
|
2014-06-24 04:32:49 +02:00
|
|
|
for k, _ := range m.Mapping {
|
2014-07-03 02:36:07 +02:00
|
|
|
ks = append(ks, k)
|
|
|
|
}
|
|
|
|
sort.Strings(ks)
|
|
|
|
|
|
|
|
rs := make([]terraform.ResourceType, 0, len(m.Mapping))
|
|
|
|
for _, k := range ks {
|
2014-06-24 04:32:49 +02:00
|
|
|
rs = append(rs, terraform.ResourceType{
|
|
|
|
Name: k,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return rs
|
|
|
|
}
|