Skip to content

Commit c93b77a

Browse files
authored
Blueprints resource (#2)
* added blueprints resource refactor http client * added blueprints resource refactor http client * bump version * fix tests collision * support update blueprint and add test * CR * fix tests
1 parent 34cc173 commit c93b77a

17 files changed

+1039
-127
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ HOSTNAME=github.com
22
NAMESPACE=port-labs
33
NAME=port-labs
44
BINARY=terraform-provider-${NAME}
5-
VERSION=0.0.16
5+
VERSION=0.1.0
66
OS=$(shell go env GOOS)
77
ARCH=$(shell go env GOARCH)
88
OS_ARCH=${OS}_${ARCH}

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
---
22
# generated by https://github.com/hashicorp/terraform-plugin-docs
3-
page_title: "port Provider"
3+
page_title: "port-labs Provider"
44
subcategory: ""
55
description: |-
66
77
---
88

9-
# port Provider
9+
# port-labs Provider
1010

1111

1212

docs/resources/blueprint.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "port-labs_blueprint Resource - terraform-provider-port-labs"
4+
subcategory: ""
5+
description: |-
6+
Port blueprint
7+
---
8+
9+
# port-labs_blueprint (Resource)
10+
11+
Port blueprint
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `icon` (String) The icon of the blueprint
21+
- `identifier` (String) The identifier of the blueprint
22+
- `properties` (Block Set, Min: 1) The metadata of the entity (see [below for nested schema](#nestedblock--properties))
23+
- `title` (String) The display name of the blueprint
24+
25+
### Optional
26+
27+
- `data_source` (String) The data source for entities of this blueprint
28+
- `relations` (Block Set) The blueprints that are connected to this blueprint (see [below for nested schema](#nestedblock--relations))
29+
30+
### Read-Only
31+
32+
- `created_at` (String)
33+
- `created_by` (String)
34+
- `id` (String) The ID of this resource.
35+
- `updated_at` (String)
36+
- `updated_by` (String)
37+
38+
<a id="nestedblock--properties"></a>
39+
### Nested Schema for `properties`
40+
41+
Required:
42+
43+
- `identifier` (String) The identifier of the property
44+
- `title` (String) The name of this property
45+
- `type` (String) The type of the property
46+
47+
Optional:
48+
49+
- `default` (String) The default value of the property
50+
- `description` (String) The description of the property
51+
- `format` (String) The format of the Property
52+
53+
54+
<a id="nestedblock--relations"></a>
55+
### Nested Schema for `relations`
56+
57+
Required:
58+
59+
- `target` (String) The id of the connected blueprint
60+
- `title` (String) The display name of the relation
61+
62+
Optional:
63+
64+
- `identifier` (String) The identifier of the relation
65+
- `many` (Boolean) Whether or not the relation is many
66+
- `required` (Boolean) Whether or not the relation is required
67+
68+

docs/resources/entity.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
# generated by https://github.com/hashicorp/terraform-plugin-docs
3-
page_title: "port-labs_entity Resource - terraform-provider-port"
3+
page_title: "port-labs_entity Resource - terraform-provider-port-labs"
44
subcategory: ""
55
description: |-
66
Port entity
@@ -10,8 +10,9 @@ description: |-
1010

1111
Port entity
1212

13-
<!-- schema generated by tfplugindocs -->
1413

14+
15+
<!-- schema generated by tfplugindocs -->
1516
## Schema
1617

1718
### Required
@@ -34,24 +35,25 @@ Port entity
3435
- `updated_by` (String)
3536

3637
<a id="nestedblock--properties"></a>
37-
3838
### Nested Schema for `properties`
3939

4040
Required:
4141

4242
- `name` (String) The name of this property
43-
- `type` (String) The type of the properrty
43+
- `type` (String) The type of the property
4444

4545
Optional:
4646

4747
- `items` (List of String) The list of items, in case the type of this property is a list
4848
- `value` (String) The value for this property
4949

50-
<a id="nestedblock--relations"></a>
5150

51+
<a id="nestedblock--relations"></a>
5252
### Nested Schema for `relations`
5353

5454
Required:
5555

5656
- `identifier` (String) The id of the connected entity
5757
- `name` (String) The name of the relation
58+
59+
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
resource "port-labs_blueprint" "environment" {
2+
title = "Environment"
3+
icon = "Environment"
4+
identifier = "hedwig-env"
5+
properties {
6+
identifier = "name"
7+
type = "string"
8+
title = "name"
9+
}
10+
properties {
11+
identifier = "docs-url"
12+
type = "string"
13+
title = "Docs URL"
14+
format = "url"
15+
}
16+
}
17+
18+
resource "port-labs_blueprint" "vm" {
19+
title = "VM"
20+
icon = "GPU"
21+
identifier = "hedwig-vm"
22+
properties {
23+
identifier = "name"
24+
type = "string"
25+
title = "Name"
26+
}
27+
relations {
28+
identifier = "environment"
29+
title = "Test Relation"
30+
required = "true"
31+
target = port-labs_blueprint.environment.identifier
32+
}
33+
}

port/cli/blueprint.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package cli
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
)
8+
9+
func (c *PortClient) ReadBlueprint(ctx context.Context, id string) (*Blueprint, error) {
10+
pb := &PortBody{}
11+
url := "v0.1/blueprints/{identifier}"
12+
resp, err := c.Client.R().
13+
SetContext(ctx).
14+
SetHeader("Accept", "application/json").
15+
SetQueryParam("exclude_mirror_properties", "true").
16+
SetResult(pb).
17+
SetPathParam("identifier", id).
18+
Get(url)
19+
if err != nil {
20+
return nil, err
21+
}
22+
if !pb.OK {
23+
return nil, fmt.Errorf("failed to read blueprint, got: %s", resp.Body())
24+
}
25+
return &pb.Blueprint, nil
26+
}
27+
28+
func (c *PortClient) CreateBlueprint(ctx context.Context, b *Blueprint) (*Blueprint, error) {
29+
url := "v0.1/blueprints"
30+
resp, err := c.Client.R().
31+
SetBody(b).
32+
SetContext(ctx).
33+
Post(url)
34+
if err != nil {
35+
return nil, err
36+
}
37+
var pb PortBody
38+
err = json.Unmarshal(resp.Body(), &pb)
39+
if err != nil {
40+
return nil, err
41+
}
42+
if !pb.OK {
43+
return nil, fmt.Errorf("failed to create blueprint, got: %s", resp.Body())
44+
}
45+
return &pb.Blueprint, nil
46+
}
47+
48+
func (c *PortClient) UpdateBlueprint(ctx context.Context, b *Blueprint, id string) (*Blueprint, error) {
49+
url := "v0.1/blueprints/{identifier}"
50+
resp, err := c.Client.R().
51+
SetBody(b).
52+
SetContext(ctx).
53+
SetPathParam("identifier", id).
54+
Put(url)
55+
if err != nil {
56+
return nil, err
57+
}
58+
var pb PortBody
59+
err = json.Unmarshal(resp.Body(), &pb)
60+
if err != nil {
61+
return nil, err
62+
}
63+
if !pb.OK {
64+
return nil, fmt.Errorf("failed to create blueprint, got: %s", resp.Body())
65+
}
66+
return &pb.Blueprint, nil
67+
}
68+
69+
func (c *PortClient) DeleteBlueprint(ctx context.Context, id string) error {
70+
url := "v0.1/blueprints/{identifier}"
71+
resp, err := c.Client.R().
72+
SetContext(ctx).
73+
SetHeader("Accept", "application/json").
74+
SetPathParam("identifier", id).
75+
Delete(url)
76+
if err != nil {
77+
return err
78+
}
79+
responseBody := make(map[string]interface{})
80+
err = json.Unmarshal(resp.Body(), &responseBody)
81+
if err != nil {
82+
return err
83+
}
84+
if !(responseBody["ok"].(bool)) {
85+
return fmt.Errorf("failed to delete blueprint. got:\n%s", string(resp.Body()))
86+
}
87+
return nil
88+
}

port/cli/client.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package cli
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"strings"
7+
8+
"github.com/go-resty/resty/v2"
9+
)
10+
11+
type (
12+
Option func(*PortClient)
13+
PortClient struct {
14+
Client *resty.Client
15+
ClientID string
16+
}
17+
)
18+
19+
func New(baseURL string, opts ...Option) (*PortClient, error) {
20+
c := &PortClient{
21+
Client: resty.New().
22+
SetBaseURL(baseURL).
23+
SetRetryCount(5).
24+
SetRetryWaitTime(300).
25+
// retry when create permission fails because scopes are created async-ly and sometimes (mainly in tests) the scope doesn't exist yet.
26+
AddRetryCondition(func(r *resty.Response, err error) bool {
27+
if err != nil {
28+
return true
29+
}
30+
if !strings.Contains(r.Request.URL, "/permissions") {
31+
return false
32+
}
33+
b := make(map[string]interface{})
34+
err = json.Unmarshal(r.Body(), &b)
35+
return err != nil || b["ok"] != true
36+
}),
37+
}
38+
for _, opt := range opts {
39+
opt(c)
40+
}
41+
return c, nil
42+
}
43+
44+
func (c *PortClient) Authenticate(ctx context.Context, clientID, clientSecret string) (string, error) {
45+
url := "v0.1/auth/access_token"
46+
resp, err := c.Client.R().
47+
SetContext(ctx).
48+
SetQueryParam("client_id", clientID).
49+
SetQueryParam("client_secret", clientSecret).
50+
Get(url)
51+
if err != nil {
52+
return "", err
53+
}
54+
var tokenResp AccessTokenResponse
55+
err = json.Unmarshal(resp.Body(), &tokenResp)
56+
if err != nil {
57+
return "", err
58+
}
59+
c.Client.SetAuthToken(tokenResp.AccessToken)
60+
return tokenResp.AccessToken, nil
61+
}
62+
63+
func WithHeader(key, val string) Option {
64+
return func(pc *PortClient) {
65+
pc.Client.SetHeader(key, val)
66+
}
67+
}
68+
69+
func WithClientID(clientID string) Option {
70+
return func(pc *PortClient) {
71+
pc.ClientID = clientID
72+
}
73+
}
74+
75+
func WithToken(token string) Option {
76+
return func(pc *PortClient) {
77+
pc.Client.SetAuthToken(token)
78+
}
79+
}

0 commit comments

Comments
 (0)