github.com/maheshbr/terraform@v0.3.1-0.20141020033300-deec7194a3ea/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 96 err = nil 97 if data.Id() == "" { 98 // We're creating, it is a new resource. 99 err = r.Create(data, meta) 100 } else { 101 if r.Update == nil { 102 return s, fmt.Errorf("doesn't support update") 103 } 104 105 err = r.Update(data, meta) 106 } 107 108 return data.State(), err 109 } 110 111 // Diff returns a diff of this resource and is API compatible with the 112 // ResourceProvider interface. 113 func (r *Resource) Diff( 114 s *terraform.InstanceState, 115 c *terraform.ResourceConfig) (*terraform.InstanceDiff, error) { 116 return schemaMap(r.Schema).Diff(s, c) 117 } 118 119 // Validate validates the resource configuration against the schema. 120 func (r *Resource) Validate(c *terraform.ResourceConfig) ([]string, []error) { 121 return schemaMap(r.Schema).Validate(c) 122 } 123 124 // Refresh refreshes the state of the resource. 125 func (r *Resource) Refresh( 126 s *terraform.InstanceState, 127 meta interface{}) (*terraform.InstanceState, error) { 128 data, err := schemaMap(r.Schema).Data(s, nil) 129 if err != nil { 130 return s, err 131 } 132 133 err = r.Read(data, meta) 134 state := data.State() 135 if state != nil && state.ID == "" { 136 state = nil 137 } 138 139 return state, err 140 } 141 142 // InternalValidate should be called to validate the structure 143 // of the resource. 144 // 145 // This should be called in a unit test for any resource to verify 146 // before release that a resource is properly configured for use with 147 // this library. 148 // 149 // Provider.InternalValidate() will automatically call this for all of 150 // the resources it manages, so you don't need to call this manually if it 151 // is part of a Provider. 152 func (r *Resource) InternalValidate() error { 153 if r == nil { 154 return errors.New("resource is nil") 155 } 156 157 return schemaMap(r.Schema).InternalValidate() 158 }