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
|
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
|
// Diff returns a diff of this resource and is API compatible with the
|
||||||
// ResourceProvider interface.
|
// ResourceProvider interface.
|
||||||
func (r *Resource) Diff(
|
func (r *Resource) Diff(
|
||||||
|
|
|
@ -46,6 +46,16 @@ func (d *ResourceData) Set(key string, value interface{}) error {
|
||||||
return d.setObject("", parts, d.schema, value)
|
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
|
// State returns the new ResourceState after the diff and any Set
|
||||||
// calls.
|
// calls.
|
||||||
func (d *ResourceData) State() *terraform.ResourceState {
|
func (d *ResourceData) State() *terraform.ResourceState {
|
||||||
|
|
|
@ -8,6 +8,184 @@ import (
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"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) {
|
func TestResourceInternalValidate(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
In *Resource
|
In *Resource
|
||||||
|
|
Loading…
Reference in New Issue