github.com/richardmarshall/terraform@v0.9.5-0.20170429023105-15704cc6ee35/helper/schema/provider_test.go (about) 1 package schema 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 "time" 8 9 "github.com/hashicorp/terraform/config" 10 "github.com/hashicorp/terraform/terraform" 11 ) 12 13 func TestProvider_impl(t *testing.T) { 14 var _ terraform.ResourceProvider = new(Provider) 15 } 16 17 func TestProviderConfigure(t *testing.T) { 18 cases := []struct { 19 P *Provider 20 Config map[string]interface{} 21 Err bool 22 }{ 23 { 24 P: &Provider{}, 25 Config: nil, 26 Err: false, 27 }, 28 29 { 30 P: &Provider{ 31 Schema: map[string]*Schema{ 32 "foo": &Schema{ 33 Type: TypeInt, 34 Optional: true, 35 }, 36 }, 37 38 ConfigureFunc: func(d *ResourceData) (interface{}, error) { 39 if d.Get("foo").(int) == 42 { 40 return nil, nil 41 } 42 43 return nil, fmt.Errorf("nope") 44 }, 45 }, 46 Config: map[string]interface{}{ 47 "foo": 42, 48 }, 49 Err: false, 50 }, 51 52 { 53 P: &Provider{ 54 Schema: map[string]*Schema{ 55 "foo": &Schema{ 56 Type: TypeInt, 57 Optional: true, 58 }, 59 }, 60 61 ConfigureFunc: func(d *ResourceData) (interface{}, error) { 62 if d.Get("foo").(int) == 42 { 63 return nil, nil 64 } 65 66 return nil, fmt.Errorf("nope") 67 }, 68 }, 69 Config: map[string]interface{}{ 70 "foo": 52, 71 }, 72 Err: true, 73 }, 74 } 75 76 for i, tc := range cases { 77 c, err := config.NewRawConfig(tc.Config) 78 if err != nil { 79 t.Fatalf("err: %s", err) 80 } 81 82 err = tc.P.Configure(terraform.NewResourceConfig(c)) 83 if err != nil != tc.Err { 84 t.Fatalf("%d: %s", i, err) 85 } 86 } 87 } 88 89 func TestProviderResources(t *testing.T) { 90 cases := []struct { 91 P *Provider 92 Result []terraform.ResourceType 93 }{ 94 { 95 P: &Provider{}, 96 Result: []terraform.ResourceType{}, 97 }, 98 99 { 100 P: &Provider{ 101 ResourcesMap: map[string]*Resource{ 102 "foo": nil, 103 "bar": nil, 104 }, 105 }, 106 Result: []terraform.ResourceType{ 107 terraform.ResourceType{Name: "bar"}, 108 terraform.ResourceType{Name: "foo"}, 109 }, 110 }, 111 112 { 113 P: &Provider{ 114 ResourcesMap: map[string]*Resource{ 115 "foo": nil, 116 "bar": &Resource{Importer: &ResourceImporter{}}, 117 "baz": nil, 118 }, 119 }, 120 Result: []terraform.ResourceType{ 121 terraform.ResourceType{Name: "bar", Importable: true}, 122 terraform.ResourceType{Name: "baz"}, 123 terraform.ResourceType{Name: "foo"}, 124 }, 125 }, 126 } 127 128 for i, tc := range cases { 129 actual := tc.P.Resources() 130 if !reflect.DeepEqual(actual, tc.Result) { 131 t.Fatalf("%d: %#v", i, actual) 132 } 133 } 134 } 135 136 func TestProviderDataSources(t *testing.T) { 137 cases := []struct { 138 P *Provider 139 Result []terraform.DataSource 140 }{ 141 { 142 P: &Provider{}, 143 Result: []terraform.DataSource{}, 144 }, 145 146 { 147 P: &Provider{ 148 DataSourcesMap: map[string]*Resource{ 149 "foo": nil, 150 "bar": nil, 151 }, 152 }, 153 Result: []terraform.DataSource{ 154 terraform.DataSource{Name: "bar"}, 155 terraform.DataSource{Name: "foo"}, 156 }, 157 }, 158 } 159 160 for i, tc := range cases { 161 actual := tc.P.DataSources() 162 if !reflect.DeepEqual(actual, tc.Result) { 163 t.Fatalf("%d: got %#v; want %#v", i, actual, tc.Result) 164 } 165 } 166 } 167 168 func TestProviderValidate(t *testing.T) { 169 cases := []struct { 170 P *Provider 171 Config map[string]interface{} 172 Err bool 173 }{ 174 { 175 P: &Provider{ 176 Schema: map[string]*Schema{ 177 "foo": &Schema{}, 178 }, 179 }, 180 Config: nil, 181 Err: true, 182 }, 183 } 184 185 for i, tc := range cases { 186 c, err := config.NewRawConfig(tc.Config) 187 if err != nil { 188 t.Fatalf("err: %s", err) 189 } 190 191 _, es := tc.P.Validate(terraform.NewResourceConfig(c)) 192 if len(es) > 0 != tc.Err { 193 t.Fatalf("%d: %#v", i, es) 194 } 195 } 196 } 197 198 func TestProviderValidateResource(t *testing.T) { 199 cases := []struct { 200 P *Provider 201 Type string 202 Config map[string]interface{} 203 Err bool 204 }{ 205 { 206 P: &Provider{}, 207 Type: "foo", 208 Config: nil, 209 Err: true, 210 }, 211 212 { 213 P: &Provider{ 214 ResourcesMap: map[string]*Resource{ 215 "foo": &Resource{}, 216 }, 217 }, 218 Type: "foo", 219 Config: nil, 220 Err: false, 221 }, 222 } 223 224 for i, tc := range cases { 225 c, err := config.NewRawConfig(tc.Config) 226 if err != nil { 227 t.Fatalf("err: %s", err) 228 } 229 230 _, es := tc.P.ValidateResource(tc.Type, terraform.NewResourceConfig(c)) 231 if len(es) > 0 != tc.Err { 232 t.Fatalf("%d: %#v", i, es) 233 } 234 } 235 } 236 237 func TestProviderImportState_default(t *testing.T) { 238 p := &Provider{ 239 ResourcesMap: map[string]*Resource{ 240 "foo": &Resource{ 241 Importer: &ResourceImporter{}, 242 }, 243 }, 244 } 245 246 states, err := p.ImportState(&terraform.InstanceInfo{ 247 Type: "foo", 248 }, "bar") 249 if err != nil { 250 t.Fatalf("err: %s", err) 251 } 252 253 if len(states) != 1 { 254 t.Fatalf("bad: %#v", states) 255 } 256 if states[0].ID != "bar" { 257 t.Fatalf("bad: %#v", states) 258 } 259 } 260 261 func TestProviderImportState_setsId(t *testing.T) { 262 var val string 263 stateFunc := func(d *ResourceData, meta interface{}) ([]*ResourceData, error) { 264 val = d.Id() 265 return []*ResourceData{d}, nil 266 } 267 268 p := &Provider{ 269 ResourcesMap: map[string]*Resource{ 270 "foo": &Resource{ 271 Importer: &ResourceImporter{ 272 State: stateFunc, 273 }, 274 }, 275 }, 276 } 277 278 _, err := p.ImportState(&terraform.InstanceInfo{ 279 Type: "foo", 280 }, "bar") 281 if err != nil { 282 t.Fatalf("err: %s", err) 283 } 284 285 if val != "bar" { 286 t.Fatal("should set id") 287 } 288 } 289 290 func TestProviderImportState_setsType(t *testing.T) { 291 var tVal string 292 stateFunc := func(d *ResourceData, meta interface{}) ([]*ResourceData, error) { 293 d.SetId("foo") 294 tVal = d.State().Ephemeral.Type 295 return []*ResourceData{d}, nil 296 } 297 298 p := &Provider{ 299 ResourcesMap: map[string]*Resource{ 300 "foo": &Resource{ 301 Importer: &ResourceImporter{ 302 State: stateFunc, 303 }, 304 }, 305 }, 306 } 307 308 _, err := p.ImportState(&terraform.InstanceInfo{ 309 Type: "foo", 310 }, "bar") 311 if err != nil { 312 t.Fatalf("err: %s", err) 313 } 314 315 if tVal != "foo" { 316 t.Fatal("should set type") 317 } 318 } 319 320 func TestProviderMeta(t *testing.T) { 321 p := new(Provider) 322 if v := p.Meta(); v != nil { 323 t.Fatalf("bad: %#v", v) 324 } 325 326 expected := 42 327 p.SetMeta(42) 328 if v := p.Meta(); !reflect.DeepEqual(v, expected) { 329 t.Fatalf("bad: %#v", v) 330 } 331 } 332 333 func TestProviderStop(t *testing.T) { 334 var p Provider 335 336 if p.Stopped() { 337 t.Fatal("should not be stopped") 338 } 339 340 // Verify stopch blocks 341 ch := p.StopContext().Done() 342 select { 343 case <-ch: 344 t.Fatal("should not be stopped") 345 case <-time.After(10 * time.Millisecond): 346 } 347 348 // Stop it 349 if err := p.Stop(); err != nil { 350 t.Fatalf("err: %s", err) 351 } 352 353 // Verify 354 if !p.Stopped() { 355 t.Fatal("should be stopped") 356 } 357 358 select { 359 case <-ch: 360 case <-time.After(10 * time.Millisecond): 361 t.Fatal("should be stopped") 362 } 363 } 364 365 func TestProviderStop_stopFirst(t *testing.T) { 366 var p Provider 367 368 // Stop it 369 if err := p.Stop(); err != nil { 370 t.Fatalf("err: %s", err) 371 } 372 373 // Verify 374 if !p.Stopped() { 375 t.Fatal("should be stopped") 376 } 377 378 select { 379 case <-p.StopContext().Done(): 380 case <-time.After(10 * time.Millisecond): 381 t.Fatal("should be stopped") 382 } 383 } 384 385 func TestProviderReset(t *testing.T) { 386 var p Provider 387 stopCtx := p.StopContext() 388 p.MetaReset = func() error { 389 stopCtx = p.StopContext() 390 return nil 391 } 392 393 // cancel the current context 394 p.Stop() 395 396 if err := p.TestReset(); err != nil { 397 t.Fatal(err) 398 } 399 400 // the first context should have been replaced 401 if err := stopCtx.Err(); err != nil { 402 t.Fatal(err) 403 } 404 405 // we should not get a canceled context here either 406 if err := p.StopContext().Err(); err != nil { 407 t.Fatal(err) 408 } 409 }