Skip to content

Commit 9cae987

Browse files
committed
feat: add meshstack_location resource
1 parent 89e5f2e commit 9cae987

File tree

8 files changed

+463
-0
lines changed

8 files changed

+463
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## Unreleased
2+
3+
FEATURES:
4+
5+
- New resource: `meshstack_location` for managing meshStack locations.
6+
17
## v0.16.3
28

39
FIXES:

client/client.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type endpoints struct {
4040
Platforms *url.URL `json:"meshplatforms"`
4141
PaymentMethods *url.URL `json:"meshpaymentmethods"`
4242
Integrations *url.URL `json:"meshintegrations"`
43+
Locations *url.URL `json:"meshlocations"`
4344
}
4445

4546
type loginRequest struct {
@@ -78,6 +79,7 @@ func NewClient(rootUrl *url.URL, apiKey string, apiSecret string) (*MeshStackPro
7879
Platforms: rootUrl.JoinPath(apiMeshObjectsRoot, "meshplatforms"),
7980
PaymentMethods: rootUrl.JoinPath(apiMeshObjectsRoot, "meshpaymentmethods"),
8081
Integrations: rootUrl.JoinPath(apiMeshObjectsRoot, "meshintegrations"),
82+
Locations: rootUrl.JoinPath(apiMeshObjectsRoot, "meshlocations"),
8183
}
8284

8385
return client, nil

client/location.go

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package client
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net/http"
9+
"net/url"
10+
)
11+
12+
const CONTENT_TYPE_LOCATION = "application/vnd.meshcloud.api.meshlocation.v1-preview.hal+json"
13+
14+
type MeshLocation struct {
15+
ApiVersion string `json:"apiVersion" tfsdk:"api_version"`
16+
Kind string `json:"kind" tfsdk:"kind"`
17+
Metadata MeshLocationMetadata `json:"metadata" tfsdk:"metadata"`
18+
Spec MeshLocationSpec `json:"spec" tfsdk:"spec"`
19+
}
20+
21+
type MeshLocationMetadata struct {
22+
Name string `json:"name" tfsdk:"name"`
23+
CreatedOn string `json:"createdOn" tfsdk:"created_on"`
24+
}
25+
26+
type MeshLocationSpec struct {
27+
DisplayName string `json:"displayName" tfsdk:"display_name"`
28+
}
29+
30+
type MeshLocationCreate struct {
31+
ApiVersion string `json:"apiVersion" tfsdk:"api_version"`
32+
Metadata MeshLocationCreateMetadata `json:"metadata" tfsdk:"metadata"`
33+
Spec MeshLocationSpec `json:"spec" tfsdk:"spec"`
34+
}
35+
36+
type MeshLocationCreateMetadata struct {
37+
Name string `json:"name" tfsdk:"name"`
38+
}
39+
40+
func (c *MeshStackProviderClient) urlForLocation(identifier string) *url.URL {
41+
return c.endpoints.Locations.JoinPath(identifier)
42+
}
43+
44+
func (c *MeshStackProviderClient) ReadLocation(identifier string) (*MeshLocation, error) {
45+
targetUrl := c.urlForLocation(identifier)
46+
47+
req, err := http.NewRequest("GET", targetUrl.String(), nil)
48+
if err != nil {
49+
return nil, err
50+
}
51+
req.Header.Set("Accept", CONTENT_TYPE_LOCATION)
52+
53+
res, err := c.doAuthenticatedRequest(req)
54+
if err != nil {
55+
return nil, err
56+
}
57+
58+
defer func() {
59+
_ = res.Body.Close()
60+
}()
61+
62+
if res.StatusCode == http.StatusNotFound {
63+
return nil, nil
64+
}
65+
66+
data, err := io.ReadAll(res.Body)
67+
if err != nil {
68+
return nil, err
69+
}
70+
71+
if !isSuccessHTTPStatus(res) {
72+
return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data)
73+
}
74+
75+
var location MeshLocation
76+
err = json.Unmarshal(data, &location)
77+
if err != nil {
78+
return nil, err
79+
}
80+
81+
return &location, nil
82+
}
83+
84+
func (c *MeshStackProviderClient) CreateLocation(location *MeshLocationCreate) (*MeshLocation, error) {
85+
payload, err := json.Marshal(location)
86+
if err != nil {
87+
return nil, err
88+
}
89+
90+
req, err := http.NewRequest("POST", c.endpoints.Locations.String(), bytes.NewBuffer(payload))
91+
if err != nil {
92+
return nil, err
93+
}
94+
req.Header.Set("Content-Type", CONTENT_TYPE_LOCATION)
95+
req.Header.Set("Accept", CONTENT_TYPE_LOCATION)
96+
97+
res, err := c.doAuthenticatedRequest(req)
98+
if err != nil {
99+
return nil, err
100+
}
101+
102+
defer func() {
103+
_ = res.Body.Close()
104+
}()
105+
106+
data, err := io.ReadAll(res.Body)
107+
if err != nil {
108+
return nil, err
109+
}
110+
111+
if !isSuccessHTTPStatus(res) {
112+
return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data)
113+
}
114+
115+
var createdLocation MeshLocation
116+
err = json.Unmarshal(data, &createdLocation)
117+
if err != nil {
118+
return nil, err
119+
}
120+
121+
return &createdLocation, nil
122+
}
123+
124+
func (c *MeshStackProviderClient) UpdateLocation(identifier string, location *MeshLocationCreate) (*MeshLocation, error) {
125+
targetUrl := c.urlForLocation(identifier)
126+
127+
payload, err := json.Marshal(location)
128+
if err != nil {
129+
return nil, err
130+
}
131+
132+
req, err := http.NewRequest("PUT", targetUrl.String(), bytes.NewBuffer(payload))
133+
if err != nil {
134+
return nil, err
135+
}
136+
req.Header.Set("Content-Type", CONTENT_TYPE_LOCATION)
137+
req.Header.Set("Accept", CONTENT_TYPE_LOCATION)
138+
139+
res, err := c.doAuthenticatedRequest(req)
140+
if err != nil {
141+
return nil, err
142+
}
143+
144+
defer func() {
145+
_ = res.Body.Close()
146+
}()
147+
148+
data, err := io.ReadAll(res.Body)
149+
if err != nil {
150+
return nil, err
151+
}
152+
153+
if !isSuccessHTTPStatus(res) {
154+
return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data)
155+
}
156+
157+
var updatedLocation MeshLocation
158+
err = json.Unmarshal(data, &updatedLocation)
159+
if err != nil {
160+
return nil, err
161+
}
162+
163+
return &updatedLocation, nil
164+
}
165+
166+
func (c *MeshStackProviderClient) DeleteLocation(identifier string) error {
167+
targetUrl := c.urlForLocation(identifier)
168+
return c.deleteMeshObject(*targetUrl, 204)
169+
}

