aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/helper/resource/map.go
blob: a465136f778cf860676bb8f9e5e057185428b433 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package resource

import (
	"fmt"
	"sort"

	"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
}

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)
}

// Apply performs a create or update depending on the diff, and calls
// the proper function on the matching Resource.
func (m *Map) Apply(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	r, ok := m.Mapping[info.Type]
	if !ok {
		return nil, fmt.Errorf("Unknown resource type: %s", info.Type)
	}

	if d.Destroy || d.RequiresNew() {
		if s.ID != "" {
			// Destroy the resource if it is created
			err := r.Destroy(s, meta)
			if err != nil {
				return s, err
			}

			s.ID = ""
		}

		// 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
		}
	}

	var result *terraform.InstanceState
	var err error
	if s.ID == "" {
		result, err = r.Create(s, d, meta)
	} else {
		if r.Update == nil {
			return s, fmt.Errorf(
				"Resource type '%s' doesn't support update",
				info.Type)
		}

		result, err = r.Update(s, d, meta)
	}
	if result != nil {
		if result.Attributes == nil {
			result.Attributes = make(map[string]string)
		}

		result.Attributes["id"] = result.ID
	}

	return result, err
}

// Diff performs a diff on the proper resource type.
func (m *Map) Diff(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	c *terraform.ResourceConfig,
	meta interface{}) (*terraform.InstanceDiff, error) {
	r, ok := m.Mapping[info.Type]
	if !ok {
		return nil, fmt.Errorf("Unknown resource type: %s", info.Type)
	}

	return r.Diff(s, c, meta)
}

// 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(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	meta interface{}) (*terraform.InstanceState, error) {
	// If the resource isn't created, don't refresh.
	if s.ID == "" {
		return s, nil
	}

	r, ok := m.Mapping[info.Type]
	if !ok {
		return nil, fmt.Errorf("Unknown resource type: %s", info.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 {
	ks := make([]string, 0, len(m.Mapping))
	for k, _ := range m.Mapping {
		ks = append(ks, k)
	}
	sort.Strings(ks)

	rs := make([]terraform.ResourceType, 0, len(m.Mapping))
	for _, k := range ks {
		rs = append(rs, terraform.ResourceType{
			Name: k,
		})
	}

	return rs
}