From d206211db21a7b807d051ab2337c4e0981fc15e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Sacrist=C3=A1n=20Izcue?= Date: Sat, 18 May 2024 18:24:01 +0200 Subject: [PATCH 1/3] chore(sdk): Serve the provider through a mux server This is in preparation to migrate to the plugin framework. --- cloudamqp/provider_test.go | 21 ++++++++++----- cloudamqp/resource_cloudamqp_alarm_test.go | 3 +-- ...resource_cloudamqp_aws_eventbridge_test.go | 3 +-- ...resource_cloudamqp_extra_disk_size_test.go | 9 +++---- cloudamqp/resource_cloudamqp_instance_test.go | 12 +++------ ...resource_cloudamqp_integration_log_test.go | 3 +-- ...ource_cloudamqp_integration_metric_test.go | 3 +-- ...ource_cloudamqp_maintenance_window_test.go | 6 ++--- .../resource_cloudamqp_notification_test.go | 3 +-- ...esource_cloudamqp_plugin_community_test.go | 3 +-- cloudamqp/resource_cloudamqp_plugin_test.go | 3 +-- ...e_cloudamqp_rabbitmq_configuration_test.go | 6 ++--- ...source_cloudamqp_security_firewall_test.go | 3 +-- ...resource_cloudamqp_upgrade_lavinmq_test.go | 3 +-- ...esource_cloudamqp_upgrade_rabbitmq_test.go | 6 ++--- .../resource_cloudamqp_vpc_connect_test.go | 9 +++---- ...resource_cloudamqp_vpc_gcp_peering_test.go | 3 +-- .../resource_cloudamqp_vpc_peering_test.go | 1 - cloudamqp/resource_cloudamqp_webhook_test.go | 3 +-- go.mod | 3 ++- go.sum | 6 +++-- main.go | 27 ++++++++++++++----- 22 files changed, 68 insertions(+), 71 deletions(-) diff --git a/cloudamqp/provider_test.go b/cloudamqp/provider_test.go index 0be2f40b..0c4f50fb 100644 --- a/cloudamqp/provider_test.go +++ b/cloudamqp/provider_test.go @@ -1,6 +1,7 @@ package cloudamqp import ( + "context" "fmt" "net/http" "net/url" @@ -9,16 +10,15 @@ import ( "testing" "github.com/cloudamqp/terraform-provider-cloudamqp/cloudamqp/vcr-testing/sanitizer" + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-mux/tf5muxserver" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/tidwall/gjson" "gopkg.in/dnaeon/go-vcr.v3/cassette" "gopkg.in/dnaeon/go-vcr.v3/recorder" ) var ( - testAccProviderFactory map[string]func() (*schema.Provider, error) - mode = recorder.ModeReplayOnly ) @@ -167,10 +167,19 @@ func cloudamqpResourceTest(t *testing.T, c resource.TestCase) { return req.URL.Path == "/login" }) - testAccProviderFactory = map[string]func() (*schema.Provider, error){ - "cloudamqp": func() (*schema.Provider, error) { return Provider("1.0", rec.GetDefaultClient()), nil }, + c.ProtoV5ProviderFactories = map[string]func() (tfprotov5.ProviderServer, error){ + "cloudamqp": func() (tfprotov5.ProviderServer, error) { + ctx := context.Background() + + muxServer, err := tf5muxserver.NewMuxServer(ctx, Provider("1.0", rec.GetDefaultClient()).GRPCProvider) + + if err != nil { + return nil, err + } + + return muxServer.ProviderServer(), nil + }, } - c.ProviderFactories = testAccProviderFactory resource.Test(t, c) } diff --git a/cloudamqp/resource_cloudamqp_alarm_test.go b/cloudamqp/resource_cloudamqp_alarm_test.go index 6ca2f0a5..79c6502d 100644 --- a/cloudamqp/resource_cloudamqp_alarm_test.go +++ b/cloudamqp/resource_cloudamqp_alarm_test.go @@ -55,8 +55,7 @@ func TestAccAlarm_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_aws_eventbridge_test.go b/cloudamqp/resource_cloudamqp_aws_eventbridge_test.go index 2cc59860..d8de79cd 100644 --- a/cloudamqp/resource_cloudamqp_aws_eventbridge_test.go +++ b/cloudamqp/resource_cloudamqp_aws_eventbridge_test.go @@ -27,8 +27,7 @@ func TestAccIntegrationAwsEventbridge_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_extra_disk_size_test.go b/cloudamqp/resource_cloudamqp_extra_disk_size_test.go index 662e51c3..e465e0e2 100644 --- a/cloudamqp/resource_cloudamqp_extra_disk_size_test.go +++ b/cloudamqp/resource_cloudamqp_extra_disk_size_test.go @@ -26,8 +26,7 @@ func TestAccExtraDiskSize_AWS_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -60,8 +59,7 @@ func TestAccExtraDiskSize_GCE_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -94,8 +92,7 @@ func TestAccExtraDiskSize_Azure_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_instance_test.go b/cloudamqp/resource_cloudamqp_instance_test.go index 48379a3b..c0c6beeb 100644 --- a/cloudamqp/resource_cloudamqp_instance_test.go +++ b/cloudamqp/resource_cloudamqp_instance_test.go @@ -34,8 +34,7 @@ func TestAccInstance_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -96,8 +95,7 @@ func TestAccInstance_Upgrade(t *testing.T) { } ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -146,8 +144,7 @@ func TestAccInstance_PlanChange(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -189,8 +186,7 @@ func TestAccInstance_Downgrade(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_integration_log_test.go b/cloudamqp/resource_cloudamqp_integration_log_test.go index b8de0d0e..53a0d4c3 100644 --- a/cloudamqp/resource_cloudamqp_integration_log_test.go +++ b/cloudamqp/resource_cloudamqp_integration_log_test.go @@ -55,8 +55,7 @@ func TestAccIntegrationLog_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { ExpectNonEmptyPlan: true, diff --git a/cloudamqp/resource_cloudamqp_integration_metric_test.go b/cloudamqp/resource_cloudamqp_integration_metric_test.go index 957f6190..94427ddd 100644 --- a/cloudamqp/resource_cloudamqp_integration_metric_test.go +++ b/cloudamqp/resource_cloudamqp_integration_metric_test.go @@ -40,8 +40,7 @@ func TestAccIntegrationMetric_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { ExpectNonEmptyPlan: true, diff --git a/cloudamqp/resource_cloudamqp_maintenance_window_test.go b/cloudamqp/resource_cloudamqp_maintenance_window_test.go index 04dec69f..bd6b107f 100644 --- a/cloudamqp/resource_cloudamqp_maintenance_window_test.go +++ b/cloudamqp/resource_cloudamqp_maintenance_window_test.go @@ -53,8 +53,7 @@ func TestAccMaintenanceWindow_LavinMQ(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNamesDayTime, paramsDayTime), @@ -138,8 +137,7 @@ func TestAccMaintenanceWindow_RabbitMQ(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNamesDayTime, paramsDayTime), diff --git a/cloudamqp/resource_cloudamqp_notification_test.go b/cloudamqp/resource_cloudamqp_notification_test.go index 2a6cb6cb..4c94abb0 100644 --- a/cloudamqp/resource_cloudamqp_notification_test.go +++ b/cloudamqp/resource_cloudamqp_notification_test.go @@ -35,8 +35,7 @@ func TestAccNotification_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_plugin_community_test.go b/cloudamqp/resource_cloudamqp_plugin_community_test.go index 037309f5..cf8873c5 100644 --- a/cloudamqp/resource_cloudamqp_plugin_community_test.go +++ b/cloudamqp/resource_cloudamqp_plugin_community_test.go @@ -40,8 +40,7 @@ func TestAccPluginCommunity_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_plugin_test.go b/cloudamqp/resource_cloudamqp_plugin_test.go index f2b97011..1e42abbd 100644 --- a/cloudamqp/resource_cloudamqp_plugin_test.go +++ b/cloudamqp/resource_cloudamqp_plugin_test.go @@ -40,8 +40,7 @@ func TestAccPlugin_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_rabbitmq_configuration_test.go b/cloudamqp/resource_cloudamqp_rabbitmq_configuration_test.go index a8398ffb..cec3958a 100644 --- a/cloudamqp/resource_cloudamqp_rabbitmq_configuration_test.go +++ b/cloudamqp/resource_cloudamqp_rabbitmq_configuration_test.go @@ -27,8 +27,7 @@ func TestAccRabbitMqConfiguration_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -70,8 +69,7 @@ func TestAccRabbitMqConfiguration_LogExhangeLevel(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_security_firewall_test.go b/cloudamqp/resource_cloudamqp_security_firewall_test.go index 069b7491..77152eb2 100644 --- a/cloudamqp/resource_cloudamqp_security_firewall_test.go +++ b/cloudamqp/resource_cloudamqp_security_firewall_test.go @@ -39,8 +39,7 @@ func TestAccFirewall_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_upgrade_lavinmq_test.go b/cloudamqp/resource_cloudamqp_upgrade_lavinmq_test.go index e1dc51f4..8313f58b 100644 --- a/cloudamqp/resource_cloudamqp_upgrade_lavinmq_test.go +++ b/cloudamqp/resource_cloudamqp_upgrade_lavinmq_test.go @@ -48,8 +48,7 @@ func TestAccUpgradeLavinMQ(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_upgrade_rabbitmq_test.go b/cloudamqp/resource_cloudamqp_upgrade_rabbitmq_test.go index 574c60f7..663e92ec 100644 --- a/cloudamqp/resource_cloudamqp_upgrade_rabbitmq_test.go +++ b/cloudamqp/resource_cloudamqp_upgrade_rabbitmq_test.go @@ -57,8 +57,7 @@ func TestAccUpgradeRabbitMQ_Latest(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -151,8 +150,7 @@ func TestAccUpgradeRabbitMQ_Specific(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_vpc_connect_test.go b/cloudamqp/resource_cloudamqp_vpc_connect_test.go index d8316d11..c7817761 100644 --- a/cloudamqp/resource_cloudamqp_vpc_connect_test.go +++ b/cloudamqp/resource_cloudamqp_vpc_connect_test.go @@ -43,8 +43,7 @@ func TestAccVpcConnect_AWS_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -98,8 +97,7 @@ func TestAccVpcConnect_Azure_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), @@ -142,8 +140,7 @@ func TestAccVpcConnect_GCP_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_vpc_gcp_peering_test.go b/cloudamqp/resource_cloudamqp_vpc_gcp_peering_test.go index 0bb25ba4..20f6c562 100644 --- a/cloudamqp/resource_cloudamqp_vpc_gcp_peering_test.go +++ b/cloudamqp/resource_cloudamqp_vpc_gcp_peering_test.go @@ -33,8 +33,7 @@ func TestAccVpcGcpPeering_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/cloudamqp/resource_cloudamqp_vpc_peering_test.go b/cloudamqp/resource_cloudamqp_vpc_peering_test.go index b839d188..4eb57b79 100644 --- a/cloudamqp/resource_cloudamqp_vpc_peering_test.go +++ b/cloudamqp/resource_cloudamqp_vpc_peering_test.go @@ -22,7 +22,6 @@ func TestAccVpcPeering_Basic(t *testing.T) { cloudamqpResourceTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, PreventPostDestroyRefresh: true, Steps: []resource.TestStep{ { diff --git a/cloudamqp/resource_cloudamqp_webhook_test.go b/cloudamqp/resource_cloudamqp_webhook_test.go index 3531302b..00e9504e 100644 --- a/cloudamqp/resource_cloudamqp_webhook_test.go +++ b/cloudamqp/resource_cloudamqp_webhook_test.go @@ -37,8 +37,7 @@ func TestAccWebhook_Basic(t *testing.T) { ) cloudamqpResourceTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProviderFactories: testAccProviderFactory, + PreCheck: func() { testAccPreCheck(t) }, Steps: []resource.TestStep{ { Config: configuration.GetTemplatedConfig(t, fileNames, params), diff --git a/go.mod b/go.mod index 2eaecaf8..d4ec11fa 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.24.0 require ( github.com/dghubble/sling v1.4.2 + github.com/hashicorp/terraform-plugin-go v0.28.0 github.com/hashicorp/terraform-plugin-log v0.9.0 + github.com/hashicorp/terraform-plugin-mux v0.20.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 github.com/tidwall/gjson v1.18.0 github.com/tidwall/sjson v1.2.5 @@ -35,7 +37,6 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.23.0 // indirect github.com/hashicorp/terraform-json v0.25.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.27.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.5 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect diff --git a/go.sum b/go.sum index 0eb17c30..5ab5f2b6 100644 --- a/go.sum +++ b/go.sum @@ -85,10 +85,12 @@ github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEs github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ= github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc= -github.com/hashicorp/terraform-plugin-go v0.27.0 h1:ujykws/fWIdsi6oTUT5Or4ukvEan4aN9lY+LOxVP8EE= -github.com/hashicorp/terraform-plugin-go v0.27.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= +github.com/hashicorp/terraform-plugin-go v0.28.0 h1:zJmu2UDwhVN0J+J20RE5huiF3XXlTYVIleaevHZgKPA= +github.com/hashicorp/terraform-plugin-go v0.28.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= +github.com/hashicorp/terraform-plugin-mux v0.20.0 h1:3QpBnI9uCuL0Yy2Rq/kR9cOdmOFNhw88A2GoZtk5aXM= +github.com/hashicorp/terraform-plugin-mux v0.20.0/go.mod h1:wSIZwJjSYk86NOTX3fKUlThMT4EAV1XpBHz9SAvjQr4= github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0 h1:NFPMacTrY/IdcIcnUB+7hsore1ZaRWU9cnB6jFoBnIM= github.com/hashicorp/terraform-plugin-sdk/v2 v2.37.0/go.mod h1:QYmYnLfsosrxjCnGY1p9c7Zj6n9thnEE+7RObeYs3fA= github.com/hashicorp/terraform-registry-address v0.2.5 h1:2GTftHqmUhVOeuu9CW3kwDkRe4pcBDq0uuK5VJngU1M= diff --git a/main.go b/main.go index 55720f3b..74d7e3f9 100644 --- a/main.go +++ b/main.go @@ -1,19 +1,32 @@ package main import ( + "context" + "log" "net/http" "github.com/cloudamqp/terraform-provider-cloudamqp/cloudamqp" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/v2/plugin" + "github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server" + "github.com/hashicorp/terraform-plugin-mux/tf5muxserver" ) var version string func main() { - plugin.Serve(&plugin.ServeOpts{ - ProviderFunc: func() *schema.Provider { - return cloudamqp.Provider(version, http.DefaultClient) - }, - }) + ctx := context.Background() + + muxServer, err := tf5muxserver.NewMuxServer(ctx, cloudamqp.Provider(version, http.DefaultClient).GRPCProvider) + + if err != nil { + log.Fatal(err) + } + + err = tf5server.Serve( + "registry.terraform.io/cloudamqp/cloudamqp", + muxServer.ProviderServer, + ) + + if err != nil { + log.Fatal(err) + } } From 7e2db5c70e1045211f1345f2286ca64da4847ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Sacrist=C3=A1n=20Izcue?= Date: Mon, 20 May 2024 00:30:45 +0200 Subject: [PATCH 2/3] chore(sdk): Implement skeleton of provider in the framework plugin This combined with the muxing will allow us to migrate resources and datasources one at a time --- cloudamqp/provider.go | 125 ++++++++++++++++++++++++++++++++----- cloudamqp/provider_test.go | 8 ++- go.mod | 1 + go.sum | 2 + main.go | 6 +- 5 files changed, 124 insertions(+), 18 deletions(-) diff --git a/cloudamqp/provider.go b/cloudamqp/provider.go index d5a173ec..d4a29be4 100644 --- a/cloudamqp/provider.go +++ b/cloudamqp/provider.go @@ -1,42 +1,137 @@ package cloudamqp import ( + "context" "fmt" "log" "net/http" + "os" "github.com/cloudamqp/terraform-provider-cloudamqp/api" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/provider" + "github.com/hashicorp/terraform-plugin-framework/provider/schema" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + schemaSdk "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) var version string var enableFasterInstanceDestroy bool -func Provider(v string, client *http.Client) *schema.Provider { +type cloudamqpProvider struct { + version string + client *http.Client +} + +type cloudamqpProviderModel struct { + ApiKey types.String `tfsdk:"apikey"` + BaseUrl types.String `tfsdk:"baseurl"` + EnableFasterInstanceDestroy types.Bool `tfsdk:"enable_faster_instance_destroy"` +} + +func (p *cloudamqpProvider) Metadata(_ context.Context, _ provider.MetadataRequest, response *provider.MetadataResponse) { + response.Version = p.version + response.TypeName = "cloudamqp" +} + +func (p *cloudamqpProvider) Schema(_ context.Context, _ provider.SchemaRequest, response *provider.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "apikey": schema.StringAttribute{ + Optional: true, + Description: "Key used to authentication to the CloudAMQP Customer API", + }, + "baseurl": schema.StringAttribute{ + Optional: true, + Description: "Base URL to CloudAMQP Customer website", + }, + "enable_faster_instance_destroy": schema.BoolAttribute{ + Optional: true, + Description: "Skips destroying backend resources on 'terraform destroy'", + }, + }, + } +} + +func (p *cloudamqpProvider) Configure(ctx context.Context, request provider.ConfigureRequest, response *provider.ConfigureResponse) { + var data cloudamqpProviderModel + + // Read configuration data into model + response.Diagnostics.Append(request.Config.Get(ctx, &data)...) + + apiKey := data.ApiKey.ValueString() + baseUrl := data.BaseUrl.ValueString() + + // Check configuration data, which should take precedence over + // environment variable data, if found. + if apiKey == "" { + apiKey = os.Getenv("CLOUDAMQP_APIKEY") + } + + if apiKey == "" { + response.Diagnostics.AddError( + "Missing API Key Configuration", + "While configuring the provider, the API key was not found in "+ + "the CLOUDAMQP_APIKEY environment variable or provider "+ + "configuration block apikey attribute.", + ) + } + + if baseUrl == "" { + baseUrl = os.Getenv("CLOUDAMQP_BASEURL") + } + + if baseUrl == "" { + baseUrl = "https://customer.cloudamqp.com" + } + + useragent := fmt.Sprintf("terraform-provider-cloudamqp_v%s", p.version) + log.Printf("[DEBUG] cloudamqp::provider::configure useragent: %v", useragent) + apiClient := api.New(baseUrl, apiKey, useragent, p.client) + + response.ResourceData = apiClient + response.DataSourceData = apiClient +} + +func (p *cloudamqpProvider) DataSources(_ context.Context) []func() datasource.DataSource { + return []func() datasource.DataSource{} +} + +func (p *cloudamqpProvider) Resources(_ context.Context) []func() resource.Resource { + return []func() resource.Resource{} +} + +func New(version string, client *http.Client) provider.Provider { + return &cloudamqpProvider{version, client} +} + +func Provider(v string, client *http.Client) *schemaSdk.Provider { version = v log.Printf("Terraform-Provider-CloudAMQP Version: %s", version) - return &schema.Provider{ - Schema: map[string]*schema.Schema{ + return &schemaSdk.Provider{ + Schema: map[string]*schemaSdk.Schema{ "apikey": { - Type: schema.TypeString, + Type: schemaSdk.TypeString, Required: true, - DefaultFunc: schema.EnvDefaultFunc("CLOUDAMQP_APIKEY", nil), + DefaultFunc: schemaSdk.EnvDefaultFunc("CLOUDAMQP_APIKEY", nil), Description: "Key used to authentication to the CloudAMQP Customer API", }, "baseurl": { - Type: schema.TypeString, - DefaultFunc: schema.EnvDefaultFunc("CLOUDAMQP_BASEURL", "https://customer.cloudamqp.com"), + Type: schemaSdk.TypeString, + DefaultFunc: schemaSdk.EnvDefaultFunc("CLOUDAMQP_BASEURL", "https://customer.cloudamqp.com"), Optional: true, Description: "Base URL to CloudAMQP Customer website", }, "enable_faster_instance_destroy": { - Type: schema.TypeBool, - DefaultFunc: schema.EnvDefaultFunc("CLOUDAMQP_ENABLE_FASTER_INSTANCE_DESTROY", false), + Type: schemaSdk.TypeBool, + DefaultFunc: schemaSdk.EnvDefaultFunc("CLOUDAMQP_ENABLE_FASTER_INSTANCE_DESTROY", false), Optional: true, Description: "Skips destroying backend resources on 'terraform destroy'", }, }, - DataSourcesMap: map[string]*schema.Resource{ + DataSourcesMap: map[string]*schemaSdk.Resource{ "cloudamqp_account_vpcs": dataSourceAccountVpcs(), "cloudamqp_account": dataSourceAccount(), "cloudamqp_alarm": dataSourceAlarm(), @@ -52,7 +147,7 @@ func Provider(v string, client *http.Client) *schema.Provider { "cloudamqp_vpc_gcp_info": dataSourceVpcGcpInfo(), "cloudamqp_vpc_info": dataSourceVpcInfo(), }, - ResourcesMap: map[string]*schema.Resource{ + ResourcesMap: map[string]*schemaSdk.Resource{ "cloudamqp_account_action": resourceAccountAction(), "cloudamqp_alarm": resourceAlarm(), "cloudamqp_custom_domain": resourceCustomDomain(), @@ -78,12 +173,12 @@ func Provider(v string, client *http.Client) *schema.Provider { "cloudamqp_vpc": resourceVpc(), "cloudamqp_webhook": resourceWebhook(), }, - ConfigureFunc: configureClient(client), + ConfigureContextFunc: configureClient(client), } } -func configureClient(client *http.Client) schema.ConfigureFunc { - return func(d *schema.ResourceData) (any, error) { +func configureClient(client *http.Client) schemaSdk.ConfigureContextFunc { + return func(ctx context.Context, d *schemaSdk.ResourceData) (interface{}, diag.Diagnostics) { enableFasterInstanceDestroy = d.Get("enable_faster_instance_destroy").(bool) useragent := fmt.Sprintf("terraform-provider-cloudamqp_v%s", version) return api.New(d.Get("baseurl").(string), d.Get("apikey").(string), useragent, client), nil diff --git a/cloudamqp/provider_test.go b/cloudamqp/provider_test.go index 0c4f50fb..43a5db6f 100644 --- a/cloudamqp/provider_test.go +++ b/cloudamqp/provider_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/cloudamqp/terraform-provider-cloudamqp/cloudamqp/vcr-testing/sanitizer" + "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov5" "github.com/hashicorp/terraform-plugin-mux/tf5muxserver" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -146,7 +147,7 @@ func cloudamqpResourceTest(t *testing.T, c resource.TestCase) { fmt.Println("SKIP: PUT /api/instances/{id}/config", i.Request.URL, "error:", errStr) i.DiscardOnSave = true } - case i.Response.Code == 200 && i.Request.Method == "GET" && + case i.Response.Code == 200 && i.Request.Method == "GET" && regexp.MustCompile(`/api/vpcs/\d+/vpc-peering$`).MatchString(i.Request.URL): // Filter polling for vpc peering state, only store active response state := gjson.Get(i.Response.Body, "rows.0.state").String() @@ -171,7 +172,10 @@ func cloudamqpResourceTest(t *testing.T, c resource.TestCase) { "cloudamqp": func() (tfprotov5.ProviderServer, error) { ctx := context.Background() - muxServer, err := tf5muxserver.NewMuxServer(ctx, Provider("1.0", rec.GetDefaultClient()).GRPCProvider) + muxServer, err := tf5muxserver.NewMuxServer(ctx, + Provider("1.0", rec.GetDefaultClient()).GRPCProvider, + providerserver.NewProtocol5(New("1.0", rec.GetDefaultClient())), + ) if err != nil { return nil, err diff --git a/go.mod b/go.mod index d4ec11fa..11802918 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.24.0 require ( github.com/dghubble/sling v1.4.2 + github.com/hashicorp/terraform-plugin-framework v1.15.0 github.com/hashicorp/terraform-plugin-go v0.28.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-mux v0.20.0 diff --git a/go.sum b/go.sum index 5ab5f2b6..7cc46f04 100644 --- a/go.sum +++ b/go.sum @@ -85,6 +85,8 @@ github.com/hashicorp/terraform-exec v0.23.0 h1:MUiBM1s0CNlRFsCLJuM5wXZrzA3MnPYEs github.com/hashicorp/terraform-exec v0.23.0/go.mod h1:mA+qnx1R8eePycfwKkCRk3Wy65mwInvlpAeOwmA7vlY= github.com/hashicorp/terraform-json v0.25.0 h1:rmNqc/CIfcWawGiwXmRuiXJKEiJu1ntGoxseG1hLhoQ= github.com/hashicorp/terraform-json v0.25.0/go.mod h1:sMKS8fiRDX4rVlR6EJUMudg1WcanxCMoWwTLkgZP/vc= +github.com/hashicorp/terraform-plugin-framework v1.15.0 h1:LQ2rsOfmDLxcn5EeIwdXFtr03FVsNktbbBci8cOKdb4= +github.com/hashicorp/terraform-plugin-framework v1.15.0/go.mod h1:hxrNI/GY32KPISpWqlCoTLM9JZsGH3CyYlir09bD/fI= github.com/hashicorp/terraform-plugin-go v0.28.0 h1:zJmu2UDwhVN0J+J20RE5huiF3XXlTYVIleaevHZgKPA= github.com/hashicorp/terraform-plugin-go v0.28.0/go.mod h1:FDa2Bb3uumkTGSkTFpWSOwWJDwA7bf3vdP3ltLDTH6o= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= diff --git a/main.go b/main.go index 74d7e3f9..24939b79 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "net/http" "github.com/cloudamqp/terraform-provider-cloudamqp/cloudamqp" + "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov5/tf5server" "github.com/hashicorp/terraform-plugin-mux/tf5muxserver" ) @@ -15,7 +16,10 @@ var version string func main() { ctx := context.Background() - muxServer, err := tf5muxserver.NewMuxServer(ctx, cloudamqp.Provider(version, http.DefaultClient).GRPCProvider) + muxServer, err := tf5muxserver.NewMuxServer( + ctx, cloudamqp.Provider(version, http.DefaultClient).GRPCProvider, + providerserver.NewProtocol5(cloudamqp.New(version, http.DefaultClient)), + ) if err != nil { log.Fatal(err) From 58054ce4d5afd2909beea7787109e9cb3491009f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Sacrist=C3=A1n=20Izcue?= Date: Wed, 29 May 2024 01:04:06 +0200 Subject: [PATCH 3/3] chore(cloudamqp_integration_aws_eventbridge): Migrate towards terraform plugin framework This is the first resource to move towards the new system and should serve as a template for all others. The reason to choose this one as the first is because it is the smallest file that still has tests to prove everything still works as before. --- cloudamqp/provider.go | 53 ++-- .../resource_cloudamqp_aws_eventbridge.go | 274 +++++++++++------- 2 files changed, 204 insertions(+), 123 deletions(-) diff --git a/cloudamqp/provider.go b/cloudamqp/provider.go index d4a29be4..81f2a103 100644 --- a/cloudamqp/provider.go +++ b/cloudamqp/provider.go @@ -100,7 +100,11 @@ func (p *cloudamqpProvider) DataSources(_ context.Context) []func() datasource.D } func (p *cloudamqpProvider) Resources(_ context.Context) []func() resource.Resource { - return []func() resource.Resource{} + return []func() resource.Resource{ + func() resource.Resource { + return &awsEventBridgeResource{} + }, + } } func New(version string, client *http.Client) provider.Provider { @@ -148,30 +152,29 @@ func Provider(v string, client *http.Client) *schemaSdk.Provider { "cloudamqp_vpc_info": dataSourceVpcInfo(), }, ResourcesMap: map[string]*schemaSdk.Resource{ - "cloudamqp_account_action": resourceAccountAction(), - "cloudamqp_alarm": resourceAlarm(), - "cloudamqp_custom_domain": resourceCustomDomain(), - "cloudamqp_extra_disk_size": resourceExtraDiskSize(), - "cloudamqp_instance": resourceInstance(), - "cloudamqp_integration_aws_eventbridge": resourceAwsEventBridge(), - "cloudamqp_integration_log": resourceIntegrationLog(), - "cloudamqp_integration_metric": resourceIntegrationMetric(), - "cloudamqp_maintenance_window": resourceMaintenanceWindow(), - "cloudamqp_node_actions": resourceNodeAction(), - "cloudamqp_notification": resourceNotification(), - "cloudamqp_plugin_community": resourcePluginCommunity(), - "cloudamqp_plugin": resourcePlugin(), - "cloudamqp_privatelink_aws": resourcePrivateLinkAws(), - "cloudamqp_privatelink_azure": resourcePrivateLinkAzure(), - "cloudamqp_rabbitmq_configuration": resourceRabbitMqConfiguration(), - "cloudamqp_security_firewall": resourceSecurityFirewall(), - "cloudamqp_upgrade_rabbitmq": resourceUpgradeRabbitMQ(), - "cloudamqp_upgrade_lavinmq": resourceUpgradeLavinMQ(), - "cloudamqp_vpc_connect": resourceVpcConnect(), - "cloudamqp_vpc_gcp_peering": resourceVpcGcpPeering(), - "cloudamqp_vpc_peering": resourceVpcPeering(), - "cloudamqp_vpc": resourceVpc(), - "cloudamqp_webhook": resourceWebhook(), + "cloudamqp_account_action": resourceAccountAction(), + "cloudamqp_alarm": resourceAlarm(), + "cloudamqp_custom_domain": resourceCustomDomain(), + "cloudamqp_extra_disk_size": resourceExtraDiskSize(), + "cloudamqp_instance": resourceInstance(), + "cloudamqp_integration_log": resourceIntegrationLog(), + "cloudamqp_integration_metric": resourceIntegrationMetric(), + "cloudamqp_maintenance_window": resourceMaintenanceWindow(), + "cloudamqp_node_actions": resourceNodeAction(), + "cloudamqp_notification": resourceNotification(), + "cloudamqp_plugin_community": resourcePluginCommunity(), + "cloudamqp_plugin": resourcePlugin(), + "cloudamqp_privatelink_aws": resourcePrivateLinkAws(), + "cloudamqp_privatelink_azure": resourcePrivateLinkAzure(), + "cloudamqp_rabbitmq_configuration": resourceRabbitMqConfiguration(), + "cloudamqp_security_firewall": resourceSecurityFirewall(), + "cloudamqp_upgrade_rabbitmq": resourceUpgradeRabbitMQ(), + "cloudamqp_upgrade_lavinmq": resourceUpgradeLavinMQ(), + "cloudamqp_vpc_connect": resourceVpcConnect(), + "cloudamqp_vpc_gcp_peering": resourceVpcGcpPeering(), + "cloudamqp_vpc_peering": resourceVpcPeering(), + "cloudamqp_vpc": resourceVpc(), + "cloudamqp_webhook": resourceWebhook(), }, ConfigureContextFunc: configureClient(client), } diff --git a/cloudamqp/resource_cloudamqp_aws_eventbridge.go b/cloudamqp/resource_cloudamqp_aws_eventbridge.go index 14b1b5cb..aa276070 100644 --- a/cloudamqp/resource_cloudamqp_aws_eventbridge.go +++ b/cloudamqp/resource_cloudamqp_aws_eventbridge.go @@ -2,63 +2,120 @@ package cloudamqp import ( "context" + "encoding/json" "fmt" + "log" "strconv" "strings" "github.com/cloudamqp/terraform-provider-cloudamqp/api" - "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" ) -func resourceAwsEventBridge() *schema.Resource { - return &schema.Resource{ - CreateContext: resourceAwsEventBridgeCreate, - ReadContext: resourceAwsEventBridgeRead, - DeleteContext: resourceAwsEventBridgeDelete, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - Schema: map[string]*schema.Schema{ - "instance_id": { - Type: schema.TypeInt, - ForceNew: true, +type awsEventBridgeResource struct { + client *api.API +} + +type awsEventBridgeResourceModel struct { + Id types.String `tfsdk:"id"` + InstanceID types.Int64 `tfsdk:"instance_id"` + AwsAccountId types.String `tfsdk:"aws_account_id"` + AwsRegion types.String `tfsdk:"aws_region"` + Vhost types.String `tfsdk:"vhost"` + QueueName types.String `tfsdk:"queue"` + WithHeaders types.Bool `tfsdk:"with_headers"` + Status types.String `tfsdk:"status"` +} + +type awsEventBridgeResourceApiModel struct { + AwsAccountId string `json:"aws_account_id"` + AwsRegion string `json:"aws_region"` + Vhost string `json:"vhost"` + QueueName string `json:"queue"` + WithHeaders bool `json:"with_headers"` +} + +func (r *awsEventBridgeResource) Configure(ctx context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { + // Always perform a nil check when handling ProviderData because Terraform + // sets that data after it calls the ConfigureProvider RPC. + if request.ProviderData == nil { + return + } + + client, ok := request.ProviderData.(*api.API) + + if !ok { + response.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *api.API, got: %T. Please report this issue to the provider developers.", request.ProviderData), + ) + + return + } + + r.client = client +} + +func (r *awsEventBridgeResource) Metadata(ctx context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "cloudamqp_integration_aws_eventbridge" +} + +func (r *awsEventBridgeResource) Schema(ctx context.Context, request resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Computed: true, + }, + "instance_id": schema.Int64Attribute{ Required: true, Description: "Instance identifier", + PlanModifiers: []planmodifier.Int64{ + int64planmodifier.RequiresReplace(), + }, }, - "aws_account_id": { - Type: schema.TypeString, - ForceNew: true, + "aws_account_id": schema.StringAttribute{ Required: true, Description: "The 12 digit AWS Account ID where you want the events to be sent to.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, - "aws_region": { - Type: schema.TypeString, - ForceNew: true, + "aws_region": schema.StringAttribute{ Required: true, Description: "The AWS region where you the events to be sent to. (e.g. us-west-1, us-west-2, ..., etc.)", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, - "vhost": { - Type: schema.TypeString, - ForceNew: true, + "vhost": schema.StringAttribute{ Required: true, Description: "The VHost the queue resides in.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, - "queue": { - Type: schema.TypeString, - ForceNew: true, + "queue": schema.StringAttribute{ Required: true, Description: "A (durable) queue on your RabbitMQ instance.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, - "with_headers": { - Type: schema.TypeBool, - ForceNew: true, + "with_headers": schema.BoolAttribute{ Required: true, Description: "Include message headers in the event data.", + PlanModifiers: []planmodifier.Bool{ + boolplanmodifier.RequiresReplace(), + }, }, - "status": { - Type: schema.TypeString, + "status": schema.StringAttribute{ Computed: true, Description: "Always set to null, unless there is an error starting the EventBridge", }, @@ -66,96 +123,117 @@ func resourceAwsEventBridge() *schema.Resource { } } -func resourceAwsEventBridgeCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - var ( - api = meta.(*api.API) - keys = awsEventbridgeAttributeKeys() - params = make(map[string]any) - instanceID = d.Get("instance_id").(int) - ) +func (r *awsEventBridgeResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var data awsEventBridgeResourceModel + + // Read Terraform plan data into the model + response.Diagnostics.Append(request.Plan.Get(ctx, &data)...) + + if response.Diagnostics.HasError() { + return + } + + apiModel := awsEventBridgeResourceApiModel{ + AwsAccountId: data.AwsAccountId.ValueString(), + AwsRegion: data.AwsRegion.ValueString(), + Vhost: data.Vhost.ValueString(), + QueueName: data.QueueName.ValueString(), + WithHeaders: data.WithHeaders.ValueBool(), + } - for _, k := range keys { - if v := d.Get(k); v != nil { - params[k] = v - } + var params map[string]interface{} + temp, err := json.Marshal(apiModel) + if err != nil { + response.Diagnostics.AddError( + "Unable to Create Resource", + "An unexpected error occurred while creating the resource create request. "+ + "Please report this issue to the provider developers.\n\n"+ + "JSON Error: "+err.Error(), + ) + return } + // TODO: This is totally a hack to get the struct into a map[string]interface{} + // It is very unlikely this will fail after the first one succeeds, so it should be fine to ignore the error + // Maybe after the api is moved into the repo we can improve the interface + _ = json.Unmarshal(temp, ¶ms) - data, err := api.CreateAwsEventBridge(ctx, instanceID, params) + apiResponse, err := r.client.CreateAwsEventBridge(ctx, int(data.InstanceID.ValueInt64()), params) if err != nil { - return diag.FromErr(err) + response.Diagnostics.AddError( + "Failed to Create Resource", + "An error occurred while calling the api to create the surface, verify your permissions are correct.\n\n"+ + "JSON Error: "+err.Error(), + ) + return } - d.SetId(data["id"].(string)) - return diag.Diagnostics{} + data.Id = types.StringValue(apiResponse["id"].(string)) + data.Status = types.StringNull() + + // Save data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &data)...) } -func resourceAwsEventBridgeRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - if strings.Contains(d.Id(), ",") { - tflog.Debug(ctx, fmt.Sprintf("import AWS eventbridge from input identifier: %s", d.Id())) - s := strings.Split(d.Id(), ",") - d.SetId(s[0]) +func (r *awsEventBridgeResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var state awsEventBridgeResourceModel + + // Read Terraform plan data into the model + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + + if strings.Contains(state.Id.ValueString(), ",") { + log.Printf("[DEBUG] cloudamqp::resource::aws-eventbridge::read id contains : %v", state.Id.String()) + s := strings.Split(state.Id.ValueString(), ",") + log.Printf("[DEBUG] cloudamqp::resource::aws-eventbridge::read split ids: %v, %v", s[0], s[1]) + state.Id = types.StringValue(s[0]) instanceID, _ := strconv.Atoi(s[1]) - d.Set("instance_id", instanceID) + state.InstanceID = types.Int64Value(int64(instanceID)) } - if d.Get("instance_id").(int) == 0 { - return diag.Errorf("missing input identifier for import: {resource_id},{instance_id}") + if state.InstanceID.ValueInt64() == 0 { + response.Diagnostics.AddError("Missing instance identifier {resource_id},{instance_id}", "") + return } var ( - api = meta.(*api.API) - instanceID = d.Get("instance_id").(int) + id = state.Id.ValueString() + instanceID = int(state.InstanceID.ValueInt64()) ) - data, err := api.ReadAwsEventBridge(ctx, instanceID, d.Id()) + log.Printf("[DEBUG] cloudamqp::resource::aws-eventbridge::read ID: %v, instanceID %v", id, instanceID) + data, err := r.client.ReadAwsEventBridge(ctx, instanceID, id) if err != nil { - return diag.FromErr(err) + response.Diagnostics.AddError("Something went wrong while reading the aws event bridge", fmt.Sprintf("%v", err)) + return } - for k, v := range data { - if validateAwsEventBridgeSchemaAttribute(k) { - if v == nil { - continue - } - if err = d.Set(k, v); err != nil { - return diag.Errorf("error setting %s for resource %s: %s", k, d.Id(), err) - } - } - } + state.AwsAccountId = types.StringValue(data["aws_account_id"].(string)) + state.AwsRegion = types.StringValue(data["aws_region"].(string)) + state.Vhost = types.StringValue(data["vhost"].(string)) + state.QueueName = types.StringValue(data["queue"].(string)) + state.WithHeaders = types.BoolValue(data["with_headers"].(bool)) - return diag.Diagnostics{} + // Save data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &state)...) } -func resourceAwsEventBridgeDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { - var ( - api = meta.(*api.API) - instanceID = d.Get("instance_id").(int) - ) - - if err := api.DeleteAwsEventBridge(ctx, instanceID, d.Id()); err != nil { - return diag.FromErr(err) - } - return diag.Diagnostics{} +func (r *awsEventBridgeResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + // This resource does not implement the Update function } -func awsEventbridgeAttributeKeys() []string { - return []string{ - "aws_account_id", - "aws_region", - "vhost", - "queue", - "with_headers", +func (r *awsEventBridgeResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var data awsEventBridgeResourceModel + + // Read Terraform plan data into the model + response.Diagnostics.Append(request.State.Get(ctx, &data)...) + var id = data.Id.ValueString() + err := r.client.DeleteAwsEventBridge(ctx, int(data.InstanceID.ValueInt64()), id) + + if err != nil { + response.Diagnostics.AddError("An error occurred while deleting cloudamqp_integration_aws_eventbridge", + fmt.Sprintf("Error deleting Cloudamqp event bridge %s: %s", id, err), + ) } } -func validateAwsEventBridgeSchemaAttribute(key string) bool { - switch key { - case "aws_account_id", - "aws_region", - "vhost", - "queue", - "with_headers", - "status": - return true - } - return false +func (r *awsEventBridgeResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) }