docs/resources/location.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "meshstack_location Resource - terraform-provider-meshstack"
4+
subcategory: ""
5+
description: |-
6+
Represents a meshStack location.
7+
---
8+
9+
# meshstack_location (Resource)
10+
11+
Represents a meshStack location.
12+
13+
## Example Usage
14+
15+
```terraform
16+
resource "meshstack_location" "example" {
17+
metadata = {
18+
name = "my-location"
19+
}
20+
21+
spec = {
22+
display_name = "My Cloud Location"
23+
}
24+
}
25+
```
26+
27+
<!-- schema generated by tfplugindocs -->
28+
## Schema
29+
30+
### Required
31+
32+
- `metadata` (Attributes) (see [below for nested schema](#nestedatt--metadata))
33+
- `spec` (Attributes) (see [below for nested schema](#nestedatt--spec))
34+
35+
### Read-Only
36+
37+
- `api_version` (String) Location datatype version
38+
- `kind` (String) meshObject type, always `meshLocation`.
39+
40+
<a id="nestedatt--metadata"></a>
41+
### Nested Schema for `metadata`
42+
43+
Required:
44+
45+
- `name` (String) Location identifier. Must be unique across all locations.
46+
47+
Read-Only:
48+
49+
- `created_on` (String) Creation timestamp of the location (server-generated).
50+
51+
52+
<a id="nestedatt--spec"></a>
53+
### Nested Schema for `spec`
54+
55+
Required:
56+
57+
- `display_name` (String) The human-readable display name of the location.
58+
59+
## Import
60+
61+
Import is supported using the following syntax:
62+
63+
```shell
64+
terraform import meshstack_location.example my-location-identifier
65+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
terraform import meshstack_location.example my-location-identifier
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "meshstack_location" "example" {
2+
metadata = {
3+
name = "my-location"
4+
}
5+
6+
spec = {
7+
display_name = "My Cloud Location"
8+
}
9+
}

0 commit comments

Comments
 (0)