From 98437042828e3fd27a170c9394104a745ceda7cc Mon Sep 17 00:00:00 2001
From: Debaditya Ray <65864761+Dray56@users.noreply.github.com>
Date: Tue, 5 Nov 2024 07:38:51 +0530
Subject: [PATCH] Added service_route_bindings datasource (#55)
---
docs/data-sources/service_route_bindings.md | 63 +++
.../data-source.tf | 7 +
.../datasource_service_route_bindings.go | 138 +++++++
.../datasource_service_route_bindings_test.go | 94 +++++
.../datasource_service_route_bindings.yaml | 375 ++++++++++++++++++
...source_service_route_bindings_invalid.yaml | 127 ++++++
internal/provider/provider.go | 1 +
internal/provider/provider_test.go | 1 +
.../provider/types_service_route_binding.go | 37 ++
migration-guide/Readme.md | 1 +
10 files changed, 844 insertions(+)
create mode 100644 docs/data-sources/service_route_bindings.md
create mode 100644 examples/data-sources/cloudfoundry_service_route_bindings/data-source.tf
create mode 100644 internal/provider/datasource_service_route_bindings.go
create mode 100644 internal/provider/datasource_service_route_bindings_test.go
create mode 100644 internal/provider/fixtures/datasource_service_route_bindings.yaml
create mode 100644 internal/provider/fixtures/datasource_service_route_bindings_invalid.yaml
diff --git a/docs/data-sources/service_route_bindings.md b/docs/data-sources/service_route_bindings.md
new file mode 100644
index 0000000..f508179
--- /dev/null
+++ b/docs/data-sources/service_route_bindings.md
@@ -0,0 +1,63 @@
+---
+page_title: "cloudfoundry_service_route_bindings Data Source - terraform-provider-cloudfoundry"
+subcategory: ""
+description: |-
+ Gets information on Service Route Bindings the user has access to.
+---
+
+# cloudfoundry_service_route_bindings (Data Source)
+
+Gets information on Service Route Bindings the user has access to.
+
+## Example Usage
+
+```terraform
+data "cloudfoundry_service_route_bindings" "rbs" {
+ service_instance = "ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"
+}
+
+output "bindings" {
+ value = data.cloudfoundry_service_route_bindings.rbs
+}
+```
+
+
+## Schema
+
+### Optional
+
+- `route` (String) The GUID of the route to filter by
+- `service_instance` (String) The GUID of the service instance to filter by
+
+### Read-Only
+
+- `route_bindings` (Attributes List) The list of route bindings for the given service instance. (see [below for nested schema](#nestedatt--route_bindings))
+
+
+### Nested Schema for `route_bindings`
+
+Optional:
+
+- `annotations` (Map of String) The annotations associated with Cloud Foundry resources. Add as described [here](https://docs.cloudfoundry.org/adminguide/metadata.html#-view-metadata-for-an-object).
+- `labels` (Map of String) The labels associated with Cloud Foundry resources. Add as described [here](https://docs.cloudfoundry.org/adminguide/metadata.html#-view-metadata-for-an-object).
+
+Read-Only:
+
+- `created_at` (String) The date and time when the resource was created in [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) format.
+- `id` (String) The GUID of the object.
+- `last_operation` (Attributes) The details of the last operation performed on the resource (see [below for nested schema](#nestedatt--route_bindings--last_operation))
+- `route` (String) The GUID of the route to be bound
+- `route_service_url` (String) The URL for the route service.
+- `service_instance` (String) The service instance that the route is bound to
+- `updated_at` (String) The date and time when the resource was updated in [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) format.
+
+
+### Nested Schema for `route_bindings.last_operation`
+
+Read-Only:
+
+- `created_at` (String) The time at which the last operation was created
+- `description` (String) A description of the last operation
+- `state` (String) The state of the last operation
+- `type` (String) The type of the last operation
+- `updated_at` (String) The time at which the last operation was updated
\ No newline at end of file
diff --git a/examples/data-sources/cloudfoundry_service_route_bindings/data-source.tf b/examples/data-sources/cloudfoundry_service_route_bindings/data-source.tf
new file mode 100644
index 0000000..1c07145
--- /dev/null
+++ b/examples/data-sources/cloudfoundry_service_route_bindings/data-source.tf
@@ -0,0 +1,7 @@
+data "cloudfoundry_service_route_bindings" "rbs" {
+ service_instance = "ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"
+}
+
+output "bindings" {
+ value = data.cloudfoundry_service_route_bindings.rbs
+}
\ No newline at end of file
diff --git a/internal/provider/datasource_service_route_bindings.go b/internal/provider/datasource_service_route_bindings.go
new file mode 100644
index 0000000..53d9b68
--- /dev/null
+++ b/internal/provider/datasource_service_route_bindings.go
@@ -0,0 +1,138 @@
+package provider
+
+import (
+ "context"
+ "fmt"
+
+ cfv3client "github.com/cloudfoundry/go-cfclient/v3/client"
+ "github.com/cloudfoundry/terraform-provider-cloudfoundry/internal/provider/managers"
+ "github.com/hashicorp/terraform-plugin-framework/datasource"
+ "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces.
+var (
+ _ datasource.DataSource = &ServiceRouteBindingsDataSource{}
+ _ datasource.DataSourceWithConfigure = &ServiceRouteBindingsDataSource{}
+)
+
+func NewServiceRouteBindingsDataSource() datasource.DataSource {
+ return &ServiceRouteBindingsDataSource{}
+}
+
+type ServiceRouteBindingsDataSource struct {
+ cfClient *cfv3client.Client
+}
+
+func (d *ServiceRouteBindingsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_service_route_bindings"
+}
+
+func (d *ServiceRouteBindingsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ MarkdownDescription: "Gets information on Service Route Bindings the user has access to.",
+
+ Attributes: map[string]schema.Attribute{
+ "service_instance": schema.StringAttribute{
+ MarkdownDescription: "The GUID of the service instance to filter by",
+ Optional: true,
+ },
+ "route": schema.StringAttribute{
+ MarkdownDescription: "The GUID of the route to filter by",
+ Optional: true,
+ },
+ "route_bindings": schema.ListNestedAttribute{
+ MarkdownDescription: "The list of route bindings for the given service instance.",
+ Computed: true,
+ NestedObject: schema.NestedAttributeObject{
+ Attributes: map[string]schema.Attribute{
+ "service_instance": schema.StringAttribute{
+ MarkdownDescription: "The service instance that the route is bound to",
+ Computed: true,
+ },
+ "route": schema.StringAttribute{
+ MarkdownDescription: "The GUID of the route to be bound",
+ Computed: true,
+ },
+ "route_service_url": schema.StringAttribute{
+ MarkdownDescription: "The URL for the route service.",
+ Computed: true,
+ },
+ "last_operation": lastOperationSchema(),
+ idKey: guidSchema(),
+ labelsKey: resourceLabelsSchema(),
+ annotationsKey: resourceAnnotationsSchema(),
+ createdAtKey: createdAtSchema(),
+ updatedAtKey: updatedAtSchema(),
+ },
+ },
+ },
+ },
+ }
+}
+
+func (d *ServiceRouteBindingsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+ session, ok := req.ProviderData.(*managers.Session)
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Data Source Configure Type",
+ fmt.Sprintf("Expected *managers.Session, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+ return
+ }
+ d.cfClient = session.CFClient
+}
+
+func (d *ServiceRouteBindingsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+
+ var data datasourceserviceRouteBindingsType
+
+ diags := req.Config.Get(ctx, &data)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ getOptions := cfv3client.NewServiceRouteBindingListOptions()
+
+ if !data.ServiceInstance.IsNull() {
+ getOptions.ServiceInstanceGUIDs = cfv3client.Filter{
+ Values: []string{
+ data.ServiceInstance.ValueString(),
+ },
+ }
+ }
+
+ if !data.Route.IsNull() {
+ getOptions.RouteGUIDs = cfv3client.Filter{
+ Values: []string{
+ data.Route.ValueString(),
+ },
+ }
+ }
+
+ svcRouteBindings, err := d.cfClient.ServiceRouteBindings.ListAll(ctx, getOptions)
+ if err != nil {
+ resp.Diagnostics.AddError(
+ "API Error Fetching Service Route Bindings.",
+ fmt.Sprintf("Request failed with %s.", err.Error()),
+ )
+ return
+ }
+
+ if len(svcRouteBindings) == 0 {
+ resp.Diagnostics.AddError(
+ "Unable to find any route bindings in list",
+ "Given input does not have any bindings present",
+ )
+ return
+ }
+
+ data.RouteBindings, diags = mapDataSourceServiceRouteBindingsValuesToType(ctx, svcRouteBindings)
+ resp.Diagnostics.Append(diags...)
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
diff --git a/internal/provider/datasource_service_route_bindings_test.go b/internal/provider/datasource_service_route_bindings_test.go
new file mode 100644
index 0000000..840b62f
--- /dev/null
+++ b/internal/provider/datasource_service_route_bindings_test.go
@@ -0,0 +1,94 @@
+package provider
+
+import (
+ "bytes"
+ "regexp"
+ "testing"
+ "text/template"
+
+ "github.com/hashicorp/terraform-plugin-testing/helper/resource"
+)
+
+type ServiceRouteBindingsModelPtr struct {
+ HclType string
+ HclObjectName string
+ Route *string
+ Routes *string
+ ServiceInstance *string
+}
+
+func hclServiceRouteBindings(sip *ServiceRouteBindingsModelPtr) string {
+ if sip != nil {
+ s := `
+ {{.HclType}} "cloudfoundry_service_route_bindings" {{.HclObjectName}} {
+ {{- if .Route}}
+ route = "{{.Route}}"
+ {{- end -}}
+ {{if .ServiceInstance}}
+ service_instance = "{{.ServiceInstance}}"
+ {{- end }}
+ {{if .Routes}}
+ routes = "{{.Routes}}"
+ {{- end }}
+ }`
+ tmpl, err := template.New("service_route_bindings").Parse(s)
+ if err != nil {
+ panic(err)
+ }
+ buf := new(bytes.Buffer)
+ err = tmpl.Execute(buf, sip)
+ if err != nil {
+ panic(err)
+ }
+ return buf.String()
+ }
+ return sip.HclType + ` "cloudfoundry_service_route_bindings" "` + sip.HclObjectName + ` {}`
+}
+
+func TestServiceRouteBindingsDataSource(t *testing.T) {
+ var (
+ ServiceInstanceGUID = "ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"
+ )
+ t.Parallel()
+ t.Run("happy path - read route bindings", func(t *testing.T) {
+ cfg := getCFHomeConf()
+ dataSourceName := "data.cloudfoundry_service_route_bindings.ds"
+ rec := cfg.SetupVCR(t, "fixtures/datasource_service_route_bindings")
+ defer stopQuietly(rec)
+ resource.Test(t, resource.TestCase{
+ IsUnitTest: true,
+ ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()),
+ Steps: []resource.TestStep{
+ {
+ Config: hclProvider(nil) + hclServiceRouteBindings(&ServiceRouteBindingsModelPtr{
+ HclType: hclObjectDataSource,
+ HclObjectName: "ds",
+ ServiceInstance: &ServiceInstanceGUID,
+ }),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr(dataSourceName, "route_bindings.#", "1"),
+ ),
+ },
+ },
+ })
+ })
+ t.Run("error path - get unavailable route bindings", func(t *testing.T) {
+ cfg := getCFHomeConf()
+ rec := cfg.SetupVCR(t, "fixtures/datasource_service_route_bindings_invalid")
+ defer stopQuietly(rec)
+ resource.UnitTest(t, resource.TestCase{
+ IsUnitTest: true,
+ ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()),
+ Steps: []resource.TestStep{
+ {
+ Config: hclProvider(nil) + hclServiceRouteBindings(&ServiceRouteBindingsModelPtr{
+ HclType: hclObjectDataSource,
+ HclObjectName: "ds",
+ Route: &ServiceInstanceGUID,
+ }),
+ ExpectError: regexp.MustCompile(`Unable to find any route bindings in list`),
+ },
+ },
+ })
+ })
+}
diff --git a/internal/provider/fixtures/datasource_service_route_bindings.yaml b/internal/provider/fixtures/datasource_service_route_bindings.yaml
new file mode 100644
index 0000000..130666e
--- /dev/null
+++ b/internal/provider/fixtures/datasource_service_route_bindings.yaml
@@ -0,0 +1,375 @@
+---
+version: 2
+interactions:
+ - id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 73
+ transfer_encoding: []
+ trailer: {}
+ host: uaa.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: grant_type=refresh_token&refresh_token=717a4fc677bd40218559c2c02ad83787-r
+ form:
+ grant_type:
+ - refresh_token
+ refresh_token:
+ - 717a4fc677bd40218559c2c02ad83787-r
+ headers:
+ Authorization:
+ - Basic Y2Y6
+ Content-Type:
+ - application/x-www-form-urlencoded
+ url: https://uaa.x.x.x.x.com/oauth/token
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: -1
+ uncompressed: false
+ body: '{"access_token":"redacted","token_type":"bearer","id_token":"redacted","refresh_token":"717a4fc677bd40218559c2c02ad83787-r","expires_in":1199,"scope":"cloud_controller.read password.write cloud_controller.write openid uaa.user","jti":"4660f6fc9fce490aa7722c52ae3b055f"}'
+ headers:
+ Cache-Control:
+ - no-store
+ Content-Security-Policy:
+ - script-src 'self'
+ Content-Type:
+ - application/json;charset=UTF-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:44 GMT
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ X-Vcap-Request-Id:
+ - 7361c52b-3e20-4322-79fb-b5d0a76f1e91
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 586.211708ms
+ - id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 0
+ transfer_encoding: []
+ trailer: {}
+ host: api.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: ""
+ form: {}
+ headers:
+ Authorization:
+ - Bearer redacted
+ User-Agent:
+ - Terraform/1.5.7 terraform-provider-cloudfoundry/dev
+ url: https://api.x.x.x.x.com/v3/service_route_bindings?page=1&per_page=50&service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec
+ method: GET
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: 1333
+ uncompressed: false
+ body: '{"pagination":{"total_results":1,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"last":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"next":null,"previous":null},"resources":[{"guid":"6961bc50-a694-4255-a5da-3ce4cdba7e54","route_service_url":"https://nginx-route-service.cfapps.sap.hana.ondemand.com","created_at":"2022-03-30T03:47:03Z","updated_at":"2022-03-30T03:47:03Z","last_operation":{"type":"create","state":"succeeded","description":"","created_at":"2022-03-30T03:47:03Z","updated_at":"2022-03-30T03:47:03Z"},"metadata":{"labels":{},"annotations":{}},"relationships":{"service_instance":{"data":{"guid":"ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"}},"route":{"data":{"guid":"8c7cdbd4-98ef-4e2f-97d1-4704f435022d"}}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings/6961bc50-a694-4255-a5da-3ce4cdba7e54"},"service_instance":{"href":"https://api.x.x.x.x.com/v3/service_instances/ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"route":{"href":"https://api.x.x.x.x.com/v3/routes/8c7cdbd4-98ef-4e2f-97d1-4704f435022d"}}}]}'
+ headers:
+ Content-Length:
+ - "1333"
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:45 GMT
+ Referrer-Policy:
+ - strict-origin-when-cross-origin
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-B3-Spanid:
+ - 72fa298d0ece342e
+ X-B3-Traceid:
+ - 1bea9912cad8466972fa298d0ece342e
+ X-Content-Type-Options:
+ - nosniff
+ X-Download-Options:
+ - noopen
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Permitted-Cross-Domain-Policies:
+ - none
+ X-Ratelimit-Limit:
+ - "20000"
+ X-Ratelimit-Remaining:
+ - "18000"
+ X-Ratelimit-Reset:
+ - "1730368988"
+ X-Runtime:
+ - "0.071994"
+ X-Vcap-Request-Id:
+ - 1bea9912-cad8-4669-72fa-298d0ece342e::b17bb17a-a028-4852-ac25-90725151c621
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 636.135459ms
+ - id: 2
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 73
+ transfer_encoding: []
+ trailer: {}
+ host: uaa.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: grant_type=refresh_token&refresh_token=717a4fc677bd40218559c2c02ad83787-r
+ form:
+ grant_type:
+ - refresh_token
+ refresh_token:
+ - 717a4fc677bd40218559c2c02ad83787-r
+ headers:
+ Authorization:
+ - Basic Y2Y6
+ Content-Type:
+ - application/x-www-form-urlencoded
+ url: https://uaa.x.x.x.x.com/oauth/token
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: -1
+ uncompressed: false
+ body: '{"access_token":"redacted","token_type":"bearer","id_token":"redacted","refresh_token":"717a4fc677bd40218559c2c02ad83787-r","expires_in":1199,"scope":"cloud_controller.read password.write cloud_controller.write openid uaa.user","jti":"b45c55bfb3dd4a2ea005dba0a99956bf"}'
+ headers:
+ Cache-Control:
+ - no-store
+ Content-Security-Policy:
+ - script-src 'self'
+ Content-Type:
+ - application/json;charset=UTF-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:45 GMT
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ X-Vcap-Request-Id:
+ - bc6e0b07-60bb-48a2-68ce-a4e289e6b8f4
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 196.216416ms
+ - id: 3
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 0
+ transfer_encoding: []
+ trailer: {}
+ host: api.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: ""
+ form: {}
+ headers:
+ Authorization:
+ - Bearer redacted
+ User-Agent:
+ - Terraform/1.5.7 terraform-provider-cloudfoundry/dev
+ url: https://api.x.x.x.x.com/v3/service_route_bindings?page=1&per_page=50&service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec
+ method: GET
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: 1333
+ uncompressed: false
+ body: '{"pagination":{"total_results":1,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"last":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"next":null,"previous":null},"resources":[{"guid":"6961bc50-a694-4255-a5da-3ce4cdba7e54","route_service_url":"https://nginx-route-service.cfapps.sap.hana.ondemand.com","created_at":"2022-03-30T03:47:03Z","updated_at":"2022-03-30T03:47:03Z","last_operation":{"type":"create","state":"succeeded","description":"","created_at":"2022-03-30T03:47:03Z","updated_at":"2022-03-30T03:47:03Z"},"metadata":{"labels":{},"annotations":{}},"relationships":{"service_instance":{"data":{"guid":"ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"}},"route":{"data":{"guid":"8c7cdbd4-98ef-4e2f-97d1-4704f435022d"}}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings/6961bc50-a694-4255-a5da-3ce4cdba7e54"},"service_instance":{"href":"https://api.x.x.x.x.com/v3/service_instances/ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"route":{"href":"https://api.x.x.x.x.com/v3/routes/8c7cdbd4-98ef-4e2f-97d1-4704f435022d"}}}]}'
+ headers:
+ Content-Length:
+ - "1333"
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:46 GMT
+ Referrer-Policy:
+ - strict-origin-when-cross-origin
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-B3-Spanid:
+ - 7b5c00b45dd1fd49
+ X-B3-Traceid:
+ - 1dda61292cce44bd7b5c00b45dd1fd49
+ X-Content-Type-Options:
+ - nosniff
+ X-Download-Options:
+ - noopen
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Permitted-Cross-Domain-Policies:
+ - none
+ X-Ratelimit-Limit:
+ - "20000"
+ X-Ratelimit-Remaining:
+ - "18000"
+ X-Ratelimit-Reset:
+ - "1730368988"
+ X-Runtime:
+ - "0.075154"
+ X-Vcap-Request-Id:
+ - 1dda6129-2cce-44bd-7b5c-00b45dd1fd49::0dfea17a-ae6d-4251-a99c-08cfb9429a7f
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 271.719666ms
+ - id: 4
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 73
+ transfer_encoding: []
+ trailer: {}
+ host: uaa.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: grant_type=refresh_token&refresh_token=717a4fc677bd40218559c2c02ad83787-r
+ form:
+ grant_type:
+ - refresh_token
+ refresh_token:
+ - 717a4fc677bd40218559c2c02ad83787-r
+ headers:
+ Authorization:
+ - Basic Y2Y6
+ Content-Type:
+ - application/x-www-form-urlencoded
+ url: https://uaa.x.x.x.x.com/oauth/token
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: -1
+ uncompressed: false
+ body: '{"access_token":"redacted","token_type":"bearer","id_token":"redacted","refresh_token":"717a4fc677bd40218559c2c02ad83787-r","expires_in":1199,"scope":"cloud_controller.read password.write cloud_controller.write openid uaa.user","jti":"93f8c156ab5c4faf9cfa03cb38bfb51d"}'
+ headers:
+ Cache-Control:
+ - no-store
+ Content-Security-Policy:
+ - script-src 'self'
+ Content-Type:
+ - application/json;charset=UTF-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:46 GMT
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ X-Vcap-Request-Id:
+ - 58c0ecd3-9e43-420a-4392-2cce5e5e19e9
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 214.750833ms
+ - id: 5
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 0
+ transfer_encoding: []
+ trailer: {}
+ host: api.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: ""
+ form: {}
+ headers:
+ Authorization:
+ - Bearer redacted
+ User-Agent:
+ - Terraform/1.5.7 terraform-provider-cloudfoundry/dev
+ url: https://api.x.x.x.x.com/v3/service_route_bindings?page=1&per_page=50&service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec
+ method: GET
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: 1333
+ uncompressed: false
+ body: '{"pagination":{"total_results":1,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"last":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026service_instance_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"next":null,"previous":null},"resources":[{"guid":"6961bc50-a694-4255-a5da-3ce4cdba7e54","route_service_url":"https://nginx-route-service.cfapps.sap.hana.ondemand.com","created_at":"2022-03-30T03:47:03Z","updated_at":"2022-03-30T03:47:03Z","last_operation":{"type":"create","state":"succeeded","description":"","created_at":"2022-03-30T03:47:03Z","updated_at":"2022-03-30T03:47:03Z"},"metadata":{"labels":{},"annotations":{}},"relationships":{"service_instance":{"data":{"guid":"ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"}},"route":{"data":{"guid":"8c7cdbd4-98ef-4e2f-97d1-4704f435022d"}}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings/6961bc50-a694-4255-a5da-3ce4cdba7e54"},"service_instance":{"href":"https://api.x.x.x.x.com/v3/service_instances/ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"route":{"href":"https://api.x.x.x.x.com/v3/routes/8c7cdbd4-98ef-4e2f-97d1-4704f435022d"}}}]}'
+ headers:
+ Content-Length:
+ - "1333"
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:46 GMT
+ Referrer-Policy:
+ - strict-origin-when-cross-origin
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-B3-Spanid:
+ - 53db9b7542208165
+ X-B3-Traceid:
+ - 2caaa15ed3f8407353db9b7542208165
+ X-Content-Type-Options:
+ - nosniff
+ X-Download-Options:
+ - noopen
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Permitted-Cross-Domain-Policies:
+ - none
+ X-Ratelimit-Limit:
+ - "20000"
+ X-Ratelimit-Remaining:
+ - "18000"
+ X-Ratelimit-Reset:
+ - "1730368988"
+ X-Runtime:
+ - "0.075181"
+ X-Vcap-Request-Id:
+ - 2caaa15e-d3f8-4073-53db-9b7542208165::8a77828b-43de-4804-8d7c-086cd44a6f11
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 262.409084ms
diff --git a/internal/provider/fixtures/datasource_service_route_bindings_invalid.yaml b/internal/provider/fixtures/datasource_service_route_bindings_invalid.yaml
new file mode 100644
index 0000000..1497239
--- /dev/null
+++ b/internal/provider/fixtures/datasource_service_route_bindings_invalid.yaml
@@ -0,0 +1,127 @@
+---
+version: 2
+interactions:
+ - id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 73
+ transfer_encoding: []
+ trailer: {}
+ host: uaa.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: grant_type=refresh_token&refresh_token=717a4fc677bd40218559c2c02ad83787-r
+ form:
+ grant_type:
+ - refresh_token
+ refresh_token:
+ - 717a4fc677bd40218559c2c02ad83787-r
+ headers:
+ Authorization:
+ - Basic Y2Y6
+ Content-Type:
+ - application/x-www-form-urlencoded
+ url: https://uaa.x.x.x.x.com/oauth/token
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: -1
+ uncompressed: false
+ body: '{"access_token":"redacted","token_type":"bearer","id_token":"redacted","refresh_token":"717a4fc677bd40218559c2c02ad83787-r","expires_in":1199,"scope":"cloud_controller.read password.write cloud_controller.write openid uaa.user","jti":"4c0d0ca92cdc495ba5499b07f603f8ca"}'
+ headers:
+ Cache-Control:
+ - no-store
+ Content-Security-Policy:
+ - script-src 'self'
+ Content-Type:
+ - application/json;charset=UTF-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:46 GMT
+ Pragma:
+ - no-cache
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-Content-Type-Options:
+ - nosniff
+ X-Frame-Options:
+ - DENY
+ X-Vcap-Request-Id:
+ - 1275eeb8-e5dc-485f-628b-e0b97b85e724
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 190.330417ms
+ - id: 1
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 0
+ transfer_encoding: []
+ trailer: {}
+ host: api.x.x.x.x.com
+ remote_addr: ""
+ request_uri: ""
+ body: ""
+ form: {}
+ headers:
+ Authorization:
+ - Bearer redacted
+ User-Agent:
+ - Terraform/1.5.7 terraform-provider-cloudfoundry/dev
+ url: https://api.x.x.x.x.com/v3/service_route_bindings?page=1&per_page=50&route_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec
+ method: GET
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ transfer_encoding: []
+ trailer: {}
+ content_length: 412
+ uncompressed: false
+ body: '{"pagination":{"total_results":0,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026route_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"last":{"href":"https://api.x.x.x.x.com/v3/service_route_bindings?page=1\u0026per_page=50\u0026route_guids=ab65cad9-73fa-4dd4-9c09-87f89b2e77ec"},"next":null,"previous":null},"resources":[]}'
+ headers:
+ Content-Length:
+ - "412"
+ Content-Type:
+ - application/json; charset=utf-8
+ Date:
+ - Thu, 31 Oct 2024 09:47:47 GMT
+ Referrer-Policy:
+ - strict-origin-when-cross-origin
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload;
+ X-B3-Spanid:
+ - 4a32f985954a6157
+ X-B3-Traceid:
+ - 65170c33b40743db4a32f985954a6157
+ X-Content-Type-Options:
+ - nosniff
+ X-Download-Options:
+ - noopen
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Permitted-Cross-Domain-Policies:
+ - none
+ X-Ratelimit-Limit:
+ - "20000"
+ X-Ratelimit-Remaining:
+ - "18000"
+ X-Ratelimit-Reset:
+ - "1730368988"
+ X-Runtime:
+ - "0.065372"
+ X-Vcap-Request-Id:
+ - 65170c33-b407-43db-4a32-f985954a6157::6a357e62-04ee-4f74-8682-8a8e026d1d76
+ X-Xss-Protection:
+ - 1; mode=block
+ status: 200 OK
+ code: 200
+ duration: 251.341167ms
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 8ddf5a0..1e1e9b0 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -344,6 +344,7 @@ func (p *CloudFoundryProvider) DataSources(ctx context.Context) []func() datasou
NewDomainsDataSource,
NewRoutesDataSource,
NewServiceBrokerDataSource,
+ NewServiceRouteBindingsDataSource,
}
}
diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go
index b6b23a3..3808bc7 100644
--- a/internal/provider/provider_test.go
+++ b/internal/provider/provider_test.go
@@ -323,6 +323,7 @@ func TestProvider_HasDataSources(t *testing.T) {
"cloudfoundry_domains",
"cloudfoundry_routes",
"cloudfoundry_service_broker",
+ "cloudfoundry_service_route_bindings",
}
ctx := context.Background()
diff --git a/internal/provider/types_service_route_binding.go b/internal/provider/types_service_route_binding.go
index f550f00..4db59dd 100644
--- a/internal/provider/types_service_route_binding.go
+++ b/internal/provider/types_service_route_binding.go
@@ -24,6 +24,24 @@ type serviceRouteBindingType struct {
LastOperation types.Object `tfsdk:"last_operation"` //LastOperationType
}
+type datasourceserviceRouteBindingType struct {
+ ID types.String `tfsdk:"id"`
+ Route types.String `tfsdk:"route"`
+ RouteServiceURL types.String `tfsdk:"route_service_url"`
+ ServiceInstance types.String `tfsdk:"service_instance"`
+ Labels types.Map `tfsdk:"labels"`
+ Annotations types.Map `tfsdk:"annotations"`
+ CreatedAt types.String `tfsdk:"created_at"`
+ UpdatedAt types.String `tfsdk:"updated_at"`
+ LastOperation types.Object `tfsdk:"last_operation"` //LastOperationType
+}
+
+type datasourceserviceRouteBindingsType struct {
+ ServiceInstance types.String `tfsdk:"service_instance"`
+ Route types.String `tfsdk:"route"`
+ RouteBindings []datasourceserviceRouteBindingType `tfsdk:"route_bindings"`
+}
+
func mapServiceRouteBindingValuesToType(ctx context.Context, value *resource.ServiceRouteBinding) (serviceRouteBindingType, diag.Diagnostics) {
var diags, diagnostics diag.Diagnostics
serviceRouteBinding := serviceRouteBindingType{
@@ -78,3 +96,22 @@ func (plan *serviceRouteBindingType) mapUpdateServiceRouteBindingTypeToValues(ct
return *updateRouteBinding, diagnostics
}
+
+func (a *serviceRouteBindingType) Reduce() datasourceserviceRouteBindingType {
+ var reduced datasourceserviceRouteBindingType
+ copyFields(&reduced, a)
+ return reduced
+}
+
+func mapDataSourceServiceRouteBindingsValuesToType(ctx context.Context, svcRouteBindings []*resource.ServiceRouteBinding) ([]datasourceserviceRouteBindingType, diag.Diagnostics) {
+ var diagnostics diag.Diagnostics
+
+ svcRouteBindingsList := []datasourceserviceRouteBindingType{}
+ for _, svcRouteBinding := range svcRouteBindings {
+ bindingValue, diags := mapServiceRouteBindingValuesToType(ctx, svcRouteBinding)
+ diagnostics.Append(diags...)
+ svcRouteBindingsList = append(svcRouteBindingsList, bindingValue.Reduce())
+ }
+
+ return svcRouteBindingsList, diagnostics
+}
diff --git a/migration-guide/Readme.md b/migration-guide/Readme.md
index ba69c03..f839a63 100644
--- a/migration-guide/Readme.md
+++ b/migration-guide/Readme.md
@@ -205,6 +205,7 @@ The below mentioned dataSources have been newly added in the current provider.
- [Service Broker](../docs/data-sources/service_broker.md)
- [Service Instances](../docs/data-sources/service_instances.md)
- [Service Plans](../docs/data-sources/service_plans.md)
+- [Service Route Bindings](../docs/data-sources/service_route_bindings.md)
- [Space Role](../docs/data-sources/space_role.md)
- [Spaces](../docs/data-sources/spaces.md)
- [Space Roles](../docs/data-sources/space_roles.md)