Skip to content

Commit 0b228de

Browse files
committed
feat: workspace resource
1 parent 7b2fda0 commit 0b228de

File tree

9 files changed

+508
-16
lines changed

9 files changed

+508
-16
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
## v0.7.2
1+
## v0.8.0
2+
3+
FEATURES:
4+
- Added `meshstack_workspace` resource.
5+
- Added `meshstack_workspace` data source.
26

37
FIXES:
48
- Allow `value_code` in `meshstack_building_block_v2` and `meshstack_building_block` resources.

client/workspace.go

Lines changed: 97 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package client
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"fmt"
67
"io"
78
"net/http"
89
"net/url"
910
)
1011

11-
const CONTENT_TYPE_WORKSPACE = "application/vnd.meshcloud.api.meshworkspace.v1.hal+json"
12+
const CONTENT_TYPE_WORKSPACE = "application/vnd.meshcloud.api.meshworkspace.v2.hal+json"
1213

1314
type MeshWorkspace struct {
1415
ApiVersion string `json:"apiVersion" tfsdk:"api_version"`
@@ -18,14 +19,25 @@ type MeshWorkspace struct {
1819
}
1920

2021
type MeshWorkspaceMetadata struct {
21-
Name string `json:"name" tfsdk:"name"`
22-
CreatedOn string `json:"createdOn" tfsdk:"created_on"`
23-
DeletedOn *string `json:"deletedOn" tfsdk:"deleted_on"`
22+
Name string `json:"name" tfsdk:"name"`
23+
CreatedOn string `json:"createdOn" tfsdk:"created_on"`
24+
DeletedOn *string `json:"deletedOn" tfsdk:"deleted_on"`
25+
Tags map[string][]string `json:"tags" tfsdk:"tags"`
2426
}
2527

2628
type MeshWorkspaceSpec struct {
27-
DisplayName string `json:"displayName" tfsdk:"display_name"`
28-
Tags map[string][]string `json:"tags" tfsdk:"tags"`
29+
DisplayName string `json:"displayName" tfsdk:"display_name"`
30+
PlatformBuilderAccessEnabled *bool `json:"platformBuilderAccessEnabled,omitempty" tfsdk:"platform_builder_access_enabled"`
31+
}
32+
33+
type MeshWorkspaceCreate struct {
34+
ApiVersion string `json:"apiVersion" tfsdk:"api_version"`
35+
Metadata MeshWorkspaceCreateMetadata `json:"metadata" tfsdk:"metadata"`
36+
Spec MeshWorkspaceSpec `json:"spec" tfsdk:"spec"`
37+
}
38+
type MeshWorkspaceCreateMetadata struct {
39+
Name string `json:"name" tfsdk:"name"`
40+
Tags map[string][]string `json:"tags" tfsdk:"tags"`
2941
}
3042

3143
func (c *MeshStackProviderClient) urlForWorkspace(name string) *url.URL {
@@ -67,3 +79,82 @@ func (c *MeshStackProviderClient) ReadWorkspace(name string) (*MeshWorkspace, er
6779
}
6880
return &workspace, nil
6981
}
82+
83+
func (c *MeshStackProviderClient) CreateWorkspace(workspace *MeshWorkspaceCreate) (*MeshWorkspace, error) {
84+
paylod, err := json.Marshal(workspace)
85+
if err != nil {
86+
return nil, err
87+
}
88+
89+
req, err := http.NewRequest("POST", c.endpoints.Workspaces.String(), bytes.NewBuffer(paylod))
90+
if err != nil {
91+
return nil, err
92+
}
93+
req.Header.Set("Content-Type", CONTENT_TYPE_WORKSPACE)
94+
req.Header.Set("Accept", CONTENT_TYPE_WORKSPACE)
95+
96+
res, err := c.doAuthenticatedRequest(req)
97+
if err != nil {
98+
return nil, err
99+
}
100+
defer res.Body.Close()
101+
102+
data, err := io.ReadAll(res.Body)
103+
if err != nil {
104+
return nil, err
105+
}
106+
107+
if !isSuccessHTTPStatus(res) {
108+
return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data)
109+
}
110+
111+
var createdWorkspace MeshWorkspace
112+
err = json.Unmarshal(data, &createdWorkspace)
113+
if err != nil {
114+
return nil, err
115+
}
116+
return &createdWorkspace, nil
117+
}
118+
119+
func (c *MeshStackProviderClient) UpdateWorkspace(name string, workspace *MeshWorkspaceCreate) (*MeshWorkspace, error) {
120+
targetUrl := c.urlForWorkspace(name)
121+
122+
paylod, err := json.Marshal(workspace)
123+
if err != nil {
124+
return nil, err
125+
}
126+
127+
req, err := http.NewRequest("PUT", targetUrl.String(), bytes.NewBuffer(paylod))
128+
if err != nil {
129+
return nil, err
130+
}
131+
req.Header.Set("Content-Type", CONTENT_TYPE_WORKSPACE)
132+
req.Header.Set("Accept", CONTENT_TYPE_WORKSPACE)
133+
134+
res, err := c.doAuthenticatedRequest(req)
135+
if err != nil {
136+
return nil, err
137+
}
138+
defer res.Body.Close()
139+
140+
data, err := io.ReadAll(res.Body)
141+
if err != nil {
142+
return nil, err
143+
}
144+
145+
if !isSuccessHTTPStatus(res) {
146+
return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data)
147+
}
148+
149+
var updatedWorkspace MeshWorkspace
150+
err = json.Unmarshal(data, &updatedWorkspace)
151+
if err != nil {
152+
return nil, err
153+
}
154+
return &updatedWorkspace, nil
155+
}
156+
157+
func (c *MeshStackProviderClient) DeleteWorkspace(name string) error {
158+
targetUrl := c.urlForWorkspace(name)
159+
return c.deleteMeshObject(*targetUrl, 204)
160+
}

