2014-05-29 06:09:47 +02:00
|
|
|
package plugin
|
|
|
|
|
|
|
|
import (
|
2016-01-25 03:10:52 +01:00
|
|
|
"errors"
|
|
|
|
"reflect"
|
2014-05-29 06:09:47 +02:00
|
|
|
"testing"
|
2016-01-25 03:10:52 +01:00
|
|
|
|
|
|
|
"github.com/hashicorp/go-plugin"
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
2014-05-29 06:09:47 +02:00
|
|
|
)
|
|
|
|
|
2016-01-25 03:10:52 +01:00
|
|
|
func TestResourceProvider_impl(t *testing.T) {
|
|
|
|
var _ plugin.Plugin = new(ResourceProviderPlugin)
|
|
|
|
var _ terraform.ResourceProvider = new(ResourceProvider)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_input(t *testing.T) {
|
|
|
|
// Create a mock provider
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
input := new(terraform.MockUIInput)
|
|
|
|
|
|
|
|
expected := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"bar": "baz"},
|
|
|
|
}
|
|
|
|
p.InputReturnConfig = expected
|
|
|
|
|
|
|
|
// Input
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
actual, err := provider.Input(input, config)
|
|
|
|
if !p.InputCalled {
|
|
|
|
t.Fatal("input should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.InputConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.InputConfig)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %#v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(actual, expected) {
|
|
|
|
t.Fatalf("bad: %#v", actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_configure(t *testing.T) {
|
|
|
|
// Create a mock provider
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
e := provider.Configure(config)
|
|
|
|
if !p.ConfigureCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ConfigureConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ConfigureConfig)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_configure_errors(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
p.ConfigureReturnError = errors.New("foo")
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
e := provider.Configure(config)
|
|
|
|
if !p.ConfigureCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ConfigureConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ConfigureConfig)
|
|
|
|
}
|
|
|
|
if e == nil {
|
|
|
|
t.Fatal("should have error")
|
|
|
|
}
|
|
|
|
if e.Error() != "foo" {
|
|
|
|
t.Fatalf("bad: %s", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_configure_warnings(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
e := provider.Configure(config)
|
|
|
|
if !p.ConfigureCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ConfigureConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ConfigureConfig)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_apply(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ApplyReturn = &terraform.InstanceState{
|
|
|
|
ID: "bob",
|
|
|
|
}
|
|
|
|
|
|
|
|
// Apply
|
|
|
|
info := &terraform.InstanceInfo{}
|
|
|
|
state := &terraform.InstanceState{}
|
|
|
|
diff := &terraform.InstanceDiff{}
|
|
|
|
newState, err := provider.Apply(info, state, diff)
|
|
|
|
if !p.ApplyCalled {
|
|
|
|
t.Fatal("apply should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ApplyDiff, diff) {
|
|
|
|
t.Fatalf("bad: %#v", p.ApplyDiff)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %#v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ApplyReturn, newState) {
|
|
|
|
t.Fatalf("bad: %#v", newState)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_diff(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.DiffReturn = &terraform.InstanceDiff{
|
|
|
|
Attributes: map[string]*terraform.ResourceAttrDiff{
|
|
|
|
"foo": &terraform.ResourceAttrDiff{
|
|
|
|
Old: "",
|
|
|
|
New: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Diff
|
|
|
|
info := &terraform.InstanceInfo{}
|
|
|
|
state := &terraform.InstanceState{}
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
diff, err := provider.Diff(info, state, config)
|
|
|
|
if !p.DiffCalled {
|
|
|
|
t.Fatal("diff should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.DiffDesired, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.DiffDesired)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %#v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.DiffReturn, diff) {
|
|
|
|
t.Fatalf("bad: %#v", diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_diff_error(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.DiffReturnError = errors.New("foo")
|
|
|
|
|
|
|
|
// Diff
|
|
|
|
info := &terraform.InstanceInfo{}
|
|
|
|
state := &terraform.InstanceState{}
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
diff, err := provider.Diff(info, state, config)
|
|
|
|
if !p.DiffCalled {
|
|
|
|
t.Fatal("diff should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.DiffDesired, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.DiffDesired)
|
|
|
|
}
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("should have error")
|
|
|
|
}
|
|
|
|
if diff != nil {
|
|
|
|
t.Fatal("should not have diff")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_refresh(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.RefreshReturn = &terraform.InstanceState{
|
|
|
|
ID: "bob",
|
|
|
|
}
|
|
|
|
|
|
|
|
// Refresh
|
|
|
|
info := &terraform.InstanceInfo{}
|
|
|
|
state := &terraform.InstanceState{}
|
|
|
|
newState, err := provider.Refresh(info, state)
|
|
|
|
if !p.RefreshCalled {
|
|
|
|
t.Fatal("refresh should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.RefreshState, state) {
|
|
|
|
t.Fatalf("bad: %#v", p.RefreshState)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %#v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.RefreshReturn, newState) {
|
|
|
|
t.Fatalf("bad: %#v", newState)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-04 21:45:48 +02:00
|
|
|
func TestResourceProvider_importState(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ImportStateReturn = []*terraform.InstanceState{
|
|
|
|
&terraform.InstanceState{
|
|
|
|
ID: "bob",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// ImportState
|
|
|
|
info := &terraform.InstanceInfo{}
|
|
|
|
states, err := provider.ImportState(info, "foo")
|
|
|
|
if !p.ImportStateCalled {
|
|
|
|
t.Fatal("ImportState should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ImportStateInfo, info) {
|
|
|
|
t.Fatalf("bad: %#v", p.ImportStateInfo)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %#v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ImportStateReturn, states) {
|
|
|
|
t.Fatalf("bad: %#v", states)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 03:10:52 +01:00
|
|
|
func TestResourceProvider_resources(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
expected := []terraform.ResourceType{
|
2016-05-04 19:58:49 +02:00
|
|
|
terraform.ResourceType{Name: "foo"},
|
|
|
|
terraform.ResourceType{Name: "bar", Importable: true},
|
2016-01-25 03:10:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
p.ResourcesReturn = expected
|
|
|
|
|
|
|
|
// Resources
|
|
|
|
result := provider.Resources()
|
|
|
|
if !p.ResourcesCalled {
|
|
|
|
t.Fatal("resources should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(result, expected) {
|
|
|
|
t.Fatalf("bad: %#v", result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
core: New ResourceProvider methods for data resources
This is a breaking change to the ResourceProvider interface that adds the
new operations relating to data sources.
DataSources, ValidateDataSource, ReadDataDiff and ReadDataApply are the
data source equivalents of Resources, Validate, Diff and Apply (respectively)
for managed resources.
The diff/apply model seems at first glance a rather strange workflow for
read-only resources, but implementing data resources in this way allows them
to fit cleanly into the standard plan/apply lifecycle in cases where the
configuration contains computed arguments and thus the read must be deferred
until apply time.
Along with breaking the interface, we also fix up the plugin client/server
and helper/schema implementations of it, which are all of the callers
used when provider plugins use helper/schema. This would be a breaking
change for any provider plugin that directly implements the provider
interface, but no known plugins do this and it is not recommended.
At the helper/schema layer the implementer sees ReadDataApply as a "Read",
as opposed to "Create" or "Update" as in the managed resource Apply
implementation. The planning mechanics are handled entirely within
helper/schema, so that complexity is hidden from the provider implementation
itself.
2016-05-08 06:55:32 +02:00
|
|
|
func TestResourceProvider_readdataapply(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ReadDataApplyReturn = &terraform.InstanceState{
|
|
|
|
ID: "bob",
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadDataApply
|
|
|
|
info := &terraform.InstanceInfo{}
|
|
|
|
diff := &terraform.InstanceDiff{}
|
|
|
|
newState, err := provider.ReadDataApply(info, diff)
|
|
|
|
if !p.ReadDataApplyCalled {
|
|
|
|
t.Fatal("ReadDataApply should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ReadDataApplyDiff, diff) {
|
|
|
|
t.Fatalf("bad: %#v", p.ReadDataApplyDiff)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("bad: %#v", err)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ReadDataApplyReturn, newState) {
|
|
|
|
t.Fatalf("bad: %#v", newState)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_datasources(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
expected := []terraform.DataSource{
|
2016-07-29 22:05:57 +02:00
|
|
|
{Name: "foo"},
|
|
|
|
{Name: "bar"},
|
core: New ResourceProvider methods for data resources
This is a breaking change to the ResourceProvider interface that adds the
new operations relating to data sources.
DataSources, ValidateDataSource, ReadDataDiff and ReadDataApply are the
data source equivalents of Resources, Validate, Diff and Apply (respectively)
for managed resources.
The diff/apply model seems at first glance a rather strange workflow for
read-only resources, but implementing data resources in this way allows them
to fit cleanly into the standard plan/apply lifecycle in cases where the
configuration contains computed arguments and thus the read must be deferred
until apply time.
Along with breaking the interface, we also fix up the plugin client/server
and helper/schema implementations of it, which are all of the callers
used when provider plugins use helper/schema. This would be a breaking
change for any provider plugin that directly implements the provider
interface, but no known plugins do this and it is not recommended.
At the helper/schema layer the implementer sees ReadDataApply as a "Read",
as opposed to "Create" or "Update" as in the managed resource Apply
implementation. The planning mechanics are handled entirely within
helper/schema, so that complexity is hidden from the provider implementation
itself.
2016-05-08 06:55:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
p.DataSourcesReturn = expected
|
|
|
|
|
|
|
|
// DataSources
|
|
|
|
result := provider.DataSources()
|
|
|
|
if !p.DataSourcesCalled {
|
|
|
|
t.Fatal("DataSources should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(result, expected) {
|
|
|
|
t.Fatalf("bad: %#v", result)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 03:10:52 +01:00
|
|
|
func TestResourceProvider_validate(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.Validate(config)
|
|
|
|
if !p.ValidateCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateConfig)
|
|
|
|
}
|
|
|
|
if w != nil {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_validate_errors(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ValidateReturnErrors = []error{errors.New("foo")}
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.Validate(config)
|
|
|
|
if !p.ValidateCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateConfig)
|
|
|
|
}
|
|
|
|
if w != nil {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(e) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
if e[0].Error() != "foo" {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_validate_warns(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ValidateReturnWarns = []string{"foo"}
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.Validate(config)
|
|
|
|
if !p.ValidateCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateConfig)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := []string{"foo"}
|
|
|
|
if !reflect.DeepEqual(w, expected) {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_validateResource(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
2014-05-29 06:09:47 +02:00
|
|
|
|
2016-01-25 03:10:52 +01:00
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
2014-05-29 06:09:47 +02:00
|
|
|
if err != nil {
|
2016-01-25 03:10:52 +01:00
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.ValidateResource("foo", config)
|
|
|
|
if !p.ValidateResourceCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if p.ValidateResourceType != "foo" {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateResourceType)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateResourceConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateResourceConfig)
|
|
|
|
}
|
|
|
|
if w != nil {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_validateResource_errors(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ValidateResourceReturnErrors = []error{errors.New("foo")}
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.ValidateResource("foo", config)
|
|
|
|
if !p.ValidateResourceCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if p.ValidateResourceType != "foo" {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateResourceType)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateResourceConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateResourceConfig)
|
|
|
|
}
|
|
|
|
if w != nil {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(e) != 1 {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
if e[0].Error() != "foo" {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestResourceProvider_validateResource_warns(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
p.ValidateResourceReturnWarns = []string{"foo"}
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.ValidateResource("foo", config)
|
|
|
|
if !p.ValidateResourceCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if p.ValidateResourceType != "foo" {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateResourceType)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateResourceConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateResourceConfig)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := []string{"foo"}
|
|
|
|
if !reflect.DeepEqual(w, expected) {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
core: New ResourceProvider methods for data resources
This is a breaking change to the ResourceProvider interface that adds the
new operations relating to data sources.
DataSources, ValidateDataSource, ReadDataDiff and ReadDataApply are the
data source equivalents of Resources, Validate, Diff and Apply (respectively)
for managed resources.
The diff/apply model seems at first glance a rather strange workflow for
read-only resources, but implementing data resources in this way allows them
to fit cleanly into the standard plan/apply lifecycle in cases where the
configuration contains computed arguments and thus the read must be deferred
until apply time.
Along with breaking the interface, we also fix up the plugin client/server
and helper/schema implementations of it, which are all of the callers
used when provider plugins use helper/schema. This would be a breaking
change for any provider plugin that directly implements the provider
interface, but no known plugins do this and it is not recommended.
At the helper/schema layer the implementer sees ReadDataApply as a "Read",
as opposed to "Create" or "Update" as in the managed resource Apply
implementation. The planning mechanics are handled entirely within
helper/schema, so that complexity is hidden from the provider implementation
itself.
2016-05-08 06:55:32 +02:00
|
|
|
func TestResourceProvider_validateDataSource(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
// Configure
|
|
|
|
config := &terraform.ResourceConfig{
|
|
|
|
Raw: map[string]interface{}{"foo": "bar"},
|
|
|
|
}
|
|
|
|
w, e := provider.ValidateDataSource("foo", config)
|
|
|
|
if !p.ValidateDataSourceCalled {
|
|
|
|
t.Fatal("configure should be called")
|
|
|
|
}
|
|
|
|
if p.ValidateDataSourceType != "foo" {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateDataSourceType)
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(p.ValidateDataSourceConfig, config) {
|
|
|
|
t.Fatalf("bad: %#v", p.ValidateDataSourceConfig)
|
|
|
|
}
|
|
|
|
if w != nil {
|
|
|
|
t.Fatalf("bad: %#v", w)
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
t.Fatalf("bad: %#v", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-25 03:10:52 +01:00
|
|
|
func TestResourceProvider_close(t *testing.T) {
|
|
|
|
p := new(terraform.MockResourceProvider)
|
|
|
|
|
|
|
|
// Create a mock provider
|
|
|
|
client, _ := plugin.TestPluginRPCConn(t, pluginMap(&ServeOpts{
|
|
|
|
ProviderFunc: testProviderFixed(p),
|
|
|
|
}))
|
|
|
|
defer client.Close()
|
|
|
|
|
|
|
|
// Request the provider
|
|
|
|
raw, err := client.Dispense(ProviderPluginName)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %s", err)
|
|
|
|
}
|
|
|
|
provider := raw.(terraform.ResourceProvider)
|
|
|
|
|
|
|
|
var iface interface{} = provider
|
|
|
|
pCloser, ok := iface.(terraform.ResourceProviderCloser)
|
|
|
|
if !ok {
|
|
|
|
t.Fatal("should be a ResourceProviderCloser")
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := pCloser.Close(); err != nil {
|
|
|
|
t.Fatalf("failed to close provider: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// The connection should be closed now, so if we to make a
|
|
|
|
// new call we should get an error.
|
|
|
|
err = provider.Configure(&terraform.ResourceConfig{})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("should have error")
|
2014-05-29 06:09:47 +02:00
|
|
|
}
|
|
|
|
}
|