github.com/chalford/terraform@v0.3.7-0.20150113080010-a78c69a8c81f/helper/schema/resource.go (about) 1 package schema 2 3 import ( 4 "errors" 5 "fmt" 6 7 "github.com/hashicorp/terraform/terraform" 8 ) 9 10 // Resource represents a thing in Terraform that has a set of configurable 11 // attributes and a lifecycle (create, read, update, delete). 12 // 13 // The Resource schema is an abstraction that allows provider writers to 14 // worry only about CRUD operations while off-loading validation, diff 15 // generation, etc. to this higher level library. 16 type Resource struct { 17 // Schema is the schema for the configuration of this resource. 18 // 19 // The keys of this map are the configuration keys, and the values 20 // describe the schema of the configuration value. 21 // 22 // The schema is used to represent both configurable data as well 23 // as data that might be computed in the process of creating this 24 // resource. 25 Schema map[string]*Schema 26 27 // The functions below are the CRUD operations for this resource. 28 // 29 // The only optional operation is Update. If Update is not implemented, 30 // then updates will not be supported for this resource. 31 // 32 // The ResourceData parameter in the functions below are used to 33 // query configuration and changes for the resource as well as to set 34 // the ID, computed data, etc. 35 // 36 // The interface{} parameter is the result of the ConfigureFunc in 37 // the provider for this resource. If the provider does not define 38 // a ConfigureFunc, this will be nil. This parameter should be used 39 // to store API clients, configuration structures, etc. 40 // 41 // If any errors occur during each of the operation, an error should be 42 // returned. If a resource was partially updated, be careful to enable 43 // partial state mode for ResourceData and use it accordingly. 44 Create CreateFunc 45 Read ReadFunc 46 Update UpdateFunc 47 Delete DeleteFunc 48 } 49 50 // See Resource documentation. 51 type CreateFunc func(*ResourceData, interface{}) error 52 53 // See Resource documentation. 54 type ReadFunc func(*ResourceData, interface{}) error 55 56 // See Resource documentation. 57 type UpdateFunc func(*ResourceData, interface{}) error 58 59 // See Resource documentation. 60 type DeleteFunc func(*ResourceData, interface{}) error 61 62 // Apply creates, updates, and/or deletes a resource. 63 func (r *Resource) Apply( 64 s *terraform.InstanceState, 65 d *terraform.InstanceDiff, 66 meta interface{}) (*terraform.InstanceState, error) { 67 data, err := schemaMap(r.Schema).Data(s, d) 68 if err != nil { 69 return s, err 70 } 71 72 if s == nil { 73 // The Terraform API dictates that this should never happen, but 74 // it doesn't hurt to be safe in this case. 75 s = new(terraform.InstanceState) 76 } 77 78 if d.Destroy || d.RequiresNew() { 79 if s.ID != "" { 80 // Destroy the resource since it is created 81 if err := r.Delete(data, meta); err != nil { 82 return data.State(), err 83 } 84 85 // Make sure the ID is gone. 86 data.SetId("") 87 } 88 89 // If we're only destroying, and not creating, then return 90 // now since we're done! 91 if !d.RequiresNew() { 92 return nil, nil 93 } 94 95 // Reset the data to be stateless since we just destroyed 96 data, err = schemaMap(r.Schema).Data(nil, d) 97 if err != nil { 98 return nil, err 99 } 100 } 101 102 err = nil 103 if data.Id() == "" { 104 // We're creating, it is a new resource. 105 err = r.Create(data, meta) 106 } else { 107 if r.Update == nil { 108 return s, fmt.Errorf("doesn't support update") 109 } 110 111 err = r.Update(data, meta) 112 } 113 114 return data.State(), err 115 } 116 117 // Diff returns a diff of this resource and is API compatible with the 118 // ResourceProvider interface. 119 func (r *Resource) Diff( 120 s *terraform.InstanceState, 121 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { 122 return schemaMap(r.Schema).Diff(s, c) 123 } 124 125 // Validate validates the resource configuration against the schema. 126 func (r *Resource) Validate(c *terraform.ResourceConfig) ([]string, []error) { 127 return schemaMap(r.Schema).Validate(c) 128 } 129 130 // Refresh refreshes the state of the resource. 131 func (r *Resource) Refresh( 132 s *terraform.InstanceState, 133 meta interface{}) (*terraform.InstanceState, error) { 134 data, err := schemaMap(r.Schema).Data(s, nil) 135 if err != nil { 136 return s, err 137 } 138 139 err = r.Read(data, meta) 140 state := data.State() 141 if state != nil && state.ID == "" { 142 state = nil 143 } 144 145 return state, err 146 } 147 148 // InternalValidate should be called to validate the structure 149 // of the resource. 150 // 151 // This should be called in a unit test for any resource to verify 152 // before release that a resource is properly configured for use with 153 // this library. 154 // 155 // Provider.InternalValidate() will automatically call this for all of 156 // the resources it manages, so you don't need to call this manually if it 157 // is part of a Provider. 158 func (r *Resource) InternalValidate() error { 159 if r == nil { 160 return errors.New("resource is nil") 161 } 162 163 return schemaMap(r.Schema).InternalValidate() 164 }