diff --git a/docs/data-sources/isolation_segment.md b/docs/data-sources/isolation_segment.md new file mode 100644 index 0000000..634a1b3 --- /dev/null +++ b/docs/data-sources/isolation_segment.md @@ -0,0 +1,33 @@ +--- +page_title: "cloudfoundry_isolation_segment Data Source - terraform-provider-cloudfoundry" +subcategory: "" +description: |- + Gets information on a Cloud Foundry Isolation Segment. +--- + +# cloudfoundry_isolation_segment (Data Source) + +Gets information on a Cloud Foundry Isolation Segment. + +## Example Usage + +```terraform +data "cloudfoundry_isolation_segment" "isosegment" { + name = "hifij" +} +``` + + +## Schema + +### Required + +- `name` (String) Name of the isolation segment + +### Read-Only + +- `annotations` (Map of String) The annotations associated with Cloud Foundry resources. +- `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. +- `labels` (Map of String) The labels associated with Cloud Foundry resources. +- `updated_at` (String) The date and time when the resource was updated in [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) format. \ No newline at end of file diff --git a/docs/data-sources/isolation_segment_entitlement.md b/docs/data-sources/isolation_segment_entitlement.md new file mode 100644 index 0000000..605d083 --- /dev/null +++ b/docs/data-sources/isolation_segment_entitlement.md @@ -0,0 +1,29 @@ +--- +page_title: "cloudfoundry_isolation_segment_entitlement Data Source - terraform-provider-cloudfoundry" +subcategory: "" +description: |- + Fetches organizations entitled with a Cloud Foundry Isolation Segment. +--- + +# cloudfoundry_isolation_segment_entitlement (Data Source) + +Fetches organizations entitled with a Cloud Foundry Isolation Segment. + +## Example Usage + +```terraform +data "cloudfoundry_isolation_segment_entitlement" "isosegment" { + segment = "63ae51b9-9073-4409-81b0-3704b8de85dd" +} +``` + + +## Schema + +### Required + +- `segment` (String) GUID of the isolation segment + +### Read-Only + +- `orgs` (Set of String) GUID's of organizations the segment is entitled with. \ No newline at end of file diff --git a/docs/resources/isolation_segment.md b/docs/resources/isolation_segment.md new file mode 100644 index 0000000..f347742 --- /dev/null +++ b/docs/resources/isolation_segment.md @@ -0,0 +1,47 @@ +--- +page_title: "cloudfoundry_isolation_segment Resource - terraform-provider-cloudfoundry" +subcategory: "" +description: |- + Provides an isolation segment resource for Cloud Foundry. +--- + +# cloudfoundry_isolation_segment (Resource) + +Provides an isolation segment resource for Cloud Foundry. + +## Example Usage + +```terraform +resource "cloudfoundry_isolation_segment" "isosegment" { + name = "hifi" + labels = { "purpose" : "testing" } +} +``` + + +## Schema + +### Required + +- `name` (String) Name of the isolation segment + +### 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. +- `updated_at` (String) The date and time when the resource was updated in [RFC3339](https://www.ietf.org/rfc/rfc3339.txt) format. + +## Import + +Import is supported using the following syntax: + +```terraform +# terraform import cloudfoundry_isolation_segment. + +terraform import cloudfoundry_isolation_segment.my_segment e3cef997-9ba5-4cb4-b25b-c79faa81a33f +``` \ No newline at end of file diff --git a/docs/resources/isolation_segment_entitlement.md b/docs/resources/isolation_segment_entitlement.md new file mode 100644 index 0000000..8e371a4 --- /dev/null +++ b/docs/resources/isolation_segment_entitlement.md @@ -0,0 +1,33 @@ +--- +page_title: "cloudfoundry_isolation_segment_entitlement Resource - terraform-provider-cloudfoundry" +subcategory: "" +description: |- + Provides a Cloud Foundry resource for entitling and revoking isolation segment from organizations. Only entitles and revokes the segment from the orgs managed through this resource and does not touch existing entitlements. Revoking isolation segment entitlement from an organization will fail if it is the default for the organization. On deleting the resource, the isolation segment will be revoked from the mentioned orgs. +--- + +# cloudfoundry_isolation_segment_entitlement (Resource) + +Provides a Cloud Foundry resource for entitling and revoking isolation segment from organizations. Only entitles and revokes the segment from the orgs managed through this resource and does not touch existing entitlements. Revoking isolation segment entitlement from an organization will fail if it is the default for the organization. On deleting the resource, the isolation segment will be revoked from the mentioned orgs. + +## Example Usage + +```terraform +resource "cloudfoundry_isolation_segment_entitlement" "isosegment" { + segment = "63ae51b9-9073-4409-81b0-3704b8de85dd" + orgs = ["c8e454cc-7a24-4d71-b146-51d69538acfb"] + default = true +} +``` + + +## Schema + +### Required + +- `orgs` (Set of String) GUID's of organizations to entitle the segment to. +- `segment` (String) GUID of the isolation segment + +### Optional + +- `default` (Boolean) Set isolation segment as default for the organizations. Defaults to false. + diff --git a/docs/resources/org.md b/docs/resources/org.md index 09c4d74..61e2904 100644 --- a/docs/resources/org.md +++ b/docs/resources/org.md @@ -18,7 +18,7 @@ Creates a Cloud Foundry Organization ```terraform resource "cloudfoundry_org" "org" { - name = "tf-test" + name = "tf-test-iso" suspended = false labels = { env = "test" diff --git a/docs/resources/space.md b/docs/resources/space.md index 817366e..fdbdbce 100644 --- a/docs/resources/space.md +++ b/docs/resources/space.md @@ -14,7 +14,7 @@ Provides a Cloud Foundry resource for managing Cloud Foundry spaces within organ ```terraform resource "cloudfoundry_space" "space" { name = "space" - org = "ca721b24-e24d-4171-83e1-1ef6bd836b38" + org = "c8e454cc-7a24-4d71-b146-51d69538acfb" allow_ssh = "true" labels = { test : "pass", purpose : "prod" } } diff --git a/examples/data-sources/cloudfoundry_isolation_segment/data-source.tf b/examples/data-sources/cloudfoundry_isolation_segment/data-source.tf new file mode 100644 index 0000000..703a1c5 --- /dev/null +++ b/examples/data-sources/cloudfoundry_isolation_segment/data-source.tf @@ -0,0 +1,3 @@ +data "cloudfoundry_isolation_segment" "isosegment" { + name = "hifij" +} \ No newline at end of file diff --git a/examples/data-sources/cloudfoundry_isolation_segment_entitlement/data-source.tf b/examples/data-sources/cloudfoundry_isolation_segment_entitlement/data-source.tf new file mode 100644 index 0000000..251f87a --- /dev/null +++ b/examples/data-sources/cloudfoundry_isolation_segment_entitlement/data-source.tf @@ -0,0 +1,3 @@ +data "cloudfoundry_isolation_segment_entitlement" "isosegment" { + segment = "63ae51b9-9073-4409-81b0-3704b8de85dd" +} \ No newline at end of file diff --git a/examples/resources/cloudfoundry_isolation_segment/import.sh b/examples/resources/cloudfoundry_isolation_segment/import.sh new file mode 100644 index 0000000..6737740 --- /dev/null +++ b/examples/resources/cloudfoundry_isolation_segment/import.sh @@ -0,0 +1,3 @@ +# terraform import cloudfoundry_isolation_segment. + +terraform import cloudfoundry_isolation_segment.my_segment e3cef997-9ba5-4cb4-b25b-c79faa81a33f \ No newline at end of file diff --git a/examples/resources/cloudfoundry_isolation_segment/resource.tf b/examples/resources/cloudfoundry_isolation_segment/resource.tf new file mode 100644 index 0000000..5067ecc --- /dev/null +++ b/examples/resources/cloudfoundry_isolation_segment/resource.tf @@ -0,0 +1,4 @@ +resource "cloudfoundry_isolation_segment" "isosegment" { + name = "hifi" + labels = { "purpose" : "testing" } +} \ No newline at end of file diff --git a/examples/resources/cloudfoundry_isolation_segment_entitlement/resource.tf b/examples/resources/cloudfoundry_isolation_segment_entitlement/resource.tf new file mode 100644 index 0000000..f5aa4fc --- /dev/null +++ b/examples/resources/cloudfoundry_isolation_segment_entitlement/resource.tf @@ -0,0 +1,5 @@ +resource "cloudfoundry_isolation_segment_entitlement" "isosegment" { + segment = "63ae51b9-9073-4409-81b0-3704b8de85dd" + orgs = ["c8e454cc-7a24-4d71-b146-51d69538acfb"] + default = true +} \ No newline at end of file diff --git a/examples/resources/cloudfoundry_org/resource.tf b/examples/resources/cloudfoundry_org/resource.tf index f72031f..e2cc77c 100644 --- a/examples/resources/cloudfoundry_org/resource.tf +++ b/examples/resources/cloudfoundry_org/resource.tf @@ -1,5 +1,5 @@ resource "cloudfoundry_org" "org" { - name = "tf-test" + name = "tf-test-iso" suspended = false labels = { env = "test" diff --git a/examples/resources/cloudfoundry_space/resource.tf b/examples/resources/cloudfoundry_space/resource.tf index ebb99e8..905bc6d 100644 --- a/examples/resources/cloudfoundry_space/resource.tf +++ b/examples/resources/cloudfoundry_space/resource.tf @@ -1,6 +1,6 @@ resource "cloudfoundry_space" "space" { name = "space" - org = "ca721b24-e24d-4171-83e1-1ef6bd836b38" + org = "c8e454cc-7a24-4d71-b146-51d69538acfb" allow_ssh = "true" labels = { test : "pass", purpose : "prod" } } diff --git a/internal/provider/datasource_isolation_segment.go b/internal/provider/datasource_isolation_segment.go new file mode 100644 index 0000000..1467871 --- /dev/null +++ b/internal/provider/datasource_isolation_segment.go @@ -0,0 +1,106 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/SAP/terraform-provider-cloudfoundry/internal/provider/managers" + cfv3client "github.com/cloudfoundry/go-cfclient/v3/client" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces. +var ( + _ datasource.DataSource = &IsolationSegmentDataSource{} + _ datasource.DataSourceWithConfigure = &IsolationSegmentDataSource{} +) + +func NewIsolationSegmentDataSource() datasource.DataSource { + return &IsolationSegmentDataSource{} +} + +type IsolationSegmentDataSource struct { + cfClient *cfv3client.Client +} + +func (d *IsolationSegmentDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_isolation_segment" +} + +func (d *IsolationSegmentDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Gets information on a Cloud Foundry Isolation Segment.", + + Attributes: map[string]schema.Attribute{ + idKey: guidSchema(), + "name": schema.StringAttribute{ + MarkdownDescription: "Name of the isolation segment", + Required: true, + }, + labelsKey: datasourceLabelsSchema(), + annotationsKey: datasourceAnnotationsSchema(), + createdAtKey: createdAtSchema(), + updatedAtKey: updatedAtSchema(), + }, + } +} + +func (d *IsolationSegmentDataSource) 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 *IsolationSegmentDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + + var data IsolationSegmentType + + diags := req.Config.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + getOptions := cfv3client.IsolationSegmentListOptions{ + Names: cfv3client.Filter{ + Values: []string{ + data.Name.ValueString(), + }, + }, + } + + isolationSegments, err := d.cfClient.IsolationSegments.ListAll(ctx, &getOptions) + if err != nil { + resp.Diagnostics.AddError( + "API Error Fetching Isolation Segment.", + fmt.Sprintf("Request failed with %s.", err.Error()), + ) + return + } + + if len(isolationSegments) == 0 { + resp.Diagnostics.AddError( + "Unable to find any Isolation Segment.", + fmt.Sprintf("Given name %s not in the list of isolation segments.", data.Name.ValueString()), + ) + return + } + + data, diags = mapIsolationSegmentValuesToType(ctx, isolationSegments[0]) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "read an isolation segment data source") + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/datasource_isolation_segment_entitlement.go b/internal/provider/datasource_isolation_segment_entitlement.go new file mode 100644 index 0000000..12d2794 --- /dev/null +++ b/internal/provider/datasource_isolation_segment_entitlement.go @@ -0,0 +1,95 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/SAP/terraform-provider-cloudfoundry/internal/provider/managers" + "github.com/SAP/terraform-provider-cloudfoundry/internal/validation" + cfv3client "github.com/cloudfoundry/go-cfclient/v3/client" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces. +var ( + _ datasource.DataSource = &IsolationSegmentEntitlementDataSource{} + _ datasource.DataSourceWithConfigure = &IsolationSegmentEntitlementDataSource{} +) + +func NewIsolationSegmentEntitlementDataSource() datasource.DataSource { + return &IsolationSegmentEntitlementDataSource{} +} + +type IsolationSegmentEntitlementDataSource struct { + cfClient *cfv3client.Client +} + +func (d *IsolationSegmentEntitlementDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_isolation_segment_entitlement" +} + +func (d *IsolationSegmentEntitlementDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Fetches organizations entitled with a Cloud Foundry Isolation Segment.", + + Attributes: map[string]schema.Attribute{ + "segment": schema.StringAttribute{ + MarkdownDescription: "GUID of the isolation segment", + Required: true, + Validators: []validator.String{ + validation.ValidUUID(), + }, + }, + "orgs": schema.SetAttribute{ + MarkdownDescription: "GUID's of organizations the segment is entitled with.", + Computed: true, + ElementType: types.StringType, + }, + }, + } +} + +func (d *IsolationSegmentEntitlementDataSource) 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 *IsolationSegmentEntitlementDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + + var data IsolationSegmentEntitlementDataSourceType + diags := req.Config.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + orgs, err := d.cfClient.IsolationSegments.ListOrganizationRelationships(ctx, data.Segment.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "API Error Fetching Entitled Organizations", + "Error : "+err.Error(), + ) + return + } + + data.Orgs, diags = types.SetValueFrom(ctx, types.StringType, orgs) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "read an isolation segment entitlement data source") + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/datasource_isolation_segment_entitlement_test.go b/internal/provider/datasource_isolation_segment_entitlement_test.go new file mode 100644 index 0000000..34e8b03 --- /dev/null +++ b/internal/provider/datasource_isolation_segment_entitlement_test.go @@ -0,0 +1,60 @@ +package provider + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestIsolationSegmentEntitlementDataSource_Configure(t *testing.T) { + var ( + // in staging + resourceName = "data.cloudfoundry_isolation_segment_entitlement.ds" + segmentGUID = "63ae51b9-9073-4409-81b0-3704b8de85dd" + ) + t.Parallel() + t.Run("happy path - get available orgs entitled with isolation segment", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/datasource_isolation_segment_entilement") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegmentEntitlement(&IsolationSegmentEntitlementModelPtr{ + HclType: hclObjectDataSource, + HclObjectName: "ds", + Segment: &segmentGUID, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "segment", segmentGUID), + resource.TestCheckResourceAttr(resourceName, "orgs.#", "1"), + ), + }, + }, + }) + }) + t.Run("error path - get orgs entitled for invalid isolation segment", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/datasource_isolation_segment_entilement_invalid") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegmentEntitlement(&IsolationSegmentEntitlementModelPtr{ + HclType: hclObjectDataSource, + HclObjectName: "ds", + Segment: &invalidOrgGUID, + }), + ExpectError: regexp.MustCompile(`API Error Fetching Entitled Organizations`), + }, + }, + }) + }) +} diff --git a/internal/provider/datasource_isolation_segment_test.go b/internal/provider/datasource_isolation_segment_test.go new file mode 100644 index 0000000..e3d7272 --- /dev/null +++ b/internal/provider/datasource_isolation_segment_test.go @@ -0,0 +1,63 @@ +package provider + +import ( + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestIsolationSegmentDataSource_Configure(t *testing.T) { + var ( + // in staging + isolationSegmentName = "hifi" + resourceName = "data.cloudfoundry_isolation_segment.ds" + ) + t.Parallel() + t.Run("get available datasource isolation segment", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/datasource_isolation_segment") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectDataSource, + HclObjectName: "ds", + Name: &isolationSegmentName, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr(resourceName, "id", regexpValidUUID), + resource.TestCheckResourceAttr(resourceName, "name", isolationSegmentName), + resource.TestMatchResourceAttr(resourceName, "created_at", regexpValidRFC3999Format), + resource.TestMatchResourceAttr(resourceName, "updated_at", regexpValidRFC3999Format), + resource.TestCheckResourceAttr(resourceName, "labels.purpose", "testing"), + ), + }, + }, + }) + }) + t.Run("error path - get unavailable isolation segment", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/datasource_isolation_segment_invalid") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectDataSource, + HclObjectName: "ds", + Name: strtostrptr("testunavailable"), + }), + ExpectError: regexp.MustCompile(`Unable to find any Isolation Segment`), + }, + }, + }) + }) +} diff --git a/internal/provider/fixtures/datasource_isolation_segment.yaml b/internal/provider/fixtures/datasource_isolation_segment.yaml new file mode 100644 index 0000000..f9c4f74 --- /dev/null +++ b/internal/provider/fixtures/datasource_isolation_segment.yaml @@ -0,0 +1,186 @@ +--- +version: 2 +interactions: + - id: 0 + 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/isolation_segments?names=hifi + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 835 + uncompressed: false + body: '{"pagination":{"total_results":1,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=hifi\u0026page=1\u0026per_page=50"},"last":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=hifi\u0026page=1\u0026per_page=50"},"next":null,"previous":null},"resources":[{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd","created_at":"2024-06-11T04:33:43Z","updated_at":"2024-06-12T10:15:04Z","name":"hifi","metadata":{"labels":{"purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}]}' + headers: + Content-Length: + - "835" + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 13 Jun 2024 06:46:58 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 5221a1bc2fe99532 + X-B3-Traceid: + - 270e57982c824f185221a1bc2fe99532 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004206" + X-Vcap-Request-Id: + - 270e5798-2c82-4f18-5221-a1bc2fe99532::3c65beac-af46-484a-bb16-30a961a95046 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 523.961541ms + - 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/isolation_segments?names=hifi + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 835 + uncompressed: false + body: '{"pagination":{"total_results":1,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=hifi\u0026page=1\u0026per_page=50"},"last":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=hifi\u0026page=1\u0026per_page=50"},"next":null,"previous":null},"resources":[{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd","created_at":"2024-06-11T04:33:43Z","updated_at":"2024-06-12T10:15:04Z","name":"hifi","metadata":{"labels":{"purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}]}' + headers: + Content-Length: + - "835" + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 13 Jun 2024 06:46:58 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 69e0f5acd65af5e0 + X-B3-Traceid: + - cded50c8287842bc69e0f5acd65af5e0 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.008324" + X-Vcap-Request-Id: + - cded50c8-2878-42bc-69e0-f5acd65af5e0::cceb3944-8efa-4862-8984-59924995da80 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 183.918458ms + - id: 2 + 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/isolation_segments?names=hifi + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 835 + uncompressed: false + body: '{"pagination":{"total_results":1,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=hifi\u0026page=1\u0026per_page=50"},"last":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=hifi\u0026page=1\u0026per_page=50"},"next":null,"previous":null},"resources":[{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd","created_at":"2024-06-11T04:33:43Z","updated_at":"2024-06-12T10:15:04Z","name":"hifi","metadata":{"labels":{"purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}]}' + headers: + Content-Length: + - "835" + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 13 Jun 2024 06:46:58 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 45868f555b4ac0f9 + X-B3-Traceid: + - 1cecc465fabe429845868f555b4ac0f9 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004300" + X-Vcap-Request-Id: + - 1cecc465-fabe-4298-4586-8f555b4ac0f9::a9903b9c-d455-41a4-8813-09977cf49188 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 174.293958ms diff --git a/internal/provider/fixtures/datasource_isolation_segment_entilement.yaml b/internal/provider/fixtures/datasource_isolation_segment_entilement.yaml new file mode 100644 index 0000000..366625a --- /dev/null +++ b/internal/provider/fixtures/datasource_isolation_segment_entilement.yaml @@ -0,0 +1,186 @@ +--- +version: 2 +interactions: + - id: 0 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 367 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "367" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:32 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 5ce4406d0aeb6ce5 + X-B3-Traceid: + - a7ad31604cb140dd5ce4406d0aeb6ce5 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004034" + X-Vcap-Request-Id: + - a7ad3160-4cb1-40dd-5ce4-406d0aeb6ce5::dd433730-aa6b-4559-923e-53570b3ed183 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 527.758041ms + - 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 367 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "367" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:32 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 79af498d9442d8c5 + X-B3-Traceid: + - b9e95b46712f483879af498d9442d8c5 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.002568" + X-Vcap-Request-Id: + - b9e95b46-712f-4838-79af-498d9442d8c5::623fb832-328c-40b6-acca-6bbd1fddd256 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 172.289458ms + - id: 2 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 367 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "367" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:32 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 598048e7be0b0d32 + X-B3-Traceid: + - c4027359e1594af7598048e7be0b0d32 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.002795" + X-Vcap-Request-Id: + - c4027359-e159-4af7-5980-48e7be0b0d32::2845d81e-a9e9-4d89-91f1-b34a57c51b13 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 168.782ms diff --git a/internal/provider/fixtures/datasource_isolation_segment_entilement_invalid.yaml b/internal/provider/fixtures/datasource_isolation_segment_entilement_invalid.yaml new file mode 100644 index 0000000..264721e --- /dev/null +++ b/internal/provider/fixtures/datasource_isolation_segment_entilement_invalid.yaml @@ -0,0 +1,64 @@ +--- +version: 2 +interactions: + - id: 0 + 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/isolation_segments/40b73419-5e01-4be0-baea-932d46cea45b/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 96 + uncompressed: false + body: '{"errors":[{"detail":"Isolation segment not found","title":"CF-ResourceNotFound","code":10010}]}' + headers: + Content-Length: + - "96" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:33 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 75fd4682e87fed09 + X-B3-Traceid: + - e0aa64f7ce644c5f75fd4682e87fed09 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003807" + X-Vcap-Request-Id: + - e0aa64f7-ce64-4c5f-75fd-4682e87fed09::c6f9de40-1e1a-4332-a477-855eaaadabfa + X-Xss-Protection: + - 1; mode=block + status: 404 Not Found + code: 404 + duration: 173.45475ms diff --git a/internal/provider/fixtures/datasource_isolation_segment_invalid.yaml b/internal/provider/fixtures/datasource_isolation_segment_invalid.yaml new file mode 100644 index 0000000..cce7840 --- /dev/null +++ b/internal/provider/fixtures/datasource_isolation_segment_invalid.yaml @@ -0,0 +1,64 @@ +--- +version: 2 +interactions: + - id: 0 + 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/isolation_segments?names=testunavailable + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 376 + uncompressed: false + body: '{"pagination":{"total_results":0,"total_pages":1,"first":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=testunavailable\u0026page=1\u0026per_page=50"},"last":{"href":"https://api.x.x.x.x.com/v3/isolation_segments?names=testunavailable\u0026page=1\u0026per_page=50"},"next":null,"previous":null},"resources":[]}' + headers: + Content-Length: + - "376" + Content-Type: + - application/json; charset=utf-8 + Date: + - Thu, 13 Jun 2024 06:46:59 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 7cca01dac2fd41b2 + X-B3-Traceid: + - 3f845976146d457f7cca01dac2fd41b2 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003287" + X-Vcap-Request-Id: + - 3f845976-146d-457f-7cca-01dac2fd41b2::92bf7b56-480d-46bd-9382-1a9fecd89ddd + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 173.02125ms diff --git a/internal/provider/fixtures/resource_isolation_segment_crud.yaml b/internal/provider/fixtures/resource_isolation_segment_crud.yaml new file mode 100644 index 0000000..5d9c307 --- /dev/null +++ b/internal/provider/fixtures/resource_isolation_segment_crud.yaml @@ -0,0 +1,432 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 101 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"name":"segment","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 503 + uncompressed: false + body: '{"guid":"b59ce779-da52-46f8-9c21-3402b74a67ee","created_at":"2024-06-14T06:44:54Z","updated_at":"2024-06-14T06:44:54Z","name":"segment","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee/organizations"}}}' + headers: + Content-Length: + - "503" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:54 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 75757bdd2efc839f + X-B3-Traceid: + - 58ee181a4487450875757bdd2efc839f + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.024945" + X-Vcap-Request-Id: + - 58ee181a-4487-4508-7575-7bdd2efc839f::53656ad8-3e0a-455d-827c-b7906d894e6a + X-Xss-Protection: + - 1; mode=block + status: 201 Created + code: 201 + duration: 539.1755ms + - 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/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 503 + uncompressed: false + body: '{"guid":"b59ce779-da52-46f8-9c21-3402b74a67ee","created_at":"2024-06-14T06:44:54Z","updated_at":"2024-06-14T06:44:54Z","name":"segment","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee/organizations"}}}' + headers: + Content-Length: + - "503" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:54 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 7b65abc299aae260 + X-B3-Traceid: + - 421ebbfdce3943ba7b65abc299aae260 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.007356" + X-Vcap-Request-Id: + - 421ebbfd-ce39-43ba-7b65-abc299aae260::0d92b1fd-2f2c-4c89-aa6f-6d819480609f + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 170.932334ms + - id: 2 + 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/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 503 + uncompressed: false + body: '{"guid":"b59ce779-da52-46f8-9c21-3402b74a67ee","created_at":"2024-06-14T06:44:54Z","updated_at":"2024-06-14T06:44:54Z","name":"segment","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee/organizations"}}}' + headers: + Content-Length: + - "503" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:55 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 7396b5c6a7541e58 + X-B3-Traceid: + - 19158255ec9f42c77396b5c6a7541e58 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.007569" + X-Vcap-Request-Id: + - 19158255-ec9f-42c7-7396-b5c6a7541e58::bc201668-4414-49cd-ad1d-df0814fd7707 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 174.300417ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 120 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"name":"segment-2","metadata":{"labels":{"landscape":null,"purpose":"production","status":"fine"},"annotations":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 505 + uncompressed: false + body: '{"guid":"b59ce779-da52-46f8-9c21-3402b74a67ee","created_at":"2024-06-14T06:44:54Z","updated_at":"2024-06-14T06:44:55Z","name":"segment-2","metadata":{"labels":{"purpose":"production","status":"fine"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee/organizations"}}}' + headers: + Content-Length: + - "505" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:55 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 75e60bcdf6d335b8 + X-B3-Traceid: + - 2d651124bc24422775e60bcdf6d335b8 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.026175" + X-Vcap-Request-Id: + - 2d651124-bc24-4227-75e6-0bcdf6d335b8::992c30c1-b4cb-4edf-b46e-23e49bad3c6c + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 189.477917ms + - id: 4 + 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/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 505 + uncompressed: false + body: '{"guid":"b59ce779-da52-46f8-9c21-3402b74a67ee","created_at":"2024-06-14T06:44:54Z","updated_at":"2024-06-14T06:44:55Z","name":"segment-2","metadata":{"labels":{"purpose":"production","status":"fine"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee/organizations"}}}' + headers: + Content-Length: + - "505" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:55 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 7e343e4857613c93 + X-B3-Traceid: + - 57483d0cdd3a432f7e343e4857613c93 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004271" + X-Vcap-Request-Id: + - 57483d0c-dd3a-432f-7e34-3e4857613c93::ec89b7c3-638a-4000-b5b4-6cdd0591d015 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 168.709167ms + - 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/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 505 + uncompressed: false + body: '{"guid":"b59ce779-da52-46f8-9c21-3402b74a67ee","created_at":"2024-06-14T06:44:54Z","updated_at":"2024-06-14T06:44:55Z","name":"segment-2","metadata":{"labels":{"purpose":"production","status":"fine"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee/organizations"}}}' + headers: + Content-Length: + - "505" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:55 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 56ab866151f19d91 + X-B3-Traceid: + - 7274073d7bab4add56ab866151f19d91 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004115" + X-Vcap-Request-Id: + - 7274073d-7bab-4add-56ab-866151f19d91::b3a7926a-a895-4acf-a32c-a3c7fec4cb36 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 171.194ms + - id: 6 + 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/isolation_segments/b59ce779-da52-46f8-9c21-3402b74a67ee + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Date: + - Fri, 14 Jun 2024 06:44:56 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 73d2aff2031c8ddd + X-B3-Traceid: + - 422484f5b78c45e173d2aff2031c8ddd + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.017439" + X-Vcap-Request-Id: + - 422484f5-b78c-45e1-73d2-aff2031c8ddd::2600e803-5d81-4b34-b7e6-805f1c25d5d4 + X-Xss-Protection: + - 1; mode=block + status: 204 No Content + code: 204 + duration: 181.7075ms diff --git a/internal/provider/fixtures/resource_isolation_segment_entitlement_crud.yaml b/internal/provider/fixtures/resource_isolation_segment_entitlement_crud.yaml new file mode 100644 index 0000000..bb1b0ae --- /dev/null +++ b/internal/provider/fixtures/resource_isolation_segment_entitlement_crud.yaml @@ -0,0 +1,924 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 107 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":[{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}]} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:44 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 63356664d716f787 + X-B3-Traceid: + - e79100d165e849b563356664d716f787 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.025879" + X-Vcap-Request-Id: + - e79100d1-65e8-49b5-6335-6664d716f787::edc48844-5f8f-4440-8b99-ad4c001edd85 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 570.177833ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 57 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd"}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/organizations/3c6ee045-7791-4d65-a12b-f42ab1b283eb/relationships/default_isolation_segment + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 358 + uncompressed: false + body: '{"data":{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd"},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/organizations/3c6ee045-7791-4d65-a12b-f42ab1b283eb/relationships/default_isolation_segment"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd"}}}' + headers: + Content-Length: + - "358" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:44 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 4dc0c3b7fddabd73 + X-B3-Traceid: + - 2d738703723f4adf4dc0c3b7fddabd73 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.011444" + X-Vcap-Request-Id: + - 2d738703-723f-4adf-4dc0-c3b7fddabd73::fef602d6-5cb4-4bec-9963-5ac3dc674485 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 183.059334ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 57 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd"}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/organizations/db29f4b8-d39e-4f5c-b24d-cb34cde27abf/relationships/default_isolation_segment + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 358 + uncompressed: false + body: '{"data":{"guid":"63ae51b9-9073-4409-81b0-3704b8de85dd"},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/organizations/db29f4b8-d39e-4f5c-b24d-cb34cde27abf/relationships/default_isolation_segment"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd"}}}' + headers: + Content-Length: + - "358" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:44 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 51ee48bf3ad71794 + X-B3-Traceid: + - a7f04799500241f151ee48bf3ad71794 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.021541" + X-Vcap-Request-Id: + - a7f04799-5002-41f1-51ee-48bf3ad71794::82523964-b9cc-4245-8c0b-6ceba54d80ea + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 199.630208ms + - 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:44 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 67f0f12a95e907bf + X-B3-Traceid: + - f9f62979fb694a3a67f0f12a95e907bf + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.005231" + X-Vcap-Request-Id: + - f9f62979-fb69-4a3a-67f0-f12a95e907bf::a55bffa7-b6ee-42c8-84af-3070c6ce9d8f + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 180.628208ms + - id: 4 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:45 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 7a825c816f1ef5f2 + X-B3-Traceid: + - 2147d97b6572421c7a825c816f1ef5f2 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.005018" + X-Vcap-Request-Id: + - 2147d97b-6572-421c-7a82-5c816f1ef5f2::012020e1-2b87-4382-a220-0308c17ae3f7 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 172.769208ms + - 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:45 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 548d070ffe75b212 + X-B3-Traceid: + - f055c80019514788548d070ffe75b212 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.002958" + X-Vcap-Request-Id: + - f055c800-1951-4788-548d-070ffe75b212::f0a185a3-beba-4968-bc07-a29451767c44 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 182.601041ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 23 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":{"guid":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/organizations/3c6ee045-7791-4d65-a12b-f42ab1b283eb/relationships/default_isolation_segment + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 185 + uncompressed: false + body: '{"data":null,"links":{"self":{"href":"https://api.x.x.x.x.com/v3/organizations/3c6ee045-7791-4d65-a12b-f42ab1b283eb/relationships/default_isolation_segment"}}}' + headers: + Content-Length: + - "185" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:45 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 6068d894d4ee2a5f + X-B3-Traceid: + - 0e685928897a4d2f6068d894d4ee2a5f + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.017401" + X-Vcap-Request-Id: + - 0e685928-897a-4d2f-6068-d894d4ee2a5f::3f3d20f9-575b-48e2-9b31-d4835ca5ecc6 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 183.283125ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 23 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":{"guid":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/organizations/db29f4b8-d39e-4f5c-b24d-cb34cde27abf/relationships/default_isolation_segment + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 185 + uncompressed: false + body: '{"data":null,"links":{"self":{"href":"https://api.x.x.x.x.com/v3/organizations/db29f4b8-d39e-4f5c-b24d-cb34cde27abf/relationships/default_isolation_segment"}}}' + headers: + Content-Length: + - "185" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:45 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 558733b7e69840af + X-B3-Traceid: + - fe487800ef4d4485558733b7e69840af + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.020865" + X-Vcap-Request-Id: + - fe487800-ef4d-4485-5587-33b7e69840af::3cd271e0-a7c2-443a-a013-cfd98d3c2fb4 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 190.012792ms + - id: 8 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:46 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 61dc01a77fb9911d + X-B3-Traceid: + - dcb33ca7241444bb61dc01a77fb9911d + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004826" + X-Vcap-Request-Id: + - dcb33ca7-2414-44bb-61dc-01a77fb9911d::00c48900-282b-480f-bd0e-b0ead92d68ae + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 172.048292ms + - id: 9 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"3c6ee045-7791-4d65-a12b-f42ab1b283eb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:46 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 5c828605670290c0 + X-B3-Traceid: + - 390d1300c337423d5c828605670290c0 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003117" + X-Vcap-Request-Id: + - 390d1300-c337-423d-5c82-8605670290c0::4ced5e04-d26a-4467-97a1-43c038652380 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 178.688208ms + - id: 10 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations/3c6ee045-7791-4d65-a12b-f42ab1b283eb + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Date: + - Fri, 14 Jun 2024 04:54:46 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 41c118b760c485cd + X-B3-Traceid: + - 23438d243e8e416b41c118b760c485cd + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.021578" + X-Vcap-Request-Id: + - 23438d24-3e8e-416b-41c1-18b760c485cd::1d952911-66d5-4cd0-9e16-6d1529f7dfe6 + X-Xss-Protection: + - 1; mode=block + status: 204 No Content + code: 204 + duration: 205.633ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 59 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":[{"guid":"b2ab6999-260f-4db8-8e9e-098d7f55ecaf"}]} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"},{"guid":"b2ab6999-260f-4db8-8e9e-098d7f55ecaf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:46 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 7294471a3aa442b1 + X-B3-Traceid: + - b59eb361fede49487294471a3aa442b1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.020726" + X-Vcap-Request-Id: + - b59eb361-fede-4948-7294-471a3aa442b1::50c06284-c7e8-4c16-b115-2560c3ce0156 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 188.521834ms + - id: 12 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 463 + uncompressed: false + body: '{"data":[{"guid":"c8e454cc-7a24-4d71-b146-51d69538acfb"},{"guid":"db29f4b8-d39e-4f5c-b24d-cb34cde27abf"},{"guid":"b2ab6999-260f-4db8-8e9e-098d7f55ecaf"}],"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations"},"related":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/organizations"}}}' + headers: + Content-Length: + - "463" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:47 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 541bb97434b08d8d + X-B3-Traceid: + - dd4658b924ab44cb541bb97434b08d8d + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003193" + X-Vcap-Request-Id: + - dd4658b9-24ab-44cb-541b-b97434b08d8d::9d3a178e-9661-46b9-9429-5ef1540d5ecb + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 178.015542ms + - id: 13 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations/b2ab6999-260f-4db8-8e9e-098d7f55ecaf + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Date: + - Fri, 14 Jun 2024 04:54:47 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 440193160fb3caf6 + X-B3-Traceid: + - 613d3421993f45b0440193160fb3caf6 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.022394" + X-Vcap-Request-Id: + - 613d3421-993f-45b0-4401-93160fb3caf6::8fc3e90f-4706-4ec4-b9a7-ffb7c32cf2f5 + X-Xss-Protection: + - 1; mode=block + status: 204 No Content + code: 204 + duration: 190.82325ms + - id: 14 + 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/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations/db29f4b8-d39e-4f5c-b24d-cb34cde27abf + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Date: + - Fri, 14 Jun 2024 04:54:47 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 6ab1e60c2ed90eef + X-B3-Traceid: + - ebfcb1d7f9f9466e6ab1e60c2ed90eef + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.022680" + X-Vcap-Request-Id: + - ebfcb1d7-f9f9-466e-6ab1-e60c2ed90eef::d91e58c1-1cd7-4193-952f-a150dae9bcdd + X-Xss-Protection: + - 1; mode=block + status: 204 No Content + code: 204 + duration: 190.919458ms diff --git a/internal/provider/fixtures/resource_isolation_segment_entitlement_invalid.yaml b/internal/provider/fixtures/resource_isolation_segment_entitlement_invalid.yaml new file mode 100644 index 0000000..4a2a194 --- /dev/null +++ b/internal/provider/fixtures/resource_isolation_segment_entitlement_invalid.yaml @@ -0,0 +1,67 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 59 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"data":[{"guid":"da7f4f0d-0488-4880-9fbd-99ebfda12bed"}]} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments/63ae51b9-9073-4409-81b0-3704b8de85dd/relationships/organizations + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 203 + uncompressed: false + body: '{"errors":[{"detail":"Unable to entitle organizations [''da7f4f0d-0488-4880-9fbd-99ebfda12bed''] for the isolation segment. Ensure the organizations exist.","title":"CF-UnprocessableEntity","code":10008}]}' + headers: + Content-Length: + - "203" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 04:54:48 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 4740a17e76537237 + X-B3-Traceid: + - 3f20176959074cbc4740a17e76537237 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003074" + X-Vcap-Request-Id: + - 3f201769-5907-4cbc-4740-a17e76537237::6a042d87-d328-445e-b13e-190771c88d53 + X-Xss-Protection: + - 1; mode=block + status: 422 Unprocessable Entity + code: 422 + duration: 168.477708ms diff --git a/internal/provider/fixtures/resource_isolation_segment_invalid_create.yaml b/internal/provider/fixtures/resource_isolation_segment_invalid_create.yaml new file mode 100644 index 0000000..a45ca56 --- /dev/null +++ b/internal/provider/fixtures/resource_isolation_segment_invalid_create.yaml @@ -0,0 +1,67 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 62 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"name":"hifi","metadata":{"labels":null,"annotations":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 135 + uncompressed: false + body: '{"errors":[{"detail":"Isolation Segment names are case insensitive and must be unique","title":"CF-UnprocessableEntity","code":10008}]}' + headers: + Content-Length: + - "135" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:56 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 428e67804c69c2c0 + X-B3-Traceid: + - 2fe483d0dea947da428e67804c69c2c0 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.004069" + X-Vcap-Request-Id: + - 2fe483d0-dea9-47da-428e-67804c69c2c0::de9dae23-1fd2-4698-a09c-761eb306aa57 + X-Xss-Protection: + - 1; mode=block + status: 422 Unprocessable Entity + code: 422 + duration: 166.594667ms diff --git a/internal/provider/fixtures/resource_isolation_segment_invalid_update.yaml b/internal/provider/fixtures/resource_isolation_segment_invalid_update.yaml new file mode 100644 index 0000000..70ce5b3 --- /dev/null +++ b/internal/provider/fixtures/resource_isolation_segment_invalid_update.yaml @@ -0,0 +1,310 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 105 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"name":"segment-new","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 507 + uncompressed: false + body: '{"guid":"aa78b460-ac63-4a09-9d20-5a0a59edcca2","created_at":"2024-06-14T06:44:56Z","updated_at":"2024-06-14T06:44:56Z","name":"segment-new","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2/organizations"}}}' + headers: + Content-Length: + - "507" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:56 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 6111dbb7f10946e5 + X-B3-Traceid: + - 3b83576644b34b4d6111dbb7f10946e5 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.037022" + X-Vcap-Request-Id: + - 3b835766-44b3-4b4d-6111-dbb7f10946e5::0520ac7c-9079-4def-b328-8095f31b5e32 + X-Xss-Protection: + - 1; mode=block + status: 201 Created + code: 201 + duration: 205.584375ms + - 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/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 507 + uncompressed: false + body: '{"guid":"aa78b460-ac63-4a09-9d20-5a0a59edcca2","created_at":"2024-06-14T06:44:56Z","updated_at":"2024-06-14T06:44:56Z","name":"segment-new","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2/organizations"}}}' + headers: + Content-Length: + - "507" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:57 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 4d2aa9d5f89c8bb8 + X-B3-Traceid: + - 691fe097051c420a4d2aa9d5f89c8bb8 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003619" + X-Vcap-Request-Id: + - 691fe097-051c-420a-4d2a-a9d5f89c8bb8::64b90ae1-86db-410d-975b-349f541eacc9 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 168.548625ms + - id: 2 + 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/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 507 + uncompressed: false + body: '{"guid":"aa78b460-ac63-4a09-9d20-5a0a59edcca2","created_at":"2024-06-14T06:44:56Z","updated_at":"2024-06-14T06:44:56Z","name":"segment-new","metadata":{"labels":{"landscape":"test","purpose":"testing"},"annotations":{}},"links":{"self":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2"},"organizations":{"href":"https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2/organizations"}}}' + headers: + Content-Length: + - "507" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:57 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 67c1b023f7415fc1 + X-B3-Traceid: + - 090e8d0bb3a8419f67c1b023f7415fc1 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.003314" + X-Vcap-Request-Id: + - 090e8d0b-b3a8-419f-67c1-b023f7415fc1::3e32033b-f660-4a83-bbc6-f11db1ff3077 + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: 167.410666ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 115 + transfer_encoding: [] + trailer: {} + host: api.x.x.x.x.com + remote_addr: "" + request_uri: "" + body: | + {"name":"hifi","metadata":{"labels":{"landscape":null,"purpose":"production","status":"fine"},"annotations":null}} + form: {} + headers: + Authorization: + - Bearer redacted + Content-Type: + - application/json + User-Agent: + - Terraform/1.5.7 terraform-provider-cloudfoundry/dev + url: https://api.x.x.x.x.com/v3/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2 + method: PATCH + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 135 + uncompressed: false + body: '{"errors":[{"detail":"Isolation Segment names are case insensitive and must be unique","title":"CF-UnprocessableEntity","code":10008}]}' + headers: + Content-Length: + - "135" + Content-Type: + - application/json; charset=utf-8 + Date: + - Fri, 14 Jun 2024 06:44:57 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 4aa0a36c87e38b52 + X-B3-Traceid: + - 64a792548f424e004aa0a36c87e38b52 + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.039331" + X-Vcap-Request-Id: + - 64a79254-8f42-4e00-4aa0-a36c87e38b52::bb8efaf7-47ea-411f-b996-916d7e673909 + X-Xss-Protection: + - 1; mode=block + status: 422 Unprocessable Entity + code: 422 + duration: 218.807916ms + - id: 4 + 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/isolation_segments/aa78b460-ac63-4a09-9d20-5a0a59edcca2 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Date: + - Fri, 14 Jun 2024 06:44:58 GMT + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload; + X-B3-Spanid: + - 779531d576777d8c + X-B3-Traceid: + - bced30d02cd34c0f779531d576777d8c + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Frame-Options: + - SAMEORIGIN + X-Permitted-Cross-Domain-Policies: + - none + X-Runtime: + - "0.018280" + X-Vcap-Request-Id: + - bced30d0-2cd3-4c0f-7795-31d576777d8c::1db4c9ea-93de-4a98-9c5e-25c0b25e8597 + X-Xss-Protection: + - 1; mode=block + status: 204 No Content + code: 204 + duration: 182.173125ms diff --git a/internal/provider/provider.go b/internal/provider/provider.go index fa340f7..b919bb2 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -302,6 +302,8 @@ func (p *CloudFoundryProvider) Resources(ctx context.Context) []func() resource. NewAppResource, NewServiceCredentialBindingResource, NewMtaResource, + NewIsolationSegmentResource, + NewIsolationSegmentEntitlementResource, } } @@ -322,6 +324,8 @@ func (p *CloudFoundryProvider) DataSources(ctx context.Context) []func() datasou NewAppDataSource, NewServiceCredentialBindingDataSource, NewMtaDataSource, + NewIsolationSegmentDataSource, + NewIsolationSegmentEntitlementDataSource, } } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 30513eb..d9318bc 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -268,6 +268,8 @@ func TestCloudFoundryProvider_HasResources(t *testing.T) { "cloudfoundry_app", "cloudfoundry_service_credential_binding", "cloudfoundry_mta", + "cloudfoundry_isolation_segment", + "cloudfoundry_isolation_segment_entitlement", } ctx := context.Background() @@ -301,6 +303,8 @@ func TestProvider_HasDataSources(t *testing.T) { "cloudfoundry_app", "cloudfoundry_service_credential_binding", "cloudfoundry_mta", + "cloudfoundry_isolation_segment", + "cloudfoundry_isolation_segment_entitlement", } ctx := context.Background() diff --git a/internal/provider/resource_isolation_segment.go b/internal/provider/resource_isolation_segment.go new file mode 100644 index 0000000..33fdedc --- /dev/null +++ b/internal/provider/resource_isolation_segment.go @@ -0,0 +1,170 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/SAP/terraform-provider-cloudfoundry/internal/provider/managers" + cfv3client "github.com/cloudfoundry/go-cfclient/v3/client" + "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-log/tflog" +) + +var ( + _ resource.Resource = &IsolationSegmentResource{} + _ resource.ResourceWithConfigure = &IsolationSegmentResource{} + _ resource.ResourceWithImportState = &IsolationSegmentResource{} +) + +// Instantiates an isolation segment resource. +func NewIsolationSegmentResource() resource.Resource { + return &IsolationSegmentResource{} +} + +// Contains reference to the v3 client to be used for making the API calls. +type IsolationSegmentResource struct { + cfClient *cfv3client.Client +} + +func (r *IsolationSegmentResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_isolation_segment" +} + +func (r *IsolationSegmentResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Provides an isolation segment resource for Cloud Foundry.", + Attributes: map[string]schema.Attribute{ + idKey: guidSchema(), + "name": schema.StringAttribute{ + MarkdownDescription: "Name of the isolation segment", + Required: true, + }, + labelsKey: resourceLabelsSchema(), + annotationsKey: resourceAnnotationsSchema(), + createdAtKey: createdAtSchema(), + updatedAtKey: updatedAtSchema(), + }, + } +} + +func (r *IsolationSegmentResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + session, ok := req.ProviderData.(*managers.Session) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *managers.Session, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + r.cfClient = session.CFClient +} + +func (r *IsolationSegmentResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var plan IsolationSegmentType + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + createIsolationSegment, diags := plan.mapCreateIsolationSegmentTypeToValues(ctx) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + isolationSegment, err := r.cfClient.IsolationSegments.Create(ctx, &createIsolationSegment) + if err != nil { + resp.Diagnostics.AddError( + "API Error Creating Isolation Segment", + "Could not create Isolation Segment with name "+plan.Name.ValueString()+" : "+err.Error(), + ) + return + } + + plan, diags = mapIsolationSegmentValuesToType(ctx, isolationSegment) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "created an isolation segment resource") + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (rs *IsolationSegmentResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data IsolationSegmentType + diags := req.State.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + isolationSegment, err := rs.cfClient.IsolationSegments.Get(ctx, data.Id.ValueString()) + if err != nil { + handleReadErrors(ctx, resp, err, "isolation segment", data.Id.ValueString()) + return + } + + data, diags = mapIsolationSegmentValuesToType(ctx, isolationSegment) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "read an isolation segment resource") + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (rs *IsolationSegmentResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plan, previousState IsolationSegmentType + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &previousState)...) + if resp.Diagnostics.HasError() { + return + } + + updateIsolationSegment, diags := plan.mapUpdateIsolationSegmentTypeToValues(ctx, previousState) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + isolationSegment, err := rs.cfClient.IsolationSegments.Update(ctx, plan.Id.ValueString(), &updateIsolationSegment) + if err != nil { + resp.Diagnostics.AddError( + "API Error Updating Isolation Segment", + "Could not update Isolation Segment with ID "+plan.Id.ValueString()+" : "+err.Error(), + ) + return + } + + data, diags := mapIsolationSegmentValuesToType(ctx, isolationSegment) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "updated an isolation segment resource") + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (rs *IsolationSegmentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var state IsolationSegmentType + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + err := rs.cfClient.IsolationSegments.Delete(ctx, state.Id.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "API Error Deleting Isolation Segment", + "Could not delete the Isolation Segment with ID "+state.Id.ValueString()+" and name "+state.Name.ValueString()+" : "+err.Error(), + ) + return + } + + tflog.Trace(ctx, "deleted an isolation segment resource") +} + +func (rs *IsolationSegmentResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} diff --git a/internal/provider/resource_isolation_segment_entitlement.go b/internal/provider/resource_isolation_segment_entitlement.go new file mode 100644 index 0000000..1deae7f --- /dev/null +++ b/internal/provider/resource_isolation_segment_entitlement.go @@ -0,0 +1,263 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/SAP/terraform-provider-cloudfoundry/internal/provider/managers" + "github.com/SAP/terraform-provider-cloudfoundry/internal/validation" + cfv3client "github.com/cloudfoundry/go-cfclient/v3/client" + cfv3resource "github.com/cloudfoundry/go-cfclient/v3/resource" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +var ( + _ resource.Resource = &IsolationSegmentEntitlementResource{} + _ resource.ResourceWithConfigure = &IsolationSegmentEntitlementResource{} +) + +// Instantiates an isolation segment resource. +func NewIsolationSegmentEntitlementResource() resource.Resource { + return &IsolationSegmentEntitlementResource{} +} + +// Contains reference to the v3 client to be used for making the API calls. +type IsolationSegmentEntitlementResource struct { + cfClient *cfv3client.Client +} + +func (r *IsolationSegmentEntitlementResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_isolation_segment_entitlement" +} + +func (r *IsolationSegmentEntitlementResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Provides a Cloud Foundry resource for entitling and revoking isolation segment from organizations. Only entitles and revokes the segment from the orgs managed through this resource and does not touch existing entitlements. Revoking isolation segment entitlement from an organization will fail if it is the default for the organization. On deleting the resource, the isolation segment will be revoked from the mentioned orgs.", + Attributes: map[string]schema.Attribute{ + "segment": schema.StringAttribute{ + MarkdownDescription: "GUID of the isolation segment", + Required: true, + Validators: []validator.String{ + validation.ValidUUID(), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "orgs": schema.SetAttribute{ + MarkdownDescription: "GUID's of organizations to entitle the segment to.", + Required: true, + ElementType: types.StringType, + Validators: []validator.Set{ + setvalidator.ValueStringsAre(validation.ValidUUID()), + setvalidator.SizeAtLeast(1), + }, + }, + "default": schema.BoolAttribute{ + MarkdownDescription: "Set isolation segment as default for the organizations. Defaults to false.", + Optional: true, + }, + }, + } +} + +func (r *IsolationSegmentEntitlementResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + session, ok := req.ProviderData.(*managers.Session) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *managers.Session, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + r.cfClient = session.CFClient +} + +func (r *IsolationSegmentEntitlementResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var ( + plan IsolationSegmentEntitlementType + orgsToEntitle []string + ) + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = plan.Orgs.ElementsAs(ctx, &orgsToEntitle, false) + resp.Diagnostics.Append(diags...) + + entitledOrgs, err := r.cfClient.IsolationSegments.EntitleOrganizations(ctx, plan.Segment.ValueString(), orgsToEntitle) + if err != nil { + resp.Diagnostics.AddError( + "API Error Entitling Isolation Segment to Organizations.", + "Could not entitle Isolation Segment with ID "+plan.Segment.ValueString()+" to some organizations : "+err.Error(), + ) + return + } + + if !plan.Default.IsNull() { + var segment string + + if plan.Default.ValueBool() { + segment = plan.Segment.ValueString() + } else { + segment = "" + } + for _, org := range orgsToEntitle { + err = r.cfClient.Organizations.AssignDefaultIsolationSegment(ctx, org, segment) + if err != nil { + resp.Diagnostics.AddError( + "API Error Assigning Default Isolation Segment", + "Could not set Isolation Segment with ID "+plan.Segment.ValueString()+" on org with ID "+org+" : "+err.Error(), + ) + } + } + } + + diags = plan.mapIsolationSegmentEntitlementValuesToType(ctx, entitledOrgs.Data, plan.Default) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "created an isolation segment entitlement resource") + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (rs *IsolationSegmentEntitlementResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data IsolationSegmentEntitlementType + diags := req.State.Get(ctx, &data) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + orgs, err := rs.cfClient.IsolationSegments.ListOrganizationRelationships(ctx, data.Segment.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "API Error Fetching Entitled Organizations", + "Error : "+err.Error(), + ) + return + } + + entitledOrgsRelations := cfv3resource.NewToManyRelationships(orgs) + diags = data.mapIsolationSegmentEntitlementValuesToType(ctx, entitledOrgsRelations.Data, data.Default) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "read an isolation segment enititlement resource") + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (rs *IsolationSegmentEntitlementResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var ( + plan, previousState IsolationSegmentEntitlementType + entitledOrgs *cfv3resource.IsolationSegmentRelationship + ) + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &previousState)...) + if resp.Diagnostics.HasError() { + return + } + + removedOrgs, addedOrgs, diags := findChangedRelationsFromTFState(ctx, plan.Orgs, previousState.Orgs) + resp.Diagnostics.Append(diags...) + + err := rs.cfClient.IsolationSegments.RevokeOrganizations(ctx, plan.Segment.ValueString(), removedOrgs) + if err != nil { + resp.Diagnostics.AddError( + "API Error Revoking Isolation Segment from Organizations.", + "Could not revoke Isolation Segment with ID "+plan.Segment.ValueString()+"from some organizations : "+err.Error(), + ) + } + + if len(addedOrgs) != 0 { + entitledOrgs, err = rs.cfClient.IsolationSegments.EntitleOrganizations(ctx, plan.Segment.ValueString(), addedOrgs) + if err != nil { + resp.Diagnostics.AddError( + "API Error Entitling Isolation Segment to Organizations.", + "Could not entitle Isolation Segment with ID "+plan.Segment.ValueString()+" to some organizations : "+err.Error(), + ) + return + } + } else { + orgs, err := rs.cfClient.IsolationSegments.ListOrganizationRelationships(ctx, plan.Segment.ValueString()) + if err != nil { + resp.Diagnostics.AddError( + "API Error Fetching Entitled Organizations", + "Error : "+err.Error(), + ) + return + } + entitledOrgsRelations := cfv3resource.NewToManyRelationships(orgs) + entitledOrgs = &cfv3resource.IsolationSegmentRelationship{ + Data: entitledOrgsRelations.Data, + } + } + + if !plan.Default.IsNull() { + var ( + segment string + orgsToEntitle []string + ) + + if plan.Default.ValueBool() { + segment = plan.Segment.ValueString() + } else { + segment = "" + } + + diags = plan.Orgs.ElementsAs(ctx, &orgsToEntitle, false) + resp.Diagnostics.Append(diags...) + + for _, org := range orgsToEntitle { + err = rs.cfClient.Organizations.AssignDefaultIsolationSegment(ctx, org, segment) + if err != nil { + resp.Diagnostics.AddError( + "API Error Assigning Default Isolation Segment", + "Could not set Isolation Segment with ID "+plan.Segment.ValueString()+" on org with ID "+org+" : "+err.Error(), + ) + } + } + + } + + diags = plan.mapIsolationSegmentEntitlementValuesToType(ctx, entitledOrgs.Data, plan.Default) + resp.Diagnostics.Append(diags...) + + tflog.Trace(ctx, "updated an isolation segment entitlement resource") + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (rs *IsolationSegmentEntitlementResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var ( + state IsolationSegmentEntitlementType + orgsToRevoke []string + ) + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + diags = state.Orgs.ElementsAs(ctx, &orgsToRevoke, false) + resp.Diagnostics.Append(diags...) + + err := rs.cfClient.IsolationSegments.RevokeOrganizations(ctx, state.Segment.ValueString(), orgsToRevoke) + if err != nil { + resp.Diagnostics.AddError( + "API Error Revoking Isolation Segment from Organizations.", + "Could not revoke Isolation Segment with ID "+state.Segment.ValueString()+"from some organizations : "+err.Error(), + ) + } + + tflog.Trace(ctx, "deleted an isolation segment entitlement resource") +} diff --git a/internal/provider/resource_isolation_segment_entitlement_test.go b/internal/provider/resource_isolation_segment_entitlement_test.go new file mode 100644 index 0000000..77bbb37 --- /dev/null +++ b/internal/provider/resource_isolation_segment_entitlement_test.go @@ -0,0 +1,134 @@ +package provider + +import ( + "bytes" + "regexp" + "testing" + "text/template" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +type IsolationSegmentEntitlementModelPtr struct { + HclType string + HclObjectName string + Segment *string + Orgs *string + Default *bool +} + +func hclIsolationSegmentEntitlement(isemp *IsolationSegmentEntitlementModelPtr) string { + if isemp != nil { + s := ` + {{.HclType}} "cloudfoundry_isolation_segment_entitlement" {{.HclObjectName}} { + {{if .Segment}} + segment = "{{.Segment}}" + {{- end -}} + {{if .Orgs}} + orgs = {{.Orgs}} + {{- end -}} + {{if .Default}} + default = {{.Default}} + {{- end }} + }` + tmpl, err := template.New("resource_isolation_segment_entitlement").Parse(s) + if err != nil { + panic(err) + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, isemp) + if err != nil { + panic(err) + } + return buf.String() + } + return isemp.HclType + ` "cloudfoundry_isolation_segment_entitlement "` + isemp.HclObjectName + ` {}` +} + +func TestIsolationSegmentEntitlementResource_Configure(t *testing.T) { + var ( + // in staging + resourceName = "cloudfoundry_isolation_segment_entitlement.rs" + segmentGUID = "63ae51b9-9073-4409-81b0-3704b8de85dd" + entitleOrgsCreate = `["db29f4b8-d39e-4f5c-b24d-cb34cde27abf", "3c6ee045-7791-4d65-a12b-f42ab1b283eb"]` + entitleOrgsUpdate = `["db29f4b8-d39e-4f5c-b24d-cb34cde27abf", "b2ab6999-260f-4db8-8e9e-098d7f55ecaf"]` + invalidOrgs = `["da7f4f0d-0488-4880-9fbd-99ebfda12bed"]` + ) + t.Parallel() + t.Run("happy path - create/read/update/delete isolation segment entitlement", func(t *testing.T) { + + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/resource_isolation_segment_entitlement_crud") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegmentEntitlement(&IsolationSegmentEntitlementModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Segment: &segmentGUID, + Orgs: &entitleOrgsCreate, + Default: booltoboolptr(true), + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "segment", segmentGUID), + resource.TestCheckResourceAttr(resourceName, "orgs.#", "2"), + resource.TestCheckResourceAttr(resourceName, "default", "true"), + ), + }, + { + Config: hclProvider(nil) + hclIsolationSegmentEntitlement(&IsolationSegmentEntitlementModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Segment: &segmentGUID, + Orgs: &entitleOrgsCreate, + Default: booltoboolptr(false), + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "segment", segmentGUID), + resource.TestCheckResourceAttr(resourceName, "orgs.#", "2"), + resource.TestCheckResourceAttr(resourceName, "default", "false"), + ), + }, + { + Config: hclProvider(nil) + hclIsolationSegmentEntitlement(&IsolationSegmentEntitlementModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Segment: &segmentGUID, + Orgs: &entitleOrgsUpdate, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "segment", segmentGUID), + resource.TestCheckResourceAttr(resourceName, "orgs.#", "2"), + resource.TestCheckNoResourceAttr(resourceName, "default"), + ), + }, + }, + }) + }) + + t.Run("error path - create isolation segment entitlement with invalid org", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/resource_isolation_segment_entitlement_invalid") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegmentEntitlement(&IsolationSegmentEntitlementModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Segment: &segmentGUID, + Orgs: &invalidOrgs, + }), + ExpectError: regexp.MustCompile(`API Error Entitling Isolation Segment to Organizations`), + }, + }, + }) + }) +} diff --git a/internal/provider/resource_isolation_segment_test.go b/internal/provider/resource_isolation_segment_test.go new file mode 100644 index 0000000..ce54aa2 --- /dev/null +++ b/internal/provider/resource_isolation_segment_test.go @@ -0,0 +1,173 @@ +package provider + +import ( + "bytes" + "regexp" + "testing" + "text/template" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +type IsolationSegmentModelPtr struct { + HclType string + HclObjectName string + Name *string + Id *string + Labels *string + Annotations *string + CreatedAt *string + UpdatedAt *string +} + +func hclIsolationSegment(ismp *IsolationSegmentModelPtr) string { + if ismp != nil { + s := ` + {{.HclType}} "cloudfoundry_isolation_segment" {{.HclObjectName}} { + {{- if .Name}} + name = "{{.Name}}" + {{- end -}} + {{if .Id}} + id = "{{.Id}}" + {{- end -}} + {{if .Labels}} + labels = {{.Labels}} + {{- end -}} + {{if .Annotations}} + annotations = {{.Annotations}} + {{- end -}} + {{if .CreatedAt}} + created_at = "{{.CreatedAt}}" + {{- end -}} + {{if .UpdatedAt}} + updated_at = "{{.UpdatedAt}}" + {{- end }} + }` + tmpl, err := template.New("resource_isolation_segment").Parse(s) + if err != nil { + panic(err) + } + buf := new(bytes.Buffer) + err = tmpl.Execute(buf, ismp) + if err != nil { + panic(err) + } + return buf.String() + } + return ismp.HclType + ` "cloudfoundry_isolation_segment "` + ismp.HclObjectName + ` {}` +} + +func TestIsolationSegmentResource_Configure(t *testing.T) { + var ( + // in staging + createName = "segment" + createName2 = "segment-new" + updateName = "segment-2" + resourceName = "cloudfoundry_isolation_segment.rs" + existingName = "hifi" + ) + t.Parallel() + t.Run("happy path - create/read/update/delete isolation segment", func(t *testing.T) { + + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/resource_isolation_segment_crud") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Name: &createName, + Labels: &testCreateLabel, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr(resourceName, "id", regexpValidUUID), + resource.TestMatchResourceAttr(resourceName, "created_at", regexpValidRFC3999Format), + resource.TestCheckResourceAttr(resourceName, "name", createName), + resource.TestCheckResourceAttr(resourceName, "labels.purpose", "testing"), + ), + }, + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Name: &updateName, + Labels: &testUpdateLabel, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr(resourceName, "id", regexpValidUUID), + resource.TestMatchResourceAttr(resourceName, "created_at", regexpValidRFC3999Format), + resource.TestCheckResourceAttr(resourceName, "name", updateName), + resource.TestCheckResourceAttr(resourceName, "labels.purpose", "production"), + ), + }, + { + ResourceName: resourceName, + ImportStateIdFunc: getIdForImport(resourceName), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) + }) + + t.Run("error path - create isolation segment with existing name", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/resource_isolation_segment_invalid_create") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Name: &existingName, + }), + ExpectError: regexp.MustCompile(`API Error Creating Isolation Segment`), + }, + }, + }) + }) + t.Run("error path - update isolation segment with existing name", func(t *testing.T) { + cfg := getCFHomeConf() + rec := cfg.SetupVCR(t, "fixtures/resource_isolation_segment_invalid_update") + defer stopQuietly(rec) + + resource.Test(t, resource.TestCase{ + IsUnitTest: true, + ProtoV6ProviderFactories: getProviders(rec.GetDefaultClient()), + Steps: []resource.TestStep{ + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Name: &createName2, + Labels: &testCreateLabel, + }), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestMatchResourceAttr(resourceName, "id", regexpValidUUID), + resource.TestMatchResourceAttr(resourceName, "created_at", regexpValidRFC3999Format), + resource.TestCheckResourceAttr(resourceName, "name", createName2), + resource.TestCheckResourceAttr(resourceName, "labels.purpose", "testing"), + ), + }, + { + Config: hclProvider(nil) + hclIsolationSegment(&IsolationSegmentModelPtr{ + HclType: hclObjectResource, + HclObjectName: "rs", + Name: &existingName, + Labels: &testUpdateLabel, + }), + ExpectError: regexp.MustCompile(`API Error Updating Isolation Segment`), + }, + }, + }) + }) +} diff --git a/internal/provider/types_isolation_segment.go b/internal/provider/types_isolation_segment.go new file mode 100644 index 0000000..8c9b02f --- /dev/null +++ b/internal/provider/types_isolation_segment.go @@ -0,0 +1,96 @@ +package provider + +import ( + "context" + "time" + + "github.com/cloudfoundry/go-cfclient/v3/resource" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// Terraform struct for storing values for isolation segment data source and resource. +type IsolationSegmentType struct { + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Labels types.Map `tfsdk:"labels"` + Annotations types.Map `tfsdk:"annotations"` + CreatedAt types.String `tfsdk:"created_at"` + UpdatedAt types.String `tfsdk:"updated_at"` +} + +// Terraform struct for storing values for isolation segment entitlement resource. +type IsolationSegmentEntitlementType struct { + Segment types.String `tfsdk:"segment"` + Orgs types.Set `tfsdk:"orgs"` + Default types.Bool `tfsdk:"default"` +} + +// Terraform struct for storing values for isolation segment entitlement datasource. +type IsolationSegmentEntitlementDataSourceType struct { + Segment types.String `tfsdk:"segment"` + Orgs types.Set `tfsdk:"orgs"` +} + +// Sets the isolation segment resource values for creation with cf-client from the terraform struct values. +func (data *IsolationSegmentType) mapCreateIsolationSegmentTypeToValues(ctx context.Context) (resource.IsolationSegmentCreate, diag.Diagnostics) { + + createIsolationSegment := resource.NewIsolationSegmentCreate(data.Name.ValueString()) + + var diagnostics diag.Diagnostics + createIsolationSegment.Metadata = resource.NewMetadata() + + labelsDiags := data.Labels.ElementsAs(ctx, &createIsolationSegment.Metadata.Labels, false) + diagnostics.Append(labelsDiags...) + annotationsDiags := data.Annotations.ElementsAs(ctx, &createIsolationSegment.Metadata.Annotations, false) + diagnostics.Append(annotationsDiags...) + + return *createIsolationSegment, diagnostics +} + +// Sets the terraform struct values from the isolation segment resource returned by the cf-client. +func mapIsolationSegmentValuesToType(ctx context.Context, isolationSegment *resource.IsolationSegment) (IsolationSegmentType, diag.Diagnostics) { + + isolationSegmentType := IsolationSegmentType{ + Id: types.StringValue(isolationSegment.GUID), + Name: types.StringValue(isolationSegment.Name), + CreatedAt: types.StringValue(isolationSegment.CreatedAt.Format(time.RFC3339)), + UpdatedAt: types.StringValue(isolationSegment.UpdatedAt.Format(time.RFC3339)), + } + + var diags, diagnostics diag.Diagnostics + isolationSegmentType.Labels, diags = mapMetadataValueToType(ctx, isolationSegment.Metadata.Labels) + diagnostics.Append(diags...) + isolationSegmentType.Annotations, diags = mapMetadataValueToType(ctx, isolationSegment.Metadata.Annotations) + diagnostics.Append(diags...) + + return isolationSegmentType, diagnostics +} + +// Sets the isolation segment resource values for updation with cf-client from the terraform struct values. +func (plan *IsolationSegmentType) mapUpdateIsolationSegmentTypeToValues(ctx context.Context, state IsolationSegmentType) (resource.IsolationSegmentUpdate, diag.Diagnostics) { + + updateIsolationSegment := &resource.IsolationSegmentUpdate{ + Name: strtostrptr(plan.Name.ValueString()), + } + + var diagnostics diag.Diagnostics + updateIsolationSegment.Metadata, diagnostics = setClientMetadataForUpdate(ctx, state.Labels, state.Annotations, plan.Labels, plan.Annotations) + + return *updateIsolationSegment, diagnostics +} + +// Sets the terraform struct values from the entitled orgs returned by the cf-client. +func (plan *IsolationSegmentEntitlementType) mapIsolationSegmentEntitlementValuesToType(ctx context.Context, entitledOrgs []resource.Relationship, makeDefaultSegment types.Bool) diag.Diagnostics { + + var diagnostics diag.Diagnostics + entitledOrgSet, diags := setRelationshipToTFSet(entitledOrgs) + diagnostics.Append(diags...) + sameOrgs, diags := findSameRelationsFromTFState(ctx, plan.Orgs, entitledOrgSet) + diagnostics.Append(diags...) + plan.Orgs, diags = types.SetValueFrom(ctx, types.StringType, sameOrgs) + diagnostics.Append(diags...) + plan.Default = makeDefaultSegment + + return diagnostics +} diff --git a/internal/provider/utils.go b/internal/provider/utils.go index 894c3e4..1ad70e9 100644 --- a/internal/provider/utils.go +++ b/internal/provider/utils.go @@ -120,6 +120,16 @@ func findChangedRelationsFromTFState(ctx context.Context, planSet basetypes.SetV return removed, added, diags } +// Returns same element in the new plan which existed in state. +func findSameRelationsFromTFState(ctx context.Context, planSet basetypes.SetValue, stateSet basetypes.SetValue) ([]string, diag.Diagnostics) { + var diags diag.Diagnostics + var planSetStr, stateSetStr []string + diags = append(diags, planSet.ElementsAs(ctx, &planSetStr, false)...) + diags = append(diags, stateSet.ElementsAs(ctx, &stateSetStr, false)...) + same := lo.Intersect(stateSetStr, planSetStr) + return same, diags +} + func handleReadErrors(ctx context.Context, resp *resource.ReadResponse, err error, res string, resName string) { if cfv3resource.IsResourceNotFoundError(err) { resp.State.RemoveResource(ctx) diff --git a/migration-guide/Readme.md b/migration-guide/Readme.md index 721b178..94d0dbf 100644 --- a/migration-guide/Readme.md +++ b/migration-guide/Readme.md @@ -147,35 +147,55 @@ terraform import cloudfoundry_app.my-app d0348ed0-6e89-4836-80db-16479526a748 After the successful import run `terraform plan` to verify. It might prompt to reapply the configuration to populate some attribute values. After that the new configuration is ready for use. -## Overview of Changes +## Overview of Provider Differences -The following sections and the documents referenced within provide a detailed overview of the changes in the resources and data sources between the two providers. +The following sections and the documents referenced within provide a detailed overview of the changes/similarities in the resources and data sources between the two providers. > [!IMPORTANT] > For every resource and datasource, the computed attributes `created_at` and `updated_at` have been added in the new provider in line with V3. -### Resource Definition Changes +### Similar Resources +The below mentioned resources replicate the schema and functionality of those present in the existing community provider. -While most resources have maintained the same structure, some resources needed changes to follow the V3 API structure. Following is a list of resources that have changed +- [Isolation Segment](../docs/resources/isolation_segment.md) +- [Isolation Segment Entitlement](../docs/resources/isolation_segment_entitlement.md) + +### Changed Resources + +The below mentioned resources have been newly added in the current provider. + +- [Multi Target Application Deployment](../docs/resources/mta.md) + +While most resources have maintained the same structure, some resources needed minor changes in schema to follow the V3 API structure. Following is a list of resources whose schema have changed. - [Application](./resources/app.md) - [Domain](./resources/domain.md) - [Org Quota](./resources/org_quota.md) -- [Org Role](./resources/org_role.md) - [Organisation](./resources/org.md) - [Route](./resources/route.md) - [Security Group](./resources/security_group.md) - [Service credential Binding](./resources/service_credential_binding.md) - [Service Instance](./resources/service_instance.md) - [Space Quota](./resources/space_quota.md) -- [Space Role](./resources/space_role.md) - [Space](./resources/space.md) + +Few resources required a major change in functionality or the way the resources were created which are mentioned below. + +- [Org Role](./resources/org_role.md) +- [Space Role](./resources/space_role.md) - [User](./resources/user.md) -### DataSource Definition Changes +### Changed DataSources + +The below mentioned dataSources have been newly added in the current provider. + +- [Multi Target Application Deployment](../docs/data-sources/mta.md) +- [Isolation Segment Entitlement](../docs/data-sources/isolation_segment_entitlement.md) +- [Role](../docs/data-sources/role.md) +- [Users](../docs/data-sources/users.md) -While most dataSources have maintaied the same structure, some dataSources needed changes to follow the V3 API structure. Following is a list of datasources that have changed +While most dataSources have maintained the same structure, some dataSources needed minor changes in schema to follow the V3 API structure. Following is a list of datasources whose schema have changed - [Application](./data-sources/app.md) - [Domain](./data-sources/domain.md) diff --git a/migration-guide/data-sources/space.md b/migration-guide/data-sources/space.md index 2b3bcee..0f71362 100644 --- a/migration-guide/data-sources/space.md +++ b/migration-guide/data-sources/space.md @@ -14,6 +14,6 @@ Gets information on a Cloud Foundry space. | Attribute name | SAP Cloud Foundry Provider (new)| Community Cloud Foundry Provider (old) | Description | | --- | --- | --- | --- | | org_name | 🔴 | 🟢 | - | -| org | 🔵 | 🟢 | Space can now be queried only by `org` GUID and not by `org_name`. If one knows org_name and not org GUID, one can obtain the id value from [`cloudfoundry_org`](https://github.com/SAP/terraform-provider-cloudfoundry/blob/migration_docs/docs/data-sources/org.md) resource by specifying `name`. | +| org | 🔵 | 🟢 | Space can now be queried only by `org` GUID and not by `org_name`. If one knows org_name and not org GUID, one can obtain the id value from [`cloudfoundry_org`](https://github.com/SAP/terraform-provider-cloudfoundry/blob/main/docs/data-sources/org.md) resource by specifying `name`. | | allow_ssh | 🟠 | 🔴 | - | | isolation_segment | 🟠 | 🔴 | - | diff --git a/migration-guide/data-sources/user.md b/migration-guide/data-sources/user.md index a9b5042..475e05b 100644 --- a/migration-guide/data-sources/user.md +++ b/migration-guide/data-sources/user.md @@ -13,6 +13,6 @@ Gets information on Cloud Foundry users with a given username. | Attribute name | SAP Cloud Foundry Provider (new)| Community Cloud Foundry Provider (old) | Description | | --- | --- | --- | --- | -| org_id | 🔴 | 🟢 | For fetching specific user under a particular org in current provider, one can set the `org` attribute in [`cloudfoundry_users`](https://github.com/SAP/terraform-provider-cloudfoundry/blob/migration_docs/docs/data-sources/users.md) resource and then from `users` attribute output, filter the user with `username` desired. | +| org_id | 🔴 | 🟢 | For fetching specific user under a particular org in current provider, one can set the `org` attribute in [`cloudfoundry_users`](https://github.com/SAP/terraform-provider-cloudfoundry/blob/main/docs/data-sources/users.md) resource and then from `users` attribute output, filter the user with `username` desired. | | users | 🟠 | 🔴 | - | | id | 🔴 | 🟠 | The current provider returns multiple users if available with same user name in the `users` attribute unlike the community provider. Therefore the id is present in the respective user resources in `users` output. | diff --git a/migration-guide/resources/org_role.md b/migration-guide/resources/org_role.md index 7c39a50..73ca322 100644 --- a/migration-guide/resources/org_role.md +++ b/migration-guide/resources/org_role.md @@ -6,9 +6,3 @@ Provides a Cloud Foundry resource for assigning org roles. Roles of `type` are a | -- | -- | |
resource "cloudfoundry_org_role" "om1" {
for_each = tolist(["username1","username2"])
org = "organization-id"
username = each.value
type = "organization_billing_manager"
}

