github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/helper/resource/map.go (about) 1 package resource 2 3 import ( 4 "fmt" 5 "sort" 6 7 "github.com/hashicorp/terraform/terraform" 8 ) 9 10 // Map is a map of resources that are supported, and provides helpers for 11 // more easily implementing a ResourceProvider. 12 type Map struct { 13 Mapping map[string]Resource 14 } 15 16 func (m *Map) Validate( 17 t string, c *terraform.ResourceConfig) ([]string, []error) { 18 r, ok := m.Mapping[t] 19 if !ok { 20 return nil, []error{fmt.Errorf("Unknown resource type: %s", t)} 21 } 22 23 // If there is no validator set, then it is valid 24 if r.ConfigValidator == nil { 25 return nil, nil 26 } 27 28 return r.ConfigValidator.Validate(c) 29 } 30 31 // Apply performs a create or update depending on the diff, and calls 32 // the proper function on the matching Resource. 33 func (m *Map) Apply( 34 info *terraform.InstanceInfo, 35 s *terraform.InstanceState, 36 d *terraform.InstanceDiff, 37 meta interface{}) (*terraform.InstanceState, error) { 38 r, ok := m.Mapping[info.Type] 39 if !ok { 40 return nil, fmt.Errorf("Unknown resource type: %s", info.Type) 41 } 42 43 if d.Destroy || d.RequiresNew() { 44 if s.ID != "" { 45 // Destroy the resource if it is created 46 err := r.Destroy(s, meta) 47 if err != nil { 48 return s, err 49 } 50 51 s.ID = "" 52 } 53 54 // If we're only destroying, and not creating, then return now. 55 // Otherwise, we continue so that we can create a new resource. 56 if !d.RequiresNew() { 57 return nil, nil 58 } 59 } 60 61 var result *terraform.InstanceState 62 var err error 63 if s.ID == "" { 64 result, err = r.Create(s, d, meta) 65 } else { 66 if r.Update == nil { 67 return s, fmt.Errorf( 68 "Resource type '%s' doesn't support update", 69 info.Type) 70 } 71 72 result, err = r.Update(s, d, meta) 73 } 74 if result != nil { 75 if result.Attributes == nil { 76 result.Attributes = make(map[string]string) 77 } 78 79 result.Attributes["id"] = result.ID 80 } 81 82 return result, err 83 } 84 85 // Diff performs a diff on the proper resource type. 86 func (m *Map) Diff( 87 info *terraform.InstanceInfo, 88 s *terraform.InstanceState, 89 c *terraform.ResourceConfig, 90 meta interface{}) (*terraform.InstanceDiff, error) { 91 r, ok := m.Mapping[info.Type] 92 if !ok { 93 return nil, fmt.Errorf("Unknown resource type: %s", info.Type) 94 } 95 96 return r.Diff(s, c, meta) 97 } 98 99 // Refresh performs a Refresh on the proper resource type. 100 // 101 // Refresh on the Resource won't be called if the state represents a 102 // non-created resource (ID is blank). 103 // 104 // An error is returned if the resource isn't registered. 105 func (m *Map) Refresh( 106 info *terraform.InstanceInfo, 107 s *terraform.InstanceState, 108 meta interface{}) (*terraform.InstanceState, error) { 109 // If the resource isn't created, don't refresh. 110 if s.ID == "" { 111 return s, nil 112 } 113 114 r, ok := m.Mapping[info.Type] 115 if !ok { 116 return nil, fmt.Errorf("Unknown resource type: %s", info.Type) 117 } 118 119 return r.Refresh(s, meta) 120 } 121 122 // Resources returns all the resources that are supported by this 123 // resource map and can be used to satisfy the Resources method of 124 // a ResourceProvider. 125 func (m *Map) Resources() []terraform.ResourceType { 126 ks := make([]string, 0, len(m.Mapping)) 127 for k, _ := range m.Mapping { 128 ks = append(ks, k) 129 } 130 sort.Strings(ks) 131 132 rs := make([]terraform.ResourceType, 0, len(m.Mapping)) 133 for _, k := range ks { 134 rs = append(rs, terraform.ResourceType{ 135 Name: k, 136 }) 137 } 138 139 return rs 140 }