helper/schema: create/update/delete should work for Resource
This commit is contained in:
parent
894187ec18
commit
c418681cc3
|
@ -31,6 +31,64 @@ type Resource struct {
|
|||
Delete DeleteFunc
|
||||
}
|
||||
|
||||
// Apply creates, updates, and/or deletes a resource.
|
||||
func (r *Resource) Apply(
|
||||
s *terraform.ResourceState,
|
||||
d *terraform.ResourceDiff,
|
||||
meta interface{}) (*terraform.ResourceState, error) {
|
||||
data, err := schemaMap(r.Schema).Data(s, d)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
|
||||
if s == nil {
|
||||
// The Terraform API dictates that this should never happen, but
|
||||
// it doesn't hurt to be safe in this case.
|
||||
s = new(terraform.ResourceState)
|
||||
}
|
||||
|
||||
if d.Destroy || d.RequiresNew() {
|
||||
if s.ID != "" {
|
||||
// Destroy the resource since it is created
|
||||
if err := r.Delete(data, meta); err != nil {
|
||||
return data.State(), err
|
||||
}
|
||||
|
||||
// Reset the data to be empty
|
||||
data, err = schemaMap(r.Schema).Data(nil, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// If we're only destroying, and not creating, then return
|
||||
// now since we're done!
|
||||
if !d.RequiresNew() {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
err = nil
|
||||
if s.ID == "" {
|
||||
// We're creating, it is a new resource.
|
||||
err = r.Create(data, meta)
|
||||
} else {
|
||||
err = r.Update(data, meta)
|
||||
}
|
||||
|
||||
// Always set the ID attribute if it is set. We also always collapse
|
||||
// the state since even partial states need to be returned.
|
||||
state := data.State()
|
||||
if state.ID != "" {
|
||||
if state.Attributes == nil {
|
||||
state.Attributes = make(map[string]string)
|
||||
}
|
||||
state.Attributes["id"] = state.ID
|
||||
}
|
||||
|
||||
return state, err
|
||||
}
|
||||
|
||||
// Diff returns a diff of this resource and is API compatible with the
|
||||
// ResourceProvider interface.
|
||||
func (r *Resource) Diff(
|
||||
|
|
|
@ -46,6 +46,16 @@ func (d *ResourceData) Set(key string, value interface{}) error {
|
|||
return d.setObject("", parts, d.schema, value)
|
||||
}
|
||||
|
||||
// SetId sets the ID of the resource. If the value is blank, then the
|
||||
// resource is destroyed.
|
||||
func (d *ResourceData) SetId(v string) {
|
||||
if d.newState == nil {
|
||||
d.newState = new(terraform.ResourceState)
|
||||
}
|
||||
|
||||
d.newState.ID = v
|
||||
}
|
||||
|
||||
// State returns the new ResourceState after the diff and any Set
|
||||
// calls.
|
||||
func (d *ResourceData) State() *terraform.ResourceState {
|
||||
|
|
|
@ -8,6 +8,184 @@ import (
|
|||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestResourceApply_create(t *testing.T) {
|
||||
r := &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"foo": &Schema{
|
||||
Type: TypeInt,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
called := false
|
||||
r.Create = func(d *ResourceData, m interface{}) error {
|
||||
called = true
|
||||
d.SetId("foo")
|
||||
return nil
|
||||
}
|
||||
|
||||
var s *terraform.ResourceState = nil
|
||||
|
||||
d := &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"foo": &terraform.ResourceAttrDiff{
|
||||
New: "42",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
actual, err := r.Apply(s, d, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("not called")
|
||||
}
|
||||
|
||||
expected := &terraform.ResourceState{
|
||||
ID: "foo",
|
||||
Attributes: map[string]string{
|
||||
"id": "foo",
|
||||
"foo": "42",
|
||||
},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceApply_destroy(t *testing.T) {
|
||||
r := &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"foo": &Schema{
|
||||
Type: TypeInt,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
called := false
|
||||
r.Delete = func(d *ResourceData, m interface{}) error {
|
||||
called = true
|
||||
return nil
|
||||
}
|
||||
|
||||
s := &terraform.ResourceState{
|
||||
ID: "bar",
|
||||
}
|
||||
|
||||
d := &terraform.ResourceDiff{
|
||||
Destroy: true,
|
||||
}
|
||||
|
||||
actual, err := r.Apply(s, d, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("delete not called")
|
||||
}
|
||||
|
||||
if actual != nil {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceApply_destroyPartial(t *testing.T) {
|
||||
r := &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"foo": &Schema{
|
||||
Type: TypeInt,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
r.Delete = func(d *ResourceData, m interface{}) error {
|
||||
d.Set("foo", 42)
|
||||
return fmt.Errorf("some error")
|
||||
}
|
||||
|
||||
s := &terraform.ResourceState{
|
||||
ID: "bar",
|
||||
Attributes: map[string]string{
|
||||
"foo": "12",
|
||||
},
|
||||
}
|
||||
|
||||
d := &terraform.ResourceDiff{
|
||||
Destroy: true,
|
||||
}
|
||||
|
||||
actual, err := r.Apply(s, d, nil)
|
||||
if err == nil {
|
||||
t.Fatal("should error")
|
||||
}
|
||||
|
||||
expected := &terraform.ResourceState{
|
||||
ID: "bar",
|
||||
Attributes: map[string]string{
|
||||
"foo": "42",
|
||||
},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceApply_update(t *testing.T) {
|
||||
r := &Resource{
|
||||
Schema: map[string]*Schema{
|
||||
"foo": &Schema{
|
||||
Type: TypeInt,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
r.Update = func(d *ResourceData, m interface{}) error {
|
||||
d.Set("foo", 42)
|
||||
return nil
|
||||
}
|
||||
|
||||
s := &terraform.ResourceState{
|
||||
ID: "foo",
|
||||
Attributes: map[string]string{
|
||||
"foo": "12",
|
||||
},
|
||||
}
|
||||
|
||||
d := &terraform.ResourceDiff{
|
||||
Attributes: map[string]*terraform.ResourceAttrDiff{
|
||||
"foo": &terraform.ResourceAttrDiff{
|
||||
New: "13",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
actual, err := r.Apply(s, d, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
expected := &terraform.ResourceState{
|
||||
ID: "foo",
|
||||
Attributes: map[string]string{
|
||||
"id": "foo",
|
||||
"foo": "42",
|
||||
},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceInternalValidate(t *testing.T) {
|
||||
cases := []struct {
|
||||
In *Resource
|
||||
|
|
Loading…
Reference in New Issue