github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/terraform/resource_provider.go (about) 1 package terraform 2 3 // ResourceProvider is an interface that must be implemented by any 4 // resource provider: the thing that creates and manages the resources in 5 // a Terraform configuration. 6 // 7 // Important implementation note: All returned pointers, such as 8 // *ResourceConfig, *InstanceState, *InstanceDiff, etc. must not point to 9 // shared data. Terraform is highly parallel and assumes that this data is safe 10 // to read/write in parallel so it must be unique references. Note that it is 11 // safe to return arguments as results, however. 12 type ResourceProvider interface { 13 /********************************************************************* 14 * Functions related to the provider 15 *********************************************************************/ 16 17 // Input is called to ask the provider to ask the user for input 18 // for completing the configuration if necesarry. 19 // 20 // This may or may not be called, so resource provider writers shouldn't 21 // rely on this being available to set some default values for validate 22 // later. Example of a situation where this wouldn't be called is if 23 // the user is not using a TTY. 24 Input(UIInput, *ResourceConfig) (*ResourceConfig, error) 25 26 // Validate is called once at the beginning with the raw configuration 27 // (no interpolation done) and can return a list of warnings and/or 28 // errors. 29 // 30 // This is called once with the provider configuration only. It may not 31 // be called at all if no provider configuration is given. 32 // 33 // This should not assume that any values of the configurations are valid. 34 // The primary use case of this call is to check that required keys are 35 // set. 36 Validate(*ResourceConfig) ([]string, []error) 37 38 // Configure configures the provider itself with the configuration 39 // given. This is useful for setting things like access keys. 40 // 41 // This won't be called at all if no provider configuration is given. 42 // 43 // Configure returns an error if it occurred. 44 Configure(*ResourceConfig) error 45 46 // Resources returns all the available resource types that this provider 47 // knows how to manage. 48 Resources() []ResourceType 49 50 // Stop is called when the provider should halt any in-flight actions. 51 // 52 // This can be used to make a nicer Ctrl-C experience for Terraform. 53 // Even if this isn't implemented to do anything (just returns nil), 54 // Terraform will still cleanly stop after the currently executing 55 // graph node is complete. However, this API can be used to make more 56 // efficient halts. 57 // 58 // Stop doesn't have to and shouldn't block waiting for in-flight actions 59 // to complete. It should take any action it wants and return immediately 60 // acknowledging it has received the stop request. Terraform core will 61 // automatically not make any further API calls to the provider soon 62 // after Stop is called (technically exactly once the currently executing 63 // graph nodes are complete). 64 // 65 // The error returned, if non-nil, is assumed to mean that signaling the 66 // stop somehow failed and that the user should expect potentially waiting 67 // a longer period of time. 68 Stop() error 69 70 /********************************************************************* 71 * Functions related to individual resources 72 *********************************************************************/ 73 74 // ValidateResource is called once at the beginning with the raw 75 // configuration (no interpolation done) and can return a list of warnings 76 // and/or errors. 77 // 78 // This is called once per resource. 79 // 80 // This should not assume any of the values in the resource configuration 81 // are valid since it is possible they have to be interpolated still. 82 // The primary use case of this call is to check that the required keys 83 // are set and that the general structure is correct. 84 ValidateResource(string, *ResourceConfig) ([]string, []error) 85 86 // Apply applies a diff to a specific resource and returns the new 87 // resource state along with an error. 88 // 89 // If the resource state given has an empty ID, then a new resource 90 // is expected to be created. 91 Apply( 92 *InstanceInfo, 93 *InstanceState, 94 *InstanceDiff) (*InstanceState, error) 95 96 // Diff diffs a resource versus a desired state and returns 97 // a diff. 98 Diff( 99 *InstanceInfo, 100 *InstanceState, 101 *ResourceConfig) (*InstanceDiff, error) 102 103 // Refresh refreshes a resource and updates all of its attributes 104 // with the latest information. 105 Refresh(*InstanceInfo, *InstanceState) (*InstanceState, error) 106 107 /********************************************************************* 108 * Functions related to importing 109 *********************************************************************/ 110 111 // ImportState requests that the given resource be imported. 112 // 113 // The returned InstanceState only requires ID be set. Importing 114 // will always call Refresh after the state to complete it. 115 // 116 // IMPORTANT: InstanceState doesn't have the resource type attached 117 // to it. A type must be specified on the state via the Ephemeral 118 // field on the state. 119 // 120 // This function can return multiple states. Normally, an import 121 // will map 1:1 to a physical resource. However, some resources map 122 // to multiple. For example, an AWS security group may contain many rules. 123 // Each rule is represented by a separate resource in Terraform, 124 // therefore multiple states are returned. 125 ImportState(*InstanceInfo, string) ([]*InstanceState, error) 126 127 /********************************************************************* 128 * Functions related to data resources 129 *********************************************************************/ 130 131 // ValidateDataSource is called once at the beginning with the raw 132 // configuration (no interpolation done) and can return a list of warnings 133 // and/or errors. 134 // 135 // This is called once per data source instance. 136 // 137 // This should not assume any of the values in the resource configuration 138 // are valid since it is possible they have to be interpolated still. 139 // The primary use case of this call is to check that the required keys 140 // are set and that the general structure is correct. 141 ValidateDataSource(string, *ResourceConfig) ([]string, []error) 142 143 // DataSources returns all of the available data sources that this 144 // provider implements. 145 DataSources() []DataSource 146 147 // ReadDataDiff produces a diff that represents the state that will 148 // be produced when the given data source is read using a later call 149 // to ReadDataApply. 150 ReadDataDiff(*InstanceInfo, *ResourceConfig) (*InstanceDiff, error) 151 152 // ReadDataApply initializes a data instance using the configuration 153 // in a diff produced by ReadDataDiff. 154 ReadDataApply(*InstanceInfo, *InstanceDiff) (*InstanceState, error) 155 } 156 157 // ResourceProviderCloser is an interface that providers that can close 158 // connections that aren't needed anymore must implement. 159 type ResourceProviderCloser interface { 160 Close() error 161 } 162 163 // ResourceType is a type of resource that a resource provider can manage. 164 type ResourceType struct { 165 Name string // Name of the resource, example "instance" (no provider prefix) 166 Importable bool // Whether this resource supports importing 167 } 168 169 // DataSource is a data source that a resource provider implements. 170 type DataSource struct { 171 Name string 172 } 173 174 // ResourceProviderFactory is a function type that creates a new instance 175 // of a resource provider. 176 type ResourceProviderFactory func() (ResourceProvider, error) 177 178 // ResourceProviderFactoryFixed is a helper that creates a 179 // ResourceProviderFactory that just returns some fixed provider. 180 func ResourceProviderFactoryFixed(p ResourceProvider) ResourceProviderFactory { 181 return func() (ResourceProvider, error) { 182 return p, nil 183 } 184 } 185 186 func ProviderHasResource(p ResourceProvider, n string) bool { 187 for _, rt := range p.Resources() { 188 if rt.Name == n { 189 return true 190 } 191 } 192 193 return false 194 } 195 196 func ProviderHasDataSource(p ResourceProvider, n string) bool { 197 for _, rt := range p.DataSources() { 198 if rt.Name == n { 199 return true 200 } 201 } 202 203 return false 204 }