From 78f8dd6f173757307b37a15242bf259a4c85667b Mon Sep 17 00:00:00 2001 From: Jian Yuan Lee Date: Sun, 8 Dec 2024 11:11:56 +0000 Subject: [PATCH] feat: workspace member resource and workspace member and workspace members data source --- docs/data-sources/user.md | 6 + docs/data-sources/workspace_member.md | 32 + docs/data-sources/workspace_members.md | 39 + docs/data-sources/workspaces.md | 5 +- docs/index.md | 17 + docs/resources/workspace.md | 6 + docs/resources/workspace_member.md | 51 + .../anthropic_user/data-source.tf | 3 + .../anthropic_workspace_member/data-source.tf | 4 + .../data-source.tf | 3 + examples/provider/provider.tf | 17 + .../{data-source.tf => resource.tf} | 0 .../anthropic_workspace_member/import.sh | 5 + .../anthropic_workspace_member/resource.tf | 14 + go.mod | 12 +- go.sum | 23 +- internal/apiclient/api.yaml | 173 ++++ internal/apiclient/apiclient.gen.go | 927 ++++++++++++++++-- .../provider/data_source_workspace_member.go | 80 ++ .../data_source_workspace_member_test.go | 57 ++ .../provider/data_source_workspace_members.go | 126 +++ .../data_source_workspace_members_test.go | 62 ++ internal/provider/data_source_workspaces.go | 2 +- internal/provider/model_workspace_member.go | 20 + internal/provider/provider.go | 3 + .../provider/resource_workspace_member.go | 206 ++++ .../resource_workspace_member_test.go | 69 ++ internal/provider/utils.go | 18 + 28 files changed, 1870 insertions(+), 110 deletions(-) create mode 100644 docs/data-sources/workspace_member.md create mode 100644 docs/data-sources/workspace_members.md create mode 100644 docs/resources/workspace_member.md create mode 100644 examples/data-sources/anthropic_user/data-source.tf create mode 100644 examples/data-sources/anthropic_workspace_member/data-source.tf create mode 100644 examples/data-sources/anthropic_workspace_members/data-source.tf rename examples/resources/anthropic_workspace/{data-source.tf => resource.tf} (100%) create mode 100644 examples/resources/anthropic_workspace_member/import.sh create mode 100644 examples/resources/anthropic_workspace_member/resource.tf create mode 100644 internal/provider/data_source_workspace_member.go create mode 100644 internal/provider/data_source_workspace_member_test.go create mode 100644 internal/provider/data_source_workspace_members.go create mode 100644 internal/provider/data_source_workspace_members_test.go create mode 100644 internal/provider/model_workspace_member.go create mode 100644 internal/provider/resource_workspace_member.go create mode 100644 internal/provider/resource_workspace_member_test.go create mode 100644 internal/provider/utils.go diff --git a/docs/data-sources/user.md b/docs/data-sources/user.md index e51ce8e..be3298a 100644 --- a/docs/data-sources/user.md +++ b/docs/data-sources/user.md @@ -10,7 +10,13 @@ description: |- Get a user in the Organization. +## Example Usage +```terraform +data "anthropic_user" "example" { + id = "user_xxxxx" +} +``` ## Schema diff --git a/docs/data-sources/workspace_member.md b/docs/data-sources/workspace_member.md new file mode 100644 index 0000000..7215a2a --- /dev/null +++ b/docs/data-sources/workspace_member.md @@ -0,0 +1,32 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "anthropic_workspace_member Data Source - terraform-provider-anthropic" +subcategory: "" +description: |- + Get a member of a Workspace. +--- + +# anthropic_workspace_member (Data Source) + +Get a member of a Workspace. + +## Example Usage + +```terraform +data "anthropic_workspace_member" "example" { + workspace_id = "wrkspc_xxxxx" + user_id = "user_xxxxx" +} +``` + + +## Schema + +### Required + +- `user_id` (String) ID of the user who is a member of the Workspace. +- `workspace_id` (String) ID of the Workspace to which the member belongs. + +### Read-Only + +- `workspace_role` (String) Role of the new Workspace Member. Must be one of `workspace_user`, `workspace_developer`, or `workspace_admin`. diff --git a/docs/data-sources/workspace_members.md b/docs/data-sources/workspace_members.md new file mode 100644 index 0000000..e7870d5 --- /dev/null +++ b/docs/data-sources/workspace_members.md @@ -0,0 +1,39 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "anthropic_workspace_members Data Source - terraform-provider-anthropic" +subcategory: "" +description: |- + List all members of the workspace. +--- + +# anthropic_workspace_members (Data Source) + +List all members of the workspace. + +## Example Usage + +```terraform +data "anthropic_workspace_members" "example" { + id = "wrkspc_xxxxx" +} +``` + + +## Schema + +### Required + +- `id` (String) ID of the Workspace. + +### Read-Only + +- `members` (Attributes Set) List of members. (see [below for nested schema](#nestedatt--members)) + + +### Nested Schema for `members` + +Read-Only: + +- `user_id` (String) ID of the user who is a member of the Workspace. +- `workspace_id` (String) ID of the Workspace to which the member belongs. +- `workspace_role` (String) Role of the new Workspace Member. Must be one of `workspace_user`, `workspace_developer`, or `workspace_admin`. diff --git a/docs/data-sources/workspaces.md b/docs/data-sources/workspaces.md index 8662c28..53beef3 100644 --- a/docs/data-sources/workspaces.md +++ b/docs/data-sources/workspaces.md @@ -22,13 +22,10 @@ List all workspaces in the organization. ### Nested Schema for `workspaces` -Required: - -- `id` (String) ID of the Workspace. - Read-Only: - `archived_at` (String) RFC 3339 datetime string indicating when the Workspace was archived, or null if the Workspace is not archived. - `created_at` (String) RFC 3339 datetime string indicating when the Workspace was created. - `display_color` (String) Hex color code representing the Workspace in the Anthropic Console. +- `id` (String) ID of the Workspace. - `name` (String) Name of the Workspace. diff --git a/docs/index.md b/docs/index.md index 0e19db9..0909e57 100644 --- a/docs/index.md +++ b/docs/index.md @@ -17,6 +17,23 @@ description: |- provider "anthropic" { api_key = "sk-ant-adminxx-xxxxx-xxxxx-xxxxx-xxxxx" } + +# Create a new workspace +resource "anthropic_workspace" "example" { + name = "Workspace Name" +} + +# Retrieve a user by ID +data "anthropic_user" "example" { + id = "user_xxxxx" +} + +# Add a user to the workspace +resource "anthropic_workspace_member" "example" { + workspace_id = anthropic_workspace.example.id + user_id = data.anthropic_user.example.id + workspace_role = "workspace_developer" +} ``` diff --git a/docs/resources/workspace.md b/docs/resources/workspace.md index 291ffb1..2291cf3 100644 --- a/docs/resources/workspace.md +++ b/docs/resources/workspace.md @@ -10,7 +10,13 @@ description: |- Workspace resource. +## Example Usage +```terraform +resource "anthropic_workspace" "example" { + name = "Workspace Name" +} +``` ## Schema diff --git a/docs/resources/workspace_member.md b/docs/resources/workspace_member.md new file mode 100644 index 0000000..4f26704 --- /dev/null +++ b/docs/resources/workspace_member.md @@ -0,0 +1,51 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "anthropic_workspace_member Resource - terraform-provider-anthropic" +subcategory: "" +description: |- + Workspace member resource. +--- + +# anthropic_workspace_member (Resource) + +Workspace member resource. + +## Example Usage + +```terraform +resource "anthropic_workspace" "example" { + name = "Workspace Name" +} + +data "anthropic_user" "example" { + id = "user_xxxxx" +} + +# Create a workspace member +resource "anthropic_workspace_member" "example" { + workspace_id = anthropic_workspace.example.id + user_id = data.anthropic_user.example.id + workspace_role = "workspace_developer" +} +``` + + +## Schema + +### Required + +- `user_id` (String) ID of the user who is a member of the Workspace. +- `workspace_id` (String) ID of the Workspace to which the member belongs. +- `workspace_role` (String) Role of the new Workspace Member. Must be one of `workspace_user`, `workspace_developer`, or `workspace_admin`. + +## Import + +Import is supported using the following syntax: + +```shell +# Import an existing workspace member +terraform import anthropic_workspace_member.example workspace_id/user_id + +# Example +terraform import anthropic_workspace_member.example wrkspc_xxxxx/user_xxxxx +``` diff --git a/examples/data-sources/anthropic_user/data-source.tf b/examples/data-sources/anthropic_user/data-source.tf new file mode 100644 index 0000000..9d36c4e --- /dev/null +++ b/examples/data-sources/anthropic_user/data-source.tf @@ -0,0 +1,3 @@ +data "anthropic_user" "example" { + id = "user_xxxxx" +} diff --git a/examples/data-sources/anthropic_workspace_member/data-source.tf b/examples/data-sources/anthropic_workspace_member/data-source.tf new file mode 100644 index 0000000..6b26d6c --- /dev/null +++ b/examples/data-sources/anthropic_workspace_member/data-source.tf @@ -0,0 +1,4 @@ +data "anthropic_workspace_member" "example" { + workspace_id = "wrkspc_xxxxx" + user_id = "user_xxxxx" +} diff --git a/examples/data-sources/anthropic_workspace_members/data-source.tf b/examples/data-sources/anthropic_workspace_members/data-source.tf new file mode 100644 index 0000000..e2ce5a5 --- /dev/null +++ b/examples/data-sources/anthropic_workspace_members/data-source.tf @@ -0,0 +1,3 @@ +data "anthropic_workspace_members" "example" { + id = "wrkspc_xxxxx" +} diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 2121ce5..290fbd9 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -2,3 +2,20 @@ provider "anthropic" { api_key = "sk-ant-adminxx-xxxxx-xxxxx-xxxxx-xxxxx" } + +# Create a new workspace +resource "anthropic_workspace" "example" { + name = "Workspace Name" +} + +# Retrieve a user by ID +data "anthropic_user" "example" { + id = "user_xxxxx" +} + +# Add a user to the workspace +resource "anthropic_workspace_member" "example" { + workspace_id = anthropic_workspace.example.id + user_id = data.anthropic_user.example.id + workspace_role = "workspace_developer" +} diff --git a/examples/resources/anthropic_workspace/data-source.tf b/examples/resources/anthropic_workspace/resource.tf similarity index 100% rename from examples/resources/anthropic_workspace/data-source.tf rename to examples/resources/anthropic_workspace/resource.tf diff --git a/examples/resources/anthropic_workspace_member/import.sh b/examples/resources/anthropic_workspace_member/import.sh new file mode 100644 index 0000000..bec5009 --- /dev/null +++ b/examples/resources/anthropic_workspace_member/import.sh @@ -0,0 +1,5 @@ +# Import an existing workspace member +terraform import anthropic_workspace_member.example workspace_id/user_id + +# Example +terraform import anthropic_workspace_member.example wrkspc_xxxxx/user_xxxxx diff --git a/examples/resources/anthropic_workspace_member/resource.tf b/examples/resources/anthropic_workspace_member/resource.tf new file mode 100644 index 0000000..5110429 --- /dev/null +++ b/examples/resources/anthropic_workspace_member/resource.tf @@ -0,0 +1,14 @@ +resource "anthropic_workspace" "example" { + name = "Workspace Name" +} + +data "anthropic_user" "example" { + id = "user_xxxxx" +} + +# Create a workspace member +resource "anthropic_workspace_member" "example" { + workspace_id = anthropic_workspace.example.id + user_id = data.anthropic_user.example.id + workspace_role = "workspace_developer" +} diff --git a/go.mod b/go.mod index 03c2141..e6ca981 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,14 @@ go 1.23.4 require ( github.com/hashicorp/go-retryablehttp v0.7.7 + github.com/hashicorp/terraform-plugin-docs v0.20.1 github.com/hashicorp/terraform-plugin-framework v1.13.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 github.com/hashicorp/terraform-plugin-go v0.25.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 github.com/hashicorp/terraform-plugin-testing v1.11.0 github.com/jianyuan/go-utils v0.0.0-20241124212807-9e88ec4ee96c + github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 github.com/oapi-codegen/runtime v1.1.1 ) @@ -30,7 +34,6 @@ require ( github.com/getkin/kin-openapi v0.127.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/go-test/deep v1.0.8 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect @@ -49,9 +52,7 @@ require ( github.com/hashicorp/logutils v1.0.0 // indirect github.com/hashicorp/terraform-exec v0.21.0 // indirect github.com/hashicorp/terraform-json v0.23.0 // indirect - github.com/hashicorp/terraform-plugin-docs v0.20.1 // indirect github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect - github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -59,7 +60,6 @@ require ( github.com/imdario/mergo v0.3.15 // indirect github.com/invopop/yaml v0.3.1 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/kr/pretty v0.3.1 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect @@ -70,15 +70,12 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect - github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 // indirect github.com/oklog/run v1.0.0 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/posener/complete v1.2.3 // indirect - github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/speakeasy-api/openapi-overlay v0.9.0 // indirect github.com/spf13/cast v1.5.0 // indirect - github.com/stretchr/testify v1.9.0 // indirect github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect @@ -99,7 +96,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index df68bb9..3e29a96 100644 --- a/go.sum +++ b/go.sum @@ -26,7 +26,6 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar v1.1.1 h1:YroD6BJCZBYx06yYFEWvUuKVWQn3vLLQAVmDmvTSaiQ= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q= github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= @@ -37,7 +36,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -51,7 +49,10 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY= github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= @@ -132,6 +133,8 @@ github.com/hashicorp/terraform-plugin-docs v0.20.1 h1:Fq7E/HrU8kuZu3hNliZGwloFWS github.com/hashicorp/terraform-plugin-docs v0.20.1/go.mod h1:Yz6HoK7/EgzSrHPB9J/lWFzwl9/xep2OPnc5jaJDV90= github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= +github.com/hashicorp/terraform-plugin-framework-validators v0.15.0 h1:RXMmu7JgpFjnI1a5QjMCBb11usrW2OtAG+iOTIj5c9Y= +github.com/hashicorp/terraform-plugin-framework-validators v0.15.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks= github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= @@ -167,7 +170,6 @@ github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPci github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -202,6 +204,7 @@ github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oapi-codegen/oapi-codegen/v2 v2.4.1 h1:ykgG34472DWey7TSjd8vIfNykXgjOgYJZoQbKfEeY/Q= github.com/oapi-codegen/oapi-codegen/v2 v2.4.1/go.mod h1:N5+lY1tiTDV3V1BeHtOxeWXHoPVeApvsvjJqegfoaz8= @@ -212,6 +215,7 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -219,18 +223,16 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= +github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= @@ -255,6 +257,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= @@ -338,6 +342,8 @@ golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -351,8 +357,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -382,6 +386,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= diff --git a/internal/apiclient/api.yaml b/internal/apiclient/api.yaml index 05c0cd4..11d196c 100644 --- a/internal/apiclient/api.yaml +++ b/internal/apiclient/api.yaml @@ -178,6 +178,151 @@ paths: application/json: schema: $ref: "#/components/schemas/Workspace" + /v1/organizations/workspaces/{workspace_id}/members: + get: + operationId: listWorkspaceMembers + parameters: + - name: workspace_id + in: path + required: true + schema: + type: string + - name: limit + in: query + schema: + type: integer + - name: before_id + in: query + schema: + type: string + - name: after_id + in: query + schema: + type: string + responses: + "200": + content: + application/json: + schema: + type: object + required: + - data + - has_more + - first_id + - last_id + properties: + data: + type: array + items: + $ref: "#/components/schemas/WorkspaceMember" + has_more: + type: boolean + first_id: + type: string + nullable: true + last_id: + type: string + nullable: true + post: + operationId: createWorkspaceMember + parameters: + - name: workspace_id + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: object + required: + - user_id + - workspace_role + properties: + user_id: + type: string + workspace_role: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WorkspaceMember" + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /v1/organizations/workspaces/{workspace_id}/members/{user_id}: + get: + operationId: getWorkspaceMember + parameters: + - name: workspace_id + in: path + required: true + schema: + type: string + - name: user_id + in: path + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WorkspaceMember" + post: + operationId: updateWorkspaceMember + parameters: + - name: workspace_id + in: path + required: true + schema: + type: string + - name: user_id + in: path + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + type: object + required: + - workspace_role + properties: + workspace_role: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WorkspaceMember" + delete: + operationId: deleteWorkspaceMember + parameters: + - name: workspace_id + in: path + required: true + schema: + type: string + - name: user_id + in: path + required: true + schema: + type: string + responses: + "200": + content: + application/json: + schema: + $ref: "#/components/schemas/WorkspaceMember" security: - apiKeyAuth: [] - versionHeader: [] @@ -192,6 +337,21 @@ components: in: header name: anthropic-version schemas: + Error: + type: object + required: + - error + properties: + error: + type: object + required: + - type + - message + properties: + type: + type: string + message: + type: string User: type: object required: @@ -231,3 +391,16 @@ components: nullable: true display_color: type: string + WorkspaceMember: + type: object + required: + - user_id + - workspace_id + - workspace_role + properties: + user_id: + type: string + workspace_id: + type: string + workspace_role: + type: string diff --git a/internal/apiclient/apiclient.gen.go b/internal/apiclient/apiclient.gen.go index 1355e42..f7dd528 100644 --- a/internal/apiclient/apiclient.gen.go +++ b/internal/apiclient/apiclient.gen.go @@ -21,6 +21,14 @@ const ( VersionHeaderScopes = "versionHeader.Scopes" ) +// Error defines model for Error. +type Error struct { + Error struct { + Message string `json:"message"` + Type string `json:"type"` + } `json:"error"` +} + // User defines model for User. type User struct { AddedAt string `json:"added_at"` @@ -39,6 +47,13 @@ type Workspace struct { Name string `json:"name"` } +// WorkspaceMember defines model for WorkspaceMember. +type WorkspaceMember struct { + UserId string `json:"user_id"` + WorkspaceId string `json:"workspace_id"` + WorkspaceRole string `json:"workspace_role"` +} + // ListUsersParams defines parameters for ListUsers. type ListUsersParams struct { Limit *int `form:"limit,omitempty" json:"limit,omitempty"` @@ -64,12 +79,36 @@ type UpdateWorkspaceJSONBody struct { Name string `json:"name"` } +// ListWorkspaceMembersParams defines parameters for ListWorkspaceMembers. +type ListWorkspaceMembersParams struct { + Limit *int `form:"limit,omitempty" json:"limit,omitempty"` + BeforeId *string `form:"before_id,omitempty" json:"before_id,omitempty"` + AfterId *string `form:"after_id,omitempty" json:"after_id,omitempty"` +} + +// CreateWorkspaceMemberJSONBody defines parameters for CreateWorkspaceMember. +type CreateWorkspaceMemberJSONBody struct { + UserId string `json:"user_id"` + WorkspaceRole string `json:"workspace_role"` +} + +// UpdateWorkspaceMemberJSONBody defines parameters for UpdateWorkspaceMember. +type UpdateWorkspaceMemberJSONBody struct { + WorkspaceRole string `json:"workspace_role"` +} + // CreateWorkspaceJSONRequestBody defines body for CreateWorkspace for application/json ContentType. type CreateWorkspaceJSONRequestBody CreateWorkspaceJSONBody // UpdateWorkspaceJSONRequestBody defines body for UpdateWorkspace for application/json ContentType. type UpdateWorkspaceJSONRequestBody UpdateWorkspaceJSONBody +// CreateWorkspaceMemberJSONRequestBody defines body for CreateWorkspaceMember for application/json ContentType. +type CreateWorkspaceMemberJSONRequestBody CreateWorkspaceMemberJSONBody + +// UpdateWorkspaceMemberJSONRequestBody defines body for UpdateWorkspaceMember for application/json ContentType. +type UpdateWorkspaceMemberJSONRequestBody UpdateWorkspaceMemberJSONBody + // RequestEditorFn is the function signature for the RequestEditor callback function type RequestEditorFn func(ctx context.Context, req *http.Request) error @@ -167,6 +206,25 @@ type ClientInterface interface { // ArchiveWorkspace request ArchiveWorkspace(ctx context.Context, workspaceId string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // ListWorkspaceMembers request + ListWorkspaceMembers(ctx context.Context, workspaceId string, params *ListWorkspaceMembersParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // CreateWorkspaceMemberWithBody request with any body + CreateWorkspaceMemberWithBody(ctx context.Context, workspaceId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + CreateWorkspaceMember(ctx context.Context, workspaceId string, body CreateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // DeleteWorkspaceMember request + DeleteWorkspaceMember(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // GetWorkspaceMember request + GetWorkspaceMember(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*http.Response, error) + + // UpdateWorkspaceMemberWithBody request with any body + UpdateWorkspaceMemberWithBody(ctx context.Context, workspaceId string, userId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + UpdateWorkspaceMember(ctx context.Context, workspaceId string, userId string, body UpdateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) } func (c *Client) ListUsers(ctx context.Context, params *ListUsersParams, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -277,6 +335,90 @@ func (c *Client) ArchiveWorkspace(ctx context.Context, workspaceId string, reqEd return c.Client.Do(req) } +func (c *Client) ListWorkspaceMembers(ctx context.Context, workspaceId string, params *ListWorkspaceMembersParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewListWorkspaceMembersRequest(c.Server, workspaceId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateWorkspaceMemberWithBody(ctx context.Context, workspaceId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateWorkspaceMemberRequestWithBody(c.Server, workspaceId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) CreateWorkspaceMember(ctx context.Context, workspaceId string, body CreateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewCreateWorkspaceMemberRequest(c.Server, workspaceId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) DeleteWorkspaceMember(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewDeleteWorkspaceMemberRequest(c.Server, workspaceId, userId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) GetWorkspaceMember(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewGetWorkspaceMemberRequest(c.Server, workspaceId, userId) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateWorkspaceMemberWithBody(ctx context.Context, workspaceId string, userId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateWorkspaceMemberRequestWithBody(c.Server, workspaceId, userId, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) UpdateWorkspaceMember(ctx context.Context, workspaceId string, userId string, body UpdateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewUpdateWorkspaceMemberRequest(c.Server, workspaceId, userId, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + // NewListUsersRequest generates requests for ListUsers func NewListUsersRequest(server string, params *ListUsersParams) (*http.Request, error) { var err error @@ -644,125 +786,415 @@ func NewArchiveWorkspaceRequest(server string, workspaceId string) (*http.Reques return req, nil } -func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { - for _, r := range c.RequestEditors { - if err := r(ctx, req); err != nil { - return err - } +// NewListWorkspaceMembersRequest generates requests for ListWorkspaceMembers +func NewListWorkspaceMembersRequest(server string, workspaceId string, params *ListWorkspaceMembersParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "workspace_id", runtime.ParamLocationPath, workspaceId) + if err != nil { + return nil, err } - for _, r := range additionalEditors { - if err := r(ctx, req); err != nil { - return err - } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err } - return nil -} -// ClientWithResponses builds on ClientInterface to offer response payloads -type ClientWithResponses struct { - ClientInterface -} + operationPath := fmt.Sprintf("/v1/organizations/workspaces/%s/members", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } -// NewClientWithResponses creates a new ClientWithResponses, which wraps -// Client with return type handling -func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { - client, err := NewClient(server, opts...) + queryURL, err := serverURL.Parse(operationPath) if err != nil { return nil, err } - return &ClientWithResponses{client}, nil -} -// WithBaseURL overrides the baseURL. -func WithBaseURL(baseURL string) ClientOption { - return func(c *Client) error { - newBaseURL, err := url.Parse(baseURL) - if err != nil { - return err - } - c.Server = newBaseURL.String() - return nil - } -} + if params != nil { + queryValues := queryURL.Query() -// ClientWithResponsesInterface is the interface specification for the client with responses above. -type ClientWithResponsesInterface interface { - // ListUsersWithResponse request - ListUsersWithResponse(ctx context.Context, params *ListUsersParams, reqEditors ...RequestEditorFn) (*ListUsersResponse, error) + if params.Limit != nil { - // GetUserWithResponse request - GetUserWithResponse(ctx context.Context, userId string, reqEditors ...RequestEditorFn) (*GetUserResponse, error) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "limit", runtime.ParamLocationQuery, *params.Limit); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } - // ListWorkspacesWithResponse request - ListWorkspacesWithResponse(ctx context.Context, params *ListWorkspacesParams, reqEditors ...RequestEditorFn) (*ListWorkspacesResponse, error) + } - // CreateWorkspaceWithBodyWithResponse request with any body - CreateWorkspaceWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateWorkspaceResponse, error) + if params.BeforeId != nil { - CreateWorkspaceWithResponse(ctx context.Context, body CreateWorkspaceJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateWorkspaceResponse, error) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "before_id", runtime.ParamLocationQuery, *params.BeforeId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } - // GetWorkspaceWithResponse request - GetWorkspaceWithResponse(ctx context.Context, workspaceId string, reqEditors ...RequestEditorFn) (*GetWorkspaceResponse, error) + } - // UpdateWorkspaceWithBodyWithResponse request with any body - UpdateWorkspaceWithBodyWithResponse(ctx context.Context, workspaceId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateWorkspaceResponse, error) + if params.AfterId != nil { - UpdateWorkspaceWithResponse(ctx context.Context, workspaceId string, body UpdateWorkspaceJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateWorkspaceResponse, error) + if queryFrag, err := runtime.StyleParamWithLocation("form", true, "after_id", runtime.ParamLocationQuery, *params.AfterId); err != nil { + return nil, err + } else if parsed, err := url.ParseQuery(queryFrag); err != nil { + return nil, err + } else { + for k, v := range parsed { + for _, v2 := range v { + queryValues.Add(k, v2) + } + } + } - // ArchiveWorkspaceWithResponse request - ArchiveWorkspaceWithResponse(ctx context.Context, workspaceId string, reqEditors ...RequestEditorFn) (*ArchiveWorkspaceResponse, error) -} + } -type ListUsersResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *struct { - Data []User `json:"data"` - FirstId *string `json:"first_id"` - HasMore bool `json:"has_more"` - LastId *string `json:"last_id"` + queryURL.RawQuery = queryValues.Encode() } -} -// Status returns HTTPResponse.Status -func (r ListUsersResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err } - return http.StatusText(0) + + return req, nil } -// StatusCode returns HTTPResponse.StatusCode -func (r ListUsersResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode +// NewCreateWorkspaceMemberRequest calls the generic CreateWorkspaceMember builder with application/json body +func NewCreateWorkspaceMemberRequest(server string, workspaceId string, body CreateWorkspaceMemberJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err } - return 0 + bodyReader = bytes.NewReader(buf) + return NewCreateWorkspaceMemberRequestWithBody(server, workspaceId, "application/json", bodyReader) } -type GetUserResponse struct { - Body []byte - HTTPResponse *http.Response - JSON200 *User -} +// NewCreateWorkspaceMemberRequestWithBody generates requests for CreateWorkspaceMember with any type of body +func NewCreateWorkspaceMemberRequestWithBody(server string, workspaceId string, contentType string, body io.Reader) (*http.Request, error) { + var err error -// Status returns HTTPResponse.Status -func (r GetUserResponse) Status() string { - if r.HTTPResponse != nil { - return r.HTTPResponse.Status + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "workspace_id", runtime.ParamLocationPath, workspaceId) + if err != nil { + return nil, err } - return http.StatusText(0) -} -// StatusCode returns HTTPResponse.StatusCode -func (r GetUserResponse) StatusCode() int { - if r.HTTPResponse != nil { - return r.HTTPResponse.StatusCode + serverURL, err := url.Parse(server) + if err != nil { + return nil, err } - return 0 -} -type ListWorkspacesResponse struct { + operationPath := fmt.Sprintf("/v1/organizations/workspaces/%s/members", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +// NewDeleteWorkspaceMemberRequest generates requests for DeleteWorkspaceMember +func NewDeleteWorkspaceMemberRequest(server string, workspaceId string, userId string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "workspace_id", runtime.ParamLocationPath, workspaceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "user_id", runtime.ParamLocationPath, userId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/organizations/workspaces/%s/members/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewGetWorkspaceMemberRequest generates requests for GetWorkspaceMember +func NewGetWorkspaceMemberRequest(server string, workspaceId string, userId string) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "workspace_id", runtime.ParamLocationPath, workspaceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "user_id", runtime.ParamLocationPath, userId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/organizations/workspaces/%s/members/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + return req, nil +} + +// NewUpdateWorkspaceMemberRequest calls the generic UpdateWorkspaceMember builder with application/json body +func NewUpdateWorkspaceMemberRequest(server string, workspaceId string, userId string, body UpdateWorkspaceMemberJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewUpdateWorkspaceMemberRequestWithBody(server, workspaceId, userId, "application/json", bodyReader) +} + +// NewUpdateWorkspaceMemberRequestWithBody generates requests for UpdateWorkspaceMember with any type of body +func NewUpdateWorkspaceMemberRequestWithBody(server string, workspaceId string, userId string, contentType string, body io.Reader) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "workspace_id", runtime.ParamLocationPath, workspaceId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "user_id", runtime.ParamLocationPath, userId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/v1/organizations/workspaces/%s/members/%s", pathParam0, pathParam1) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + return req, nil +} + +func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error { + for _, r := range c.RequestEditors { + if err := r(ctx, req); err != nil { + return err + } + } + for _, r := range additionalEditors { + if err := r(ctx, req); err != nil { + return err + } + } + return nil +} + +// ClientWithResponses builds on ClientInterface to offer response payloads +type ClientWithResponses struct { + ClientInterface +} + +// NewClientWithResponses creates a new ClientWithResponses, which wraps +// Client with return type handling +func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) { + client, err := NewClient(server, opts...) + if err != nil { + return nil, err + } + return &ClientWithResponses{client}, nil +} + +// WithBaseURL overrides the baseURL. +func WithBaseURL(baseURL string) ClientOption { + return func(c *Client) error { + newBaseURL, err := url.Parse(baseURL) + if err != nil { + return err + } + c.Server = newBaseURL.String() + return nil + } +} + +// ClientWithResponsesInterface is the interface specification for the client with responses above. +type ClientWithResponsesInterface interface { + // ListUsersWithResponse request + ListUsersWithResponse(ctx context.Context, params *ListUsersParams, reqEditors ...RequestEditorFn) (*ListUsersResponse, error) + + // GetUserWithResponse request + GetUserWithResponse(ctx context.Context, userId string, reqEditors ...RequestEditorFn) (*GetUserResponse, error) + + // ListWorkspacesWithResponse request + ListWorkspacesWithResponse(ctx context.Context, params *ListWorkspacesParams, reqEditors ...RequestEditorFn) (*ListWorkspacesResponse, error) + + // CreateWorkspaceWithBodyWithResponse request with any body + CreateWorkspaceWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateWorkspaceResponse, error) + + CreateWorkspaceWithResponse(ctx context.Context, body CreateWorkspaceJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateWorkspaceResponse, error) + + // GetWorkspaceWithResponse request + GetWorkspaceWithResponse(ctx context.Context, workspaceId string, reqEditors ...RequestEditorFn) (*GetWorkspaceResponse, error) + + // UpdateWorkspaceWithBodyWithResponse request with any body + UpdateWorkspaceWithBodyWithResponse(ctx context.Context, workspaceId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateWorkspaceResponse, error) + + UpdateWorkspaceWithResponse(ctx context.Context, workspaceId string, body UpdateWorkspaceJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateWorkspaceResponse, error) + + // ArchiveWorkspaceWithResponse request + ArchiveWorkspaceWithResponse(ctx context.Context, workspaceId string, reqEditors ...RequestEditorFn) (*ArchiveWorkspaceResponse, error) + + // ListWorkspaceMembersWithResponse request + ListWorkspaceMembersWithResponse(ctx context.Context, workspaceId string, params *ListWorkspaceMembersParams, reqEditors ...RequestEditorFn) (*ListWorkspaceMembersResponse, error) + + // CreateWorkspaceMemberWithBodyWithResponse request with any body + CreateWorkspaceMemberWithBodyWithResponse(ctx context.Context, workspaceId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateWorkspaceMemberResponse, error) + + CreateWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, body CreateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateWorkspaceMemberResponse, error) + + // DeleteWorkspaceMemberWithResponse request + DeleteWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*DeleteWorkspaceMemberResponse, error) + + // GetWorkspaceMemberWithResponse request + GetWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*GetWorkspaceMemberResponse, error) + + // UpdateWorkspaceMemberWithBodyWithResponse request with any body + UpdateWorkspaceMemberWithBodyWithResponse(ctx context.Context, workspaceId string, userId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateWorkspaceMemberResponse, error) + + UpdateWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, userId string, body UpdateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateWorkspaceMemberResponse, error) +} + +type ListUsersResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Data []User `json:"data"` + FirstId *string `json:"first_id"` + HasMore bool `json:"has_more"` + LastId *string `json:"last_id"` + } +} + +// Status returns HTTPResponse.Status +func (r ListUsersResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r ListUsersResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetUserResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *User +} + +// Status returns HTTPResponse.Status +func (r GetUserResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetUserResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type ListWorkspacesResponse struct { Body []byte HTTPResponse *http.Response JSON200 *struct { @@ -877,6 +1309,122 @@ func (r ArchiveWorkspaceResponse) StatusCode() int { return 0 } +type ListWorkspaceMembersResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *struct { + Data []WorkspaceMember `json:"data"` + FirstId *string `json:"first_id"` + HasMore bool `json:"has_more"` + LastId *string `json:"last_id"` + } +} + +// Status returns HTTPResponse.Status +func (r ListWorkspaceMembersResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r ListWorkspaceMembersResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type CreateWorkspaceMemberResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *WorkspaceMember + JSON400 *Error +} + +// Status returns HTTPResponse.Status +func (r CreateWorkspaceMemberResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r CreateWorkspaceMemberResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type DeleteWorkspaceMemberResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *WorkspaceMember +} + +// Status returns HTTPResponse.Status +func (r DeleteWorkspaceMemberResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r DeleteWorkspaceMemberResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type GetWorkspaceMemberResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *WorkspaceMember +} + +// Status returns HTTPResponse.Status +func (r GetWorkspaceMemberResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r GetWorkspaceMemberResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type UpdateWorkspaceMemberResponse struct { + Body []byte + HTTPResponse *http.Response + JSON200 *WorkspaceMember +} + +// Status returns HTTPResponse.Status +func (r UpdateWorkspaceMemberResponse) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r UpdateWorkspaceMemberResponse) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + // ListUsersWithResponse request returning *ListUsersResponse func (c *ClientWithResponses) ListUsersWithResponse(ctx context.Context, params *ListUsersParams, reqEditors ...RequestEditorFn) (*ListUsersResponse, error) { rsp, err := c.ListUsers(ctx, params, reqEditors...) @@ -956,6 +1504,67 @@ func (c *ClientWithResponses) ArchiveWorkspaceWithResponse(ctx context.Context, return ParseArchiveWorkspaceResponse(rsp) } +// ListWorkspaceMembersWithResponse request returning *ListWorkspaceMembersResponse +func (c *ClientWithResponses) ListWorkspaceMembersWithResponse(ctx context.Context, workspaceId string, params *ListWorkspaceMembersParams, reqEditors ...RequestEditorFn) (*ListWorkspaceMembersResponse, error) { + rsp, err := c.ListWorkspaceMembers(ctx, workspaceId, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseListWorkspaceMembersResponse(rsp) +} + +// CreateWorkspaceMemberWithBodyWithResponse request with arbitrary body returning *CreateWorkspaceMemberResponse +func (c *ClientWithResponses) CreateWorkspaceMemberWithBodyWithResponse(ctx context.Context, workspaceId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CreateWorkspaceMemberResponse, error) { + rsp, err := c.CreateWorkspaceMemberWithBody(ctx, workspaceId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateWorkspaceMemberResponse(rsp) +} + +func (c *ClientWithResponses) CreateWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, body CreateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*CreateWorkspaceMemberResponse, error) { + rsp, err := c.CreateWorkspaceMember(ctx, workspaceId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseCreateWorkspaceMemberResponse(rsp) +} + +// DeleteWorkspaceMemberWithResponse request returning *DeleteWorkspaceMemberResponse +func (c *ClientWithResponses) DeleteWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*DeleteWorkspaceMemberResponse, error) { + rsp, err := c.DeleteWorkspaceMember(ctx, workspaceId, userId, reqEditors...) + if err != nil { + return nil, err + } + return ParseDeleteWorkspaceMemberResponse(rsp) +} + +// GetWorkspaceMemberWithResponse request returning *GetWorkspaceMemberResponse +func (c *ClientWithResponses) GetWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, userId string, reqEditors ...RequestEditorFn) (*GetWorkspaceMemberResponse, error) { + rsp, err := c.GetWorkspaceMember(ctx, workspaceId, userId, reqEditors...) + if err != nil { + return nil, err + } + return ParseGetWorkspaceMemberResponse(rsp) +} + +// UpdateWorkspaceMemberWithBodyWithResponse request with arbitrary body returning *UpdateWorkspaceMemberResponse +func (c *ClientWithResponses) UpdateWorkspaceMemberWithBodyWithResponse(ctx context.Context, workspaceId string, userId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*UpdateWorkspaceMemberResponse, error) { + rsp, err := c.UpdateWorkspaceMemberWithBody(ctx, workspaceId, userId, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateWorkspaceMemberResponse(rsp) +} + +func (c *ClientWithResponses) UpdateWorkspaceMemberWithResponse(ctx context.Context, workspaceId string, userId string, body UpdateWorkspaceMemberJSONRequestBody, reqEditors ...RequestEditorFn) (*UpdateWorkspaceMemberResponse, error) { + rsp, err := c.UpdateWorkspaceMember(ctx, workspaceId, userId, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseUpdateWorkspaceMemberResponse(rsp) +} + // ParseListUsersResponse parses an HTTP response from a ListUsersWithResponse call func ParseListUsersResponse(rsp *http.Response) (*ListUsersResponse, error) { bodyBytes, err := io.ReadAll(rsp.Body) @@ -1147,3 +1756,145 @@ func ParseArchiveWorkspaceResponse(rsp *http.Response) (*ArchiveWorkspaceRespons return response, nil } + +// ParseListWorkspaceMembersResponse parses an HTTP response from a ListWorkspaceMembersWithResponse call +func ParseListWorkspaceMembersResponse(rsp *http.Response) (*ListWorkspaceMembersResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &ListWorkspaceMembersResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest struct { + Data []WorkspaceMember `json:"data"` + FirstId *string `json:"first_id"` + HasMore bool `json:"has_more"` + LastId *string `json:"last_id"` + } + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseCreateWorkspaceMemberResponse parses an HTTP response from a CreateWorkspaceMemberWithResponse call +func ParseCreateWorkspaceMemberResponse(rsp *http.Response) (*CreateWorkspaceMemberResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &CreateWorkspaceMemberResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest WorkspaceMember + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 400: + var dest Error + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON400 = &dest + + } + + return response, nil +} + +// ParseDeleteWorkspaceMemberResponse parses an HTTP response from a DeleteWorkspaceMemberWithResponse call +func ParseDeleteWorkspaceMemberResponse(rsp *http.Response) (*DeleteWorkspaceMemberResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &DeleteWorkspaceMemberResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest WorkspaceMember + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseGetWorkspaceMemberResponse parses an HTTP response from a GetWorkspaceMemberWithResponse call +func ParseGetWorkspaceMemberResponse(rsp *http.Response) (*GetWorkspaceMemberResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &GetWorkspaceMemberResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest WorkspaceMember + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} + +// ParseUpdateWorkspaceMemberResponse parses an HTTP response from a UpdateWorkspaceMemberWithResponse call +func ParseUpdateWorkspaceMemberResponse(rsp *http.Response) (*UpdateWorkspaceMemberResponse, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &UpdateWorkspaceMemberResponse{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest WorkspaceMember + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + } + + return response, nil +} diff --git a/internal/provider/data_source_workspace_member.go b/internal/provider/data_source_workspace_member.go new file mode 100644 index 0000000..db83842 --- /dev/null +++ b/internal/provider/data_source_workspace_member.go @@ -0,0 +1,80 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" +) + +func NewWorkspaceMemberDataSource() datasource.DataSource { + return &WorkspaceMemberDataSource{} +} + +var _ datasource.DataSource = &WorkspaceMemberDataSource{} + +type WorkspaceMemberDataSource struct { + baseDataSource +} + +func (d *WorkspaceMemberDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_workspace_member" +} + +func (d *WorkspaceMemberDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Get a member of a Workspace.", + + Attributes: map[string]schema.Attribute{ + "workspace_id": schema.StringAttribute{ + MarkdownDescription: "ID of the Workspace to which the member belongs.", + Required: true, + }, + "user_id": schema.StringAttribute{ + MarkdownDescription: "ID of the user who is a member of the Workspace.", + Required: true, + }, + "workspace_role": schema.StringAttribute{ + MarkdownDescription: "Role of the new Workspace Member. Must be one of `workspace_user`, `workspace_developer`, or `workspace_admin`.", + Computed: true, + }, + }, + } +} + +func (d *WorkspaceMemberDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data WorkspaceMemberModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := d.client.GetWorkspaceMemberWithResponse( + ctx, + data.WorkspaceId.ValueString(), + data.UserId.ValueString(), + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read, got error: %s", err)) + return + } + + if httpResp.StatusCode() != 200 { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read, got status code: %d", httpResp.StatusCode())) + return + } + + if httpResp.JSON200 == nil { + resp.Diagnostics.AddError("Client Error", "Unable to read, got empty response body") + return + } + + if err := data.Fill(*httpResp.JSON200); err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to fill data, got error: %s", err)) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/data_source_workspace_member_test.go b/internal/provider/data_source_workspace_member_test.go new file mode 100644 index 0000000..8042e1b --- /dev/null +++ b/internal/provider/data_source_workspace_member_test.go @@ -0,0 +1,57 @@ +package provider + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/compare" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/jianyuan/terraform-provider-anthropic/internal/acctest" +) + +func TestAccWorkspaceMemberDataSource(t *testing.T) { + rn := "data.anthropic_workspace_member.test" + workspaceName := acctest.RandomWithPrefix("tf-workspace") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccWorkspaceMemberDataSourceConfig(workspaceName), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(rn, tfjsonpath.New("workspace_id"), "anthropic_workspace_member.test", tfjsonpath.New("workspace_id"), compare.ValuesSame()), + statecheck.CompareValuePairs(rn, tfjsonpath.New("user_id"), "anthropic_workspace_member.test", tfjsonpath.New("user_id"), compare.ValuesSame()), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("user_id"), knownvalue.StringExact(acctest.TestUserId)), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("workspace_role"), knownvalue.StringExact("workspace_developer")), + }, + }, + }, + }) +} + +func testAccWorkspaceMemberDataSourceConfig(workspaceName string) string { + return fmt.Sprintf(` +resource "anthropic_workspace" "test" { + name = %[1]q +} + +data "anthropic_user" "test" { + id = %[2]q +} + +resource "anthropic_workspace_member" "test" { + workspace_id = anthropic_workspace.test.id + user_id = data.anthropic_user.test.id + workspace_role = "workspace_developer" +} + +data "anthropic_workspace_member" "test" { + workspace_id = anthropic_workspace_member.test.workspace_id + user_id = anthropic_workspace_member.test.user_id +} +`, workspaceName, acctest.TestUserId) +} diff --git a/internal/provider/data_source_workspace_members.go b/internal/provider/data_source_workspace_members.go new file mode 100644 index 0000000..8828e1f --- /dev/null +++ b/internal/provider/data_source_workspace_members.go @@ -0,0 +1,126 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/jianyuan/go-utils/ptr" + "github.com/jianyuan/terraform-provider-anthropic/internal/apiclient" +) + +type WorkspaceMembersDataSourceModel struct { + Id types.String `tfsdk:"id"` + Members []WorkspaceMemberModel `tfsdk:"members"` +} + +func (m *WorkspaceMembersDataSourceModel) Fill(members []apiclient.WorkspaceMember) error { + m.Members = make([]WorkspaceMemberModel, len(members)) + for i, u := range members { + if err := m.Members[i].Fill(u); err != nil { + return err + } + } + + return nil +} + +func NewWorkspaceMembersDataSource() datasource.DataSource { + return &WorkspaceMembersDataSource{} +} + +var _ datasource.DataSource = &WorkspaceMembersDataSource{} + +type WorkspaceMembersDataSource struct { + baseDataSource +} + +func (d *WorkspaceMembersDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_workspace_members" +} + +func (d *WorkspaceMembersDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "List all members of the workspace.", + + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + MarkdownDescription: "ID of the Workspace.", + Required: true, + }, + "members": schema.SetNestedAttribute{ + MarkdownDescription: "List of members.", + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "workspace_id": schema.StringAttribute{ + MarkdownDescription: "ID of the Workspace to which the member belongs.", + Computed: true, + }, + "user_id": schema.StringAttribute{ + MarkdownDescription: "ID of the user who is a member of the Workspace.", + Computed: true, + }, + "workspace_role": schema.StringAttribute{ + MarkdownDescription: "Role of the new Workspace Member. Must be one of `workspace_user`, `workspace_developer`, or `workspace_admin`.", + Computed: true, + }, + }, + }, + }, + }, + } +} + +func (d *WorkspaceMembersDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data WorkspaceMembersDataSourceModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + var members []apiclient.WorkspaceMember + params := &apiclient.ListWorkspaceMembersParams{ + Limit: ptr.Ptr(100), + } + + for { + httpResp, err := d.client.ListWorkspaceMembersWithResponse( + ctx, + data.Id.ValueString(), + params, + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read, got error: %s", err)) + return + } + + if httpResp.StatusCode() != 200 { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read, got status code: %d", httpResp.StatusCode())) + return + } + + if httpResp.JSON200 == nil { + resp.Diagnostics.AddError("Client Error", "Unable to read, got empty response body") + return + } + + members = append(members, httpResp.JSON200.Data...) + + if !httpResp.JSON200.HasMore || httpResp.JSON200.LastId == nil { + break + } + + params.AfterId = httpResp.JSON200.LastId + } + + if err := data.Fill(members); err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to fill data, got error: %s", err)) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/data_source_workspace_members_test.go b/internal/provider/data_source_workspace_members_test.go new file mode 100644 index 0000000..a0e88b1 --- /dev/null +++ b/internal/provider/data_source_workspace_members_test.go @@ -0,0 +1,62 @@ +package provider + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/compare" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/jianyuan/terraform-provider-anthropic/internal/acctest" +) + +func TestAccWorkspaceMembersDataSource(t *testing.T) { + rn := "data.anthropic_workspace_members.test" + workspaceName := acctest.RandomWithPrefix("tf-workspace") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccWorkspaceMembersDataSourceConfig(workspaceName), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(rn, tfjsonpath.New("id"), "anthropic_workspace.test", tfjsonpath.New("id"), compare.ValuesSame()), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("members"), knownvalue.SetPartial([]knownvalue.Check{ + knownvalue.ObjectExact(map[string]knownvalue.Check{ + "workspace_id": knownvalue.NotNull(), + "user_id": knownvalue.StringExact(acctest.TestUserId), + "workspace_role": knownvalue.StringExact("workspace_developer"), + }), + })), + }, + }, + }, + }) +} + +func testAccWorkspaceMembersDataSourceConfig(workspaceName string) string { + return fmt.Sprintf(` +resource "anthropic_workspace" "test" { + name = %[1]q +} + +data "anthropic_user" "test" { + id = %[2]q +} + +resource "anthropic_workspace_member" "test" { + workspace_id = anthropic_workspace.test.id + user_id = data.anthropic_user.test.id + workspace_role = "workspace_developer" +} + +data "anthropic_workspace_members" "test" { + depends_on = [anthropic_workspace_member.test] + + id = anthropic_workspace_member.test.workspace_id +} +`, workspaceName, acctest.TestUserId) +} diff --git a/internal/provider/data_source_workspaces.go b/internal/provider/data_source_workspaces.go index 94809af..1421111 100644 --- a/internal/provider/data_source_workspaces.go +++ b/internal/provider/data_source_workspaces.go @@ -51,7 +51,7 @@ func (d *WorkspacesDataSource) Schema(ctx context.Context, req datasource.Schema Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ MarkdownDescription: "ID of the Workspace.", - Required: true, + Computed: true, }, "name": schema.StringAttribute{ MarkdownDescription: "Name of the Workspace.", diff --git a/internal/provider/model_workspace_member.go b/internal/provider/model_workspace_member.go new file mode 100644 index 0000000..e4af912 --- /dev/null +++ b/internal/provider/model_workspace_member.go @@ -0,0 +1,20 @@ +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/jianyuan/terraform-provider-anthropic/internal/apiclient" +) + +type WorkspaceMemberModel struct { + WorkspaceId types.String `tfsdk:"workspace_id"` + UserId types.String `tfsdk:"user_id"` + WorkspaceRole types.String `tfsdk:"workspace_role"` +} + +func (m *WorkspaceMemberModel) Fill(data apiclient.WorkspaceMember) error { + m.WorkspaceId = types.StringValue(data.WorkspaceId) + m.UserId = types.StringValue(data.UserId) + m.WorkspaceRole = types.StringValue(data.WorkspaceRole) + + return nil +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index b1cc474..d3edddf 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -111,6 +111,7 @@ func (p *AnthropicProvider) Configure(ctx context.Context, req provider.Configur func (p *AnthropicProvider) Resources(ctx context.Context) []func() resource.Resource { return []func() resource.Resource{ + NewWorkspaceMemberResource, NewWorkspaceResource, } } @@ -120,6 +121,8 @@ func (p *AnthropicProvider) DataSources(ctx context.Context) []func() datasource NewUserDataSource, NewUsersDataSource, NewWorkspaceDataSource, + NewWorkspaceMemberDataSource, + NewWorkspaceMembersDataSource, NewWorkspacesDataSource, } } diff --git a/internal/provider/resource_workspace_member.go b/internal/provider/resource_workspace_member.go new file mode 100644 index 0000000..a6ded0a --- /dev/null +++ b/internal/provider/resource_workspace_member.go @@ -0,0 +1,206 @@ +package provider + +import ( + "context" + "fmt" + "net/http" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/jianyuan/terraform-provider-anthropic/internal/apiclient" +) + +func NewWorkspaceMemberResource() resource.Resource { + return &WorkspaceMemberResource{} +} + +var _ resource.Resource = &WorkspaceMemberResource{} +var _ resource.ResourceWithImportState = &WorkspaceMemberResource{} + +type WorkspaceMemberResource struct { + baseResource +} + +func (r *WorkspaceMemberResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_workspace_member" +} + +func (r *WorkspaceMemberResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Workspace member resource.", + + Attributes: map[string]schema.Attribute{ + "workspace_id": schema.StringAttribute{ + MarkdownDescription: "ID of the Workspace to which the member belongs.", + Required: true, + }, + "user_id": schema.StringAttribute{ + MarkdownDescription: "ID of the user who is a member of the Workspace.", + Required: true, + }, + "workspace_role": schema.StringAttribute{ + MarkdownDescription: "Role of the new Workspace Member. Must be one of `workspace_user`, `workspace_developer`, or `workspace_admin`.", + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("workspace_user", "workspace_developer", "workspace_admin"), + }, + }, + }, + } +} + +func (r *WorkspaceMemberResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data WorkspaceMemberModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := r.client.CreateWorkspaceMemberWithResponse( + ctx, + data.WorkspaceId.ValueString(), + apiclient.CreateWorkspaceMemberJSONRequestBody{ + UserId: data.UserId.ValueString(), + WorkspaceRole: data.WorkspaceRole.ValueString(), + }, + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create, got error: %s", err)) + return + } + + if httpResp.StatusCode() != http.StatusOK { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create, got status code %d: %s", httpResp.StatusCode(), string(httpResp.Body))) + return + } + + if httpResp.JSON200 == nil { + resp.Diagnostics.AddError("Client Error", "Unable to create, got empty response body") + return + } + + if err := data.Fill(*httpResp.JSON200); err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to fill data: %s", err)) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *WorkspaceMemberResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data WorkspaceMemberModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := r.client.GetWorkspaceMemberWithResponse( + ctx, + data.WorkspaceId.ValueString(), + data.UserId.ValueString(), + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read, got error: %s", err)) + return + } + + if httpResp.StatusCode() != http.StatusOK { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read, got status code %d: %s", httpResp.StatusCode(), string(httpResp.Body))) + return + } + + if httpResp.JSON200 == nil { + resp.Diagnostics.AddError("Client Error", "Unable to read, got empty response body") + return + } + + if err := data.Fill(*httpResp.JSON200); err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to fill data: %s", err)) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *WorkspaceMemberResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data WorkspaceMemberModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := r.client.UpdateWorkspaceMemberWithResponse( + ctx, + data.WorkspaceId.ValueString(), + data.UserId.ValueString(), + apiclient.UpdateWorkspaceMemberJSONRequestBody{ + WorkspaceRole: data.WorkspaceRole.ValueString(), + }, + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update, got error: %s", err)) + return + } + + if httpResp.StatusCode() != http.StatusOK { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update, got status code %d: %s", httpResp.StatusCode(), string(httpResp.Body))) + return + } + + if httpResp.JSON200 == nil { + resp.Diagnostics.AddError("Client Error", "Unable to update, got empty response body") + return + } + + if err := data.Fill(*httpResp.JSON200); err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to fill data: %s", err)) + return + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *WorkspaceMemberResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data WorkspaceMemberModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + httpResp, err := r.client.DeleteWorkspaceMemberWithResponse( + ctx, + data.WorkspaceId.ValueString(), + data.UserId.ValueString(), + ) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete, got error: %s", err)) + return + } + + if httpResp.StatusCode() != http.StatusOK { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete, got status code %d: %s", httpResp.StatusCode(), string(httpResp.Body))) + return + } +} + +func (r *WorkspaceMemberResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + workspaceId, userId, err := SplitTwoPartId(req.ID, "workspace_id", "user_id") + if err != nil { + resp.Diagnostics.AddError("Invalid ID", fmt.Sprintf("Error parsing ID: %s", err.Error())) + return + } + + resp.Diagnostics.Append(resp.State.SetAttribute( + ctx, path.Root("workspace_id"), workspaceId, + )...) + resp.Diagnostics.Append(resp.State.SetAttribute( + ctx, path.Root("user_id"), userId, + )...) +} diff --git a/internal/provider/resource_workspace_member_test.go b/internal/provider/resource_workspace_member_test.go new file mode 100644 index 0000000..8dfe565 --- /dev/null +++ b/internal/provider/resource_workspace_member_test.go @@ -0,0 +1,69 @@ +package provider + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/compare" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/knownvalue" + "github.com/hashicorp/terraform-plugin-testing/statecheck" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-plugin-testing/tfjsonpath" + "github.com/jianyuan/terraform-provider-anthropic/internal/acctest" +) + +func TestAccWorkspaceMemberResource(t *testing.T) { + rn := "anthropic_workspace_member.test" + workspaceName := acctest.RandomWithPrefix("tf-workspace") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccWorkspaceMemberResourceConfig(workspaceName, "workspace_user"), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(rn, tfjsonpath.New("workspace_id"), "anthropic_workspace.test", tfjsonpath.New("id"), compare.ValuesSame()), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("user_id"), knownvalue.StringExact(acctest.TestUserId)), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("workspace_role"), knownvalue.StringExact("workspace_user")), + }, + }, + { + ResourceName: rn, + ImportState: true, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + rs, ok := s.RootModule().Resources[rn] + if !ok { + return "", fmt.Errorf("not found: %s", rn) + } + workspaceId := rs.Primary.Attributes["workspace_id"] + userId := rs.Primary.Attributes["user_id"] + return BuildTwoPartId(workspaceId, userId), nil + }, + }, + { + Config: testAccWorkspaceMemberResourceConfig(workspaceName, "workspace_developer"), + ConfigStateChecks: []statecheck.StateCheck{ + statecheck.CompareValuePairs(rn, tfjsonpath.New("workspace_id"), "anthropic_workspace.test", tfjsonpath.New("id"), compare.ValuesSame()), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("user_id"), knownvalue.StringExact(acctest.TestUserId)), + statecheck.ExpectKnownValue(rn, tfjsonpath.New("workspace_role"), knownvalue.StringExact("workspace_developer")), + }, + }, + }, + }) +} + +func testAccWorkspaceMemberResourceConfig(workspaceName string, workspaceRole string) string { + return fmt.Sprintf(` +resource "anthropic_workspace" "test" { + name = %[1]q +} + +resource "anthropic_workspace_member" "test" { + workspace_id = anthropic_workspace.test.id + user_id = %[2]q + workspace_role = %[3]q +} +`, workspaceName, acctest.TestUserId, workspaceRole) +} diff --git a/internal/provider/utils.go b/internal/provider/utils.go new file mode 100644 index 0000000..873867b --- /dev/null +++ b/internal/provider/utils.go @@ -0,0 +1,18 @@ +package provider + +import ( + "fmt" + "strings" +) + +func BuildTwoPartId(a, b string) string { + return fmt.Sprintf("%s/%s", a, b) +} + +func SplitTwoPartId(id, a, b string) (string, string, error) { + parts := strings.Split(id, "/") + if len(parts) != 2 || parts[0] == "" || parts[1] == "" { + return "", "", fmt.Errorf("unexpected format of ID (%s), expected %s/%s", id, a, b) + } + return parts[0], parts[1], nil +}