docs/data-sources/workspace.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "meshstack_workspace Data Source - terraform-provider-meshstack"
4+
subcategory: ""
5+
description: |-
6+
Read a single workspace by identifier.
7+
---
8+
9+
# meshstack_workspace (Data Source)
10+
11+
Read a single workspace by identifier.
12+
13+
## Example Usage
14+
15+
```terraform
16+
data "meshstack_workspace" "example" {
17+
metadata = {
18+
name = "my-workspace-identifier"
19+
}
20+
}
21+
```
22+
23+
<!-- schema generated by tfplugindocs -->
24+
## Schema
25+
26+
### Required
27+
28+
- `metadata` (Attributes) (see [below for nested schema](#nestedatt--metadata))
29+
30+
### Read-Only
31+
32+
- `api_version` (String) Workspace API version.
33+
- `kind` (String) meshObject type, always `meshWorkspace`.
34+
- `spec` (Attributes) (see [below for nested schema](#nestedatt--spec))
35+
36+
<a id="nestedatt--metadata"></a>
37+
### Nested Schema for `metadata`
38+
39+
Required:
40+
41+
- `name` (String) Workspace identifier.
42+
43+
Read-Only:
44+
45+
- `created_on` (String) Creation date of the workspace.
46+
- `deleted_on` (String) Deletion date of the workspace.
47+
- `tags` (Map of List of String) Tags of the workspace.
48+
49+
50+
<a id="nestedatt--spec"></a>
51+
### Nested Schema for `spec`
52+
53+
Read-Only:
54+
55+
- `display_name` (String) Display name of the workspace.
56+
- `platform_builder_access_enabled` (Boolean) Whether platform builder access is enabled for the workspace.

docs/resources/workspace.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "meshstack_workspace Resource - terraform-provider-meshstack"
4+
subcategory: ""
5+
description: |-
6+
Represents a meshStack workspace.
7+
~> Note: Managing workspaces requires an API key with sufficient admin permissions.
8+
---
9+
10+
# meshstack_workspace (Resource)
11+
12+
Represents a meshStack workspace.
13+
14+
~> **Note:** Managing workspaces requires an API key with sufficient admin permissions.
15+
16+
## Example Usage
17+
18+
```terraform
19+
resource "meshstack_workspace" "example" {
20+
metadata = {
21+
name = "my-workspace-identifier"
22+
}
23+
spec = {
24+
display_name = "My Workspace's Display Name"
25+
tags = {
26+
"cost-center" = [
27+
"12345"
28+
]
29+
}
30+
}
31+
}
32+
```
33+
34+
<!-- schema generated by tfplugindocs -->
35+
## Schema
36+
37+
### Required
38+
39+
- `metadata` (Attributes) (see [below for nested schema](#nestedatt--metadata))
40+
- `spec` (Attributes) (see [below for nested schema](#nestedatt--spec))
41+
42+
### Read-Only
43+
44+
- `api_version` (String) Workspace datatype version
45+
- `kind` (String) meshObject type, always `meshWorkspace`.
46+
47+
<a id="nestedatt--metadata"></a>
48+
### Nested Schema for `metadata`
49+
50+
Required:
51+
52+
- `name` (String) Workspace identifier.
53+
54+
Optional:
55+
56+
- `tags` (Map of List of String) Tags of the workspace.
57+
58+
Read-Only:
59+
60+
- `created_on` (String) Creation date of the workspace.
61+
- `deleted_on` (String) Deletion date of the workspace.
62+
63+
64+
<a id="nestedatt--spec"></a>
65+
### Nested Schema for `spec`
66+
67+
Required:
68+
69+
- `display_name` (String) Display name of the workspace.
70+
71+
Optional:
72+
73+
- `platform_builder_access_enabled` (Boolean) Whether platform builder access is enabled for the workspace.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
data "meshstack_workspace" "example" {
2+
metadata = {
3+
name = "my-workspace-identifier"
4+
}
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
resource "meshstack_workspace" "example" {
2+
metadata = {
3+
name = "my-workspace-identifier"
4+
}
5+
spec = {
6+
display_name = "My Workspace's Display Name"
7+
tags = {
8+
"cost-center" = [
9+
"12345"
10+
]
11+
}
12+
}
13+
}

internal/provider/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ func (p *MeshStackProvider) Resources(ctx context.Context) []func() resource.Res
107107
NewTenantResource,
108108
NewProjectUserBindingResource,
109109
NewProjectGroupBindingResource,
110+
NewWorkspaceResource,
110111
NewBuildingBlockResource,
111112
NewBuildingBlockV2Resource,
112113
NewTagDefinitionResource,
@@ -121,6 +122,7 @@ func (p *MeshStackProvider) DataSources(ctx context.Context) []func() datasource
121122
NewProjectsDataSource,
122123
NewProjectUserBindingDataSource,
123124
NewProjectGroupBindingDataSource,
125+
NewWorkspaceDataSource,
124126
NewTenantDataSource,
125127
NewTagDefinitionDataSource,
126128
NewTagDefinitionsDataSource,

internal/provider/workspace_data_source.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (d *workspaceDataSource) Metadata(_ context.Context, req datasource.Metadat
3535
// Schema defines the schema for the data source.
3636
func (d *workspaceDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
3737
resp.Schema = schema.Schema{
38-
MarkdownDescription: "Read a single workspace by name.",
38+
MarkdownDescription: "Read a single workspace by identifier.",
3939

4040
Attributes: map[string]schema.Attribute{
4141
"api_version": schema.StringAttribute{
@@ -51,18 +51,23 @@ func (d *workspaceDataSource) Schema(_ context.Context, _ datasource.SchemaReque
5151
},
5252

5353
"metadata": schema.SingleNestedAttribute{
54-
Computed: true,
54+
Required: true,
5555
Attributes: map[string]schema.Attribute{
5656
"name": schema.StringAttribute{
57-
MarkdownDescription: "Name of the workspace. Is used to identify the workspace.",
57+
MarkdownDescription: "Workspace identifier.",
5858
Required: true,
5959
},
6060
"created_on": schema.StringAttribute{
61-
MarkdownDescription: "Creation date of the Workspace.",
61+
MarkdownDescription: "Creation date of the workspace.",
6262
Computed: true,
6363
},
6464
"deleted_on": schema.StringAttribute{
65-
MarkdownDescription: "Deletion date of the Workspace.",
65+
MarkdownDescription: "Deletion date of the workspace.",
66+
Computed: true,
67+
},
68+
"tags": schema.MapAttribute{
69+
MarkdownDescription: "Tags of the workspace.",
70+
ElementType: types.ListType{ElemType: types.StringType},
6671
Computed: true,
6772
},
6873
},
@@ -72,12 +77,11 @@ func (d *workspaceDataSource) Schema(_ context.Context, _ datasource.SchemaReque
7277
Computed: true,
7378
Attributes: map[string]schema.Attribute{
7479
"display_name": schema.StringAttribute{
75-
MarkdownDescription: "Display name of the Workspace.",
80+
MarkdownDescription: "Display name of the workspace.",
7681
Computed: true,
7782
},
78-
"tags": schema.MapAttribute{
79-
MarkdownDescription: "Tags of the Workspace.",
80-
ElementType: types.ListType{ElemType: types.StringType},
83+
"platform_builder_access_enabled": schema.BoolAttribute{
84+
MarkdownDescription: "Whether platform builder access is enabled for the workspace.",
8185
Computed: true,
8286
},
8387
},

0 commit comments

Comments
 (0)