resource "cloudfoundry_org_role" "oa1" {
org = "organization-id"
username = "username"
type = "organization_auditor"
}

|
resource "cloudfoundry_org_users" "ou1" {
org = "organization-id"
managers = ["user-guid"]
billing_managers = ["username1","username2"]
auditors = ["user-guid", "username"]
}

| -## Differences - -> [!NOTE] -> 🔵 Required 🟢 Optional 🟠 Computed 🔴 Not present - -TODO: Add differences between the providers for the resource. diff --git a/migration-guide/resources/space_role.md b/migration-guide/resources/space_role.md index 027d588..413ca6d 100644 --- a/migration-guide/resources/space_role.md +++ b/migration-guide/resources/space_role.md @@ -5,10 +5,3 @@ Provides a Cloud Foundry resource for assigning space roles. V3 api has clear we | SAP Cloud Foundry Provider |Community Cloud Foundry Provider | | -- | -- | |
resource "cloudfoundry_space_role" "om1" {
space = "space-id"
user = "user-guid"
type = "space_manager"
}

resource "cloudfoundry_space_role" "od1" {
for_each = tolist(["username1","username2"])
space = "space-id"
username = each.value
type = "space_developer"
}

resource "cloudfoundry_space_role" "oa1" {
space = "space-id"
username = "username"
type = "space_auditor"
}

