github.com/rmenn/terraform@v0.3.8-0.20150225065417-fc84b3a78802/helper/schema/resource_test.go (about)

     1  package schema
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/terraform"
     9  )
    10  
    11  func TestResourceApply_create(t *testing.T) {
    12  	r := &Resource{
    13  		Schema: map[string]*Schema{
    14  			"foo": &Schema{
    15  				Type:     TypeInt,
    16  				Optional: true,
    17  			},
    18  		},
    19  	}
    20  
    21  	called := false
    22  	r.Create = func(d *ResourceData, m interface{}) error {
    23  		called = true
    24  		d.SetId("foo")
    25  		return nil
    26  	}
    27  
    28  	var s *terraform.InstanceState = nil
    29  
    30  	d := &terraform.InstanceDiff{
    31  		Attributes: map[string]*terraform.ResourceAttrDiff{
    32  			"foo": &terraform.ResourceAttrDiff{
    33  				New: "42",
    34  			},
    35  		},
    36  	}
    37  
    38  	actual, err := r.Apply(s, d, nil)
    39  	if err != nil {
    40  		t.Fatalf("err: %s", err)
    41  	}
    42  
    43  	if !called {
    44  		t.Fatal("not called")
    45  	}
    46  
    47  	expected := &terraform.InstanceState{
    48  		ID: "foo",
    49  		Attributes: map[string]string{
    50  			"id":  "foo",
    51  			"foo": "42",
    52  		},
    53  	}
    54  
    55  	if !reflect.DeepEqual(actual, expected) {
    56  		t.Fatalf("bad: %#v", actual)
    57  	}
    58  }
    59  
    60  func TestResourceApply_destroy(t *testing.T) {
    61  	r := &Resource{
    62  		Schema: map[string]*Schema{
    63  			"foo": &Schema{
    64  				Type:     TypeInt,
    65  				Optional: true,
    66  			},
    67  		},
    68  	}
    69  
    70  	called := false
    71  	r.Delete = func(d *ResourceData, m interface{}) error {
    72  		called = true
    73  		return nil
    74  	}
    75  
    76  	s := &terraform.InstanceState{
    77  		ID: "bar",
    78  	}
    79  
    80  	d := &terraform.InstanceDiff{
    81  		Destroy: true,
    82  	}
    83  
    84  	actual, err := r.Apply(s, d, nil)
    85  	if err != nil {
    86  		t.Fatalf("err: %s", err)
    87  	}
    88  
    89  	if !called {
    90  		t.Fatal("delete not called")
    91  	}
    92  
    93  	if actual != nil {
    94  		t.Fatalf("bad: %#v", actual)
    95  	}
    96  }
    97  
    98  func TestResourceApply_destroyCreate(t *testing.T) {
    99  	r := &Resource{
   100  		Schema: map[string]*Schema{
   101  			"foo": &Schema{
   102  				Type:     TypeInt,
   103  				Optional: true,
   104  			},
   105  
   106  			"tags": &Schema{
   107  				Type:     TypeMap,
   108  				Optional: true,
   109  				Computed: true,
   110  			},
   111  		},
   112  	}
   113  
   114  	change := false
   115  	r.Create = func(d *ResourceData, m interface{}) error {
   116  		change = d.HasChange("tags")
   117  		d.SetId("foo")
   118  		return nil
   119  	}
   120  	r.Delete = func(d *ResourceData, m interface{}) error {
   121  		return nil
   122  	}
   123  
   124  	var s *terraform.InstanceState = &terraform.InstanceState{
   125  		ID: "bar",
   126  		Attributes: map[string]string{
   127  			"foo":       "bar",
   128  			"tags.Name": "foo",
   129  		},
   130  	}
   131  
   132  	d := &terraform.InstanceDiff{
   133  		Attributes: map[string]*terraform.ResourceAttrDiff{
   134  			"foo": &terraform.ResourceAttrDiff{
   135  				New:         "42",
   136  				RequiresNew: true,
   137  			},
   138  			"tags.Name": &terraform.ResourceAttrDiff{
   139  				Old:         "foo",
   140  				New:         "foo",
   141  				RequiresNew: true,
   142  			},
   143  		},
   144  	}
   145  
   146  	actual, err := r.Apply(s, d, nil)
   147  	if err != nil {
   148  		t.Fatalf("err: %s", err)
   149  	}
   150  
   151  	if !change {
   152  		t.Fatal("should have change")
   153  	}
   154  
   155  	expected := &terraform.InstanceState{
   156  		ID: "foo",
   157  		Attributes: map[string]string{
   158  			"id":        "foo",
   159  			"foo":       "42",
   160  			"tags.#":    "1",
   161  			"tags.Name": "foo",
   162  		},
   163  	}
   164  
   165  	if !reflect.DeepEqual(actual, expected) {
   166  		t.Fatalf("bad: %#v", actual)
   167  	}
   168  }
   169  
   170  func TestResourceApply_destroyPartial(t *testing.T) {
   171  	r := &Resource{
   172  		Schema: map[string]*Schema{
   173  			"foo": &Schema{
   174  				Type:     TypeInt,
   175  				Optional: true,
   176  			},
   177  		},
   178  	}
   179  
   180  	r.Delete = func(d *ResourceData, m interface{}) error {
   181  		d.Set("foo", 42)
   182  		return fmt.Errorf("some error")
   183  	}
   184  
   185  	s := &terraform.InstanceState{
   186  		ID: "bar",
   187  		Attributes: map[string]string{
   188  			"foo": "12",
   189  		},
   190  	}
   191  
   192  	d := &terraform.InstanceDiff{
   193  		Destroy: true,
   194  	}
   195  
   196  	actual, err := r.Apply(s, d, nil)
   197  	if err == nil {
   198  		t.Fatal("should error")
   199  	}
   200  
   201  	expected := &terraform.InstanceState{
   202  		ID: "bar",
   203  		Attributes: map[string]string{
   204  			"id":  "bar",
   205  			"foo": "42",
   206  		},
   207  	}
   208  
   209  	if !reflect.DeepEqual(actual, expected) {
   210  		t.Fatalf("bad: %#v", actual)
   211  	}
   212  }
   213  
   214  func TestResourceApply_update(t *testing.T) {
   215  	r := &Resource{
   216  		Schema: map[string]*Schema{
   217  			"foo": &Schema{
   218  				Type:     TypeInt,
   219  				Optional: true,
   220  			},
   221  		},
   222  	}
   223  
   224  	r.Update = func(d *ResourceData, m interface{}) error {
   225  		d.Set("foo", 42)
   226  		return nil
   227  	}
   228  
   229  	s := &terraform.InstanceState{
   230  		ID: "foo",
   231  		Attributes: map[string]string{
   232  			"foo": "12",
   233  		},
   234  	}
   235  
   236  	d := &terraform.InstanceDiff{
   237  		Attributes: map[string]*terraform.ResourceAttrDiff{
   238  			"foo": &terraform.ResourceAttrDiff{
   239  				New: "13",
   240  			},
   241  		},
   242  	}
   243  
   244  	actual, err := r.Apply(s, d, nil)
   245  	if err != nil {
   246  		t.Fatalf("err: %s", err)
   247  	}
   248  
   249  	expected := &terraform.InstanceState{
   250  		ID: "foo",
   251  		Attributes: map[string]string{
   252  			"id":  "foo",
   253  			"foo": "42",
   254  		},
   255  	}
   256  
   257  	if !reflect.DeepEqual(actual, expected) {
   258  		t.Fatalf("bad: %#v", actual)
   259  	}
   260  }
   261  
   262  func TestResourceApply_updateNoCallback(t *testing.T) {
   263  	r := &Resource{
   264  		Schema: map[string]*Schema{
   265  			"foo": &Schema{
   266  				Type:     TypeInt,
   267  				Optional: true,
   268  			},
   269  		},
   270  	}
   271  
   272  	r.Update = nil
   273  
   274  	s := &terraform.InstanceState{
   275  		ID: "foo",
   276  		Attributes: map[string]string{
   277  			"foo": "12",
   278  		},
   279  	}
   280  
   281  	d := &terraform.InstanceDiff{
   282  		Attributes: map[string]*terraform.ResourceAttrDiff{
   283  			"foo": &terraform.ResourceAttrDiff{
   284  				New: "13",
   285  			},
   286  		},
   287  	}
   288  
   289  	actual, err := r.Apply(s, d, nil)
   290  	if err == nil {
   291  		t.Fatal("should error")
   292  	}
   293  
   294  	expected := &terraform.InstanceState{
   295  		ID: "foo",
   296  		Attributes: map[string]string{
   297  			"foo": "12",
   298  		},
   299  	}
   300  
   301  	if !reflect.DeepEqual(actual, expected) {
   302  		t.Fatalf("bad: %#v", actual)
   303  	}
   304  }
   305  
   306  func TestResourceInternalValidate(t *testing.T) {
   307  	cases := []struct {
   308  		In  *Resource
   309  		Err bool
   310  	}{
   311  		{
   312  			nil,
   313  			true,
   314  		},
   315  
   316  		// No optional and no required
   317  		{
   318  			&Resource{
   319  				Schema: map[string]*Schema{
   320  					"foo": &Schema{
   321  						Type:     TypeInt,
   322  						Optional: true,
   323  						Required: true,
   324  					},
   325  				},
   326  			},
   327  			true,
   328  		},
   329  	}
   330  
   331  	for i, tc := range cases {
   332  		err := tc.In.InternalValidate()
   333  		if (err != nil) != tc.Err {
   334  			t.Fatalf("%d: bad: %s", i, err)
   335  		}
   336  	}
   337  }
   338  
   339  func TestResourceRefresh(t *testing.T) {
   340  	r := &Resource{
   341  		Schema: map[string]*Schema{
   342  			"foo": &Schema{
   343  				Type:     TypeInt,
   344  				Optional: true,
   345  			},
   346  		},
   347  	}
   348  
   349  	r.Read = func(d *ResourceData, m interface{}) error {
   350  		if m != 42 {
   351  			return fmt.Errorf("meta not passed")
   352  		}
   353  
   354  		return d.Set("foo", d.Get("foo").(int)+1)
   355  	}
   356  
   357  	s := &terraform.InstanceState{
   358  		ID: "bar",
   359  		Attributes: map[string]string{
   360  			"foo": "12",
   361  		},
   362  	}
   363  
   364  	expected := &terraform.InstanceState{
   365  		ID: "bar",
   366  		Attributes: map[string]string{
   367  			"id":  "bar",
   368  			"foo": "13",
   369  		},
   370  	}
   371  
   372  	actual, err := r.Refresh(s, 42)
   373  	if err != nil {
   374  		t.Fatalf("err: %s", err)
   375  	}
   376  
   377  	if !reflect.DeepEqual(actual, expected) {
   378  		t.Fatalf("bad: %#v", actual)
   379  	}
   380  }
   381  
   382  func TestResourceRefresh_delete(t *testing.T) {
   383  	r := &Resource{
   384  		Schema: map[string]*Schema{
   385  			"foo": &Schema{
   386  				Type:     TypeInt,
   387  				Optional: true,
   388  			},
   389  		},
   390  	}
   391  
   392  	r.Read = func(d *ResourceData, m interface{}) error {
   393  		d.SetId("")
   394  		return nil
   395  	}
   396  
   397  	s := &terraform.InstanceState{
   398  		ID: "bar",
   399  		Attributes: map[string]string{
   400  			"foo": "12",
   401  		},
   402  	}
   403  
   404  	actual, err := r.Refresh(s, 42)
   405  	if err != nil {
   406  		t.Fatalf("err: %s", err)
   407  	}
   408  
   409  	if actual != nil {
   410  		t.Fatalf("bad: %#v", actual)
   411  	}
   412  }
   413  
   414  func TestResourceRefresh_existsError(t *testing.T) {
   415  	r := &Resource{
   416  		Schema: map[string]*Schema{
   417  			"foo": &Schema{
   418  				Type:     TypeInt,
   419  				Optional: true,
   420  			},
   421  		},
   422  	}
   423  
   424  	r.Exists = func(*ResourceData, interface{}) (bool, error) {
   425  		return false, fmt.Errorf("error")
   426  	}
   427  
   428  	r.Read = func(d *ResourceData, m interface{}) error {
   429  		panic("shouldn't be called")
   430  	}
   431  
   432  	s := &terraform.InstanceState{
   433  		ID: "bar",
   434  		Attributes: map[string]string{
   435  			"foo": "12",
   436  		},
   437  	}
   438  
   439  	actual, err := r.Refresh(s, 42)
   440  	if err == nil {
   441  		t.Fatalf("should error")
   442  	}
   443  	if !reflect.DeepEqual(actual, s) {
   444  		t.Fatalf("bad: %#v", actual)
   445  	}
   446  }
   447  
   448  func TestResourceRefresh_noExists(t *testing.T) {
   449  	r := &Resource{
   450  		Schema: map[string]*Schema{
   451  			"foo": &Schema{
   452  				Type:     TypeInt,
   453  				Optional: true,
   454  			},
   455  		},
   456  	}
   457  
   458  	r.Exists = func(*ResourceData, interface{}) (bool, error) {
   459  		return false, nil
   460  	}
   461  
   462  	r.Read = func(d *ResourceData, m interface{}) error {
   463  		panic("shouldn't be called")
   464  	}
   465  
   466  	s := &terraform.InstanceState{
   467  		ID: "bar",
   468  		Attributes: map[string]string{
   469  			"foo": "12",
   470  		},
   471  	}
   472  
   473  	actual, err := r.Refresh(s, 42)
   474  	if err != nil {
   475  		t.Fatalf("err: %s", err)
   476  	}
   477  	if actual != nil {
   478  		t.Fatalf("should have no state")
   479  	}
   480  }