resource "cloudfoundry_space_role" "oa2" {
space = "space-id"
user = "user-guid"
type = "space_auditor"
}
|
resource "cloudfoundry_space_users" "ou1" {
space = "space-id"
managers = ["user-guid"]
developers = ["username1","username2"]
auditors = ["user-guid", "username"]
}

| - -## Differences - -> [!NOTE] -> 🔵 Required 🟢 Optional 🟠 Computed 🔴 Not present - -TODO: Add differences between the providers for the resource. diff --git a/migration-guide/resources/user.md b/migration-guide/resources/user.md index fe375e5..66542e2 100644 --- a/migration-guide/resources/user.md +++ b/migration-guide/resources/user.md @@ -6,9 +6,3 @@ Provides a Cloud Foundry resource for registering users. Intended to mimic funct | -- | -- | |
resource "cloudfoundry_user" "my_user" {
id = "test-user567"
annotations = { purpose : "testing" }
}
|
resource "cloudfoundry_user" "admin-service-user" {

name = "cf-admin"
password = "Passw0rd"

given_name = "John"
family_name = "Doe"

groups = [ "cloud_controller.admin", "scim.read", "scim.write" ]
}
| -## Differences - -> [!NOTE] -> 🔵 Required 🟢 Optional 🟠 Computed 🔴 Not present - -TODO: Add differences between the providers for the resource.