Skip to content

Commit d6b1cf1

Browse files
authored
feat: support database group (#109)
* feat: support database group * fix: lint
1 parent 6583f84 commit d6b1cf1

29 files changed

+742
-77
lines changed

api/client.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,15 @@ type Client interface {
191191
UpdateRisk(ctx context.Context, patch *v1pb.Risk, updateMasks []string) (*v1pb.Risk, error)
192192
// DeleteRisk deletes the risk by name.
193193
DeleteRisk(ctx context.Context, name string) error
194+
195+
// ListDatabaseGroup list all database groups in a project.
196+
ListDatabaseGroup(ctx context.Context, project string) (*v1pb.ListDatabaseGroupsResponse, error)
197+
// CreateDatabaseGroup creates the database group.
198+
CreateDatabaseGroup(ctx context.Context, project, groupID string, group *v1pb.DatabaseGroup) (*v1pb.DatabaseGroup, error)
199+
// GetDatabaseGroup gets the database group by name.
200+
GetDatabaseGroup(ctx context.Context, name string, view v1pb.DatabaseGroupView) (*v1pb.DatabaseGroup, error)
201+
// UpdateDatabaseGroup updates the database group.
202+
UpdateDatabaseGroup(ctx context.Context, patch *v1pb.DatabaseGroup, updateMasks []string) (*v1pb.DatabaseGroup, error)
203+
// DeleteDatabaseGroup deletes the database group by name.
204+
DeleteDatabaseGroup(ctx context.Context, name string) error
194205
}

client/common.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ func (c *client) updateResource(ctx context.Context, name string, patch protoref
6363
}
6464

6565
// getResource gets the resource by name.
66-
func (c *client) getResource(ctx context.Context, name string) ([]byte, error) {
67-
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, url.QueryEscape(name)), nil)
66+
func (c *client) getResource(ctx context.Context, name, query string) ([]byte, error) {
67+
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s?%s", c.url, c.version, url.QueryEscape(name), query), nil)
6868
if err != nil {
6969
return nil, err
7070
}

client/database.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
// GetDatabase gets the database by the database full name.
1919
func (c *client) GetDatabase(ctx context.Context, databaseName string) (*v1pb.Database, error) {
20-
body, err := c.getResource(ctx, databaseName)
20+
body, err := c.getResource(ctx, databaseName, "")
2121
if err != nil {
2222
return nil, err
2323
}
@@ -177,7 +177,7 @@ func (c *client) BatchUpdateDatabases(ctx context.Context, request *v1pb.BatchUp
177177

178178
// GetDatabaseCatalog gets the database catalog by the database full name.
179179
func (c *client) GetDatabaseCatalog(ctx context.Context, databaseName string) (*v1pb.DatabaseCatalog, error) {
180-
body, err := c.getResource(ctx, fmt.Sprintf("%s/catalog", databaseName))
180+
body, err := c.getResource(ctx, fmt.Sprintf("%s/catalog", databaseName), "")
181181
if err != nil {
182182
return nil, err
183183
}

client/database_group.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package client
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net/http"
7+
"strings"
8+
9+
v1pb "github.com/bytebase/bytebase/proto/generated-go/v1"
10+
"google.golang.org/protobuf/encoding/protojson"
11+
)
12+
13+
// ListDatabaseGroup list all database groups in a project.
14+
func (c *client) ListDatabaseGroup(ctx context.Context, project string) (*v1pb.ListDatabaseGroupsResponse, error) {
15+
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s/databaseGroups", c.url, c.version, project), nil)
16+
if err != nil {
17+
return nil, err
18+
}
19+
20+
body, err := c.doRequest(req)
21+
if err != nil {
22+
return nil, err
23+
}
24+
25+
var res v1pb.ListDatabaseGroupsResponse
26+
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
27+
return nil, err
28+
}
29+
30+
return &res, nil
31+
}
32+
33+
// CreateDatabaseGroup creates the database group.
34+
func (c *client) CreateDatabaseGroup(ctx context.Context, project, groupID string, group *v1pb.DatabaseGroup) (*v1pb.DatabaseGroup, error) {
35+
payload, err := protojson.Marshal(group)
36+
if err != nil {
37+
return nil, err
38+
}
39+
40+
req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s/databaseGroups?databaseGroupId=%s", c.url, c.version, project, groupID), strings.NewReader(string(payload)))
41+
42+
if err != nil {
43+
return nil, err
44+
}
45+
46+
body, err := c.doRequest(req)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
var res v1pb.DatabaseGroup
52+
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
53+
return nil, err
54+
}
55+
56+
return &res, nil
57+
}
58+
59+
// GetDatabaseGroup gets the database group by name.
60+
func (c *client) GetDatabaseGroup(ctx context.Context, name string, view v1pb.DatabaseGroupView) (*v1pb.DatabaseGroup, error) {
61+
// TODO(ed): query
62+
body, err := c.getResource(ctx, name, fmt.Sprintf("view=%s", view.String()))
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
var res v1pb.DatabaseGroup
68+
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
69+
return nil, err
70+
}
71+
72+
return &res, nil
73+
}
74+
75+
// UpdateDatabaseGroup updates the database group.
76+
func (c *client) UpdateDatabaseGroup(ctx context.Context, patch *v1pb.DatabaseGroup, updateMasks []string) (*v1pb.DatabaseGroup, error) {
77+
body, err := c.updateResource(ctx, patch.Name, patch, updateMasks, false /* allow missing = false*/)
78+
if err != nil {
79+
return nil, err
80+
}
81+
82+
var res v1pb.DatabaseGroup
83+
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
84+
return nil, err
85+
}
86+
87+
return &res, nil
88+
}
89+
90+
// DeleteDatabaseGroup deletes the database group by name.
91+
func (c *client) DeleteDatabaseGroup(ctx context.Context, name string) error {
92+
return c.deleteResource(ctx, name)
93+
}

client/group.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (c *client) CreateGroup(ctx context.Context, email string, group *v1pb.Grou
5959

6060
// GetGroup gets the group by name.
6161
func (c *client) GetGroup(ctx context.Context, name string) (*v1pb.Group, error) {
62-
body, err := c.getResource(ctx, name)
62+
body, err := c.getResource(ctx, name, "")
6363
if err != nil {
6464
return nil, err
6565
}

client/instance.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ func (c *client) listInstancePerPage(ctx context.Context, query, pageToken strin
116116

117117
// GetInstance gets the instance by full name.
118118
func (c *client) GetInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) {
119-
body, err := c.getResource(ctx, instanceName)
119+
body, err := c.getResource(ctx, instanceName, "")
120120
if err != nil {
121121
return nil, err
122122
}

client/policy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (c *client) ListPolicies(ctx context.Context, parent string) (*v1pb.ListPol
3636

3737
// GetPolicy gets a policy in a specific resource.
3838
func (c *client) GetPolicy(ctx context.Context, policyName string) (*v1pb.Policy, error) {
39-
body, err := c.getResource(ctx, policyName)
39+
body, err := c.getResource(ctx, policyName, "")
4040
if err != nil {
4141
return nil, err
4242
}

client/project.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
// GetProject gets the project by project full name.
1919
func (c *client) GetProject(ctx context.Context, projectName string) (*v1pb.Project, error) {
20-
body, err := c.getResource(ctx, projectName)
20+
body, err := c.getResource(ctx, projectName, "")
2121
if err != nil {
2222
return nil, err
2323
}
@@ -32,7 +32,7 @@ func (c *client) GetProject(ctx context.Context, projectName string) (*v1pb.Proj
3232

3333
// GetProjectIAMPolicy gets the project IAM policy by project full name.
3434
func (c *client) GetProjectIAMPolicy(ctx context.Context, projectName string) (*v1pb.IamPolicy, error) {
35-
body, err := c.getResource(ctx, fmt.Sprintf("%s:getIamPolicy", projectName))
35+
body, err := c.getResource(ctx, fmt.Sprintf("%s:getIamPolicy", projectName), "")
3636
if err != nil {
3737
return nil, err
3838
}

client/review_config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (c *client) ListReviewConfig(ctx context.Context) (*v1pb.ListReviewConfigsR
3030

3131
// GetReviewConfig gets the review config by full name.
3232
func (c *client) GetReviewConfig(ctx context.Context, reviewName string) (*v1pb.ReviewConfig, error) {
33-
body, err := c.getResource(ctx, reviewName)
33+
body, err := c.getResource(ctx, reviewName, "")
3434
if err != nil {
3535
return nil, err
3636
}

client/risk.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (c *client) ListRisk(ctx context.Context) ([]*v1pb.Risk, error) {
3232

3333
// GetRisk gets the risk by full name.
3434
func (c *client) GetRisk(ctx context.Context, name string) (*v1pb.Risk, error) {
35-
body, err := c.getResource(ctx, name)
35+
body, err := c.getResource(ctx, name, "")
3636
if err != nil {
3737
return nil, err
3838
}

client/role.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// GetRole gets the role by full name.
1414
func (c *client) GetRole(ctx context.Context, name string) (*v1pb.Role, error) {
15-
body, err := c.getResource(ctx, name)
15+
body, err := c.getResource(ctx, name, "")
1616
if err != nil {
1717
return nil, err
1818
}

client/setting.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (c *client) ListSettings(ctx context.Context) (*v1pb.ListSettingsResponse,
3030

3131
// GetSetting gets the setting by the name.
3232
func (c *client) GetSetting(ctx context.Context, settingName string) (*v1pb.Setting, error) {
33-
body, err := c.getResource(ctx, settingName)
33+
body, err := c.getResource(ctx, settingName, "")
3434
if err != nil {
3535
return nil, err
3636
}

client/user.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (c *client) CreateUser(ctx context.Context, user *v1pb.User) (*v1pb.User, e
136136

137137
// GetUser gets the user by name.
138138
func (c *client) GetUser(ctx context.Context, userName string) (*v1pb.User, error) {
139-
body, err := c.getResource(ctx, userName)
139+
body, err := c.getResource(ctx, userName, "")
140140
if err != nil {
141141
return nil, err
142142
}

client/workspace.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
// GetWorkspaceIAMPolicy gets the workspace IAM policy.
1414
func (c *client) GetWorkspaceIAMPolicy(ctx context.Context) (*v1pb.IamPolicy, error) {
15-
body, err := c.getResource(ctx, "workspaces/-:getIamPolicy")
15+
body, err := c.getResource(ctx, "workspaces/-:getIamPolicy", "")
1616
if err != nil {
1717
return nil, err
1818
}

docs/data-sources/database_group.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "bytebase_database_group Data Source - terraform-provider-bytebase"
4+
subcategory: ""
5+
description: |-
6+
The database group data source.
7+
---
8+
9+
# bytebase_database_group (Data Source)
10+
11+
The database group data source.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `project` (String) The project fullname in projects/{id} format.
21+
- `resource_id` (String) The database group unique resource id.
22+
23+
### Read-Only
24+
25+
- `condition` (String) The database group condition.
26+
- `id` (String) The ID of this resource.
27+
- `matched_databases` (Set of String) The matched databases in the group.
28+
- `title` (String) The database group title.
29+
30+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "bytebase_database_group_list Data Source - terraform-provider-bytebase"
4+
subcategory: ""
5+
description: |-
6+
The database group data source list.
7+
---
8+
9+
# bytebase_database_group_list (Data Source)
10+
11+
The database group data source list.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `project` (String) The project fullname in projects/{id} format.
21+
22+
### Read-Only
23+
24+
- `database_groups` (List of Object) (see [below for nested schema](#nestedatt--database_groups))
25+
- `id` (String) The ID of this resource.
26+
27+
<a id="nestedatt--database_groups"></a>
28+
### Nested Schema for `database_groups`
29+
30+
Read-Only:
31+
32+
- `condition` (String)
33+
- `name` (String)
34+
- `title` (String)
35+
36+

docs/resources/database_group.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "bytebase_database_group Resource - terraform-provider-bytebase"
4+
subcategory: ""
5+
description: |-
6+
The database group resource.
7+
---
8+
9+
# bytebase_database_group (Resource)
10+
11+
The database group resource.
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `condition` (String) The database group condition. Check the proto message https://github.com/bytebase/bytebase/blob/main/proto/v1/v1/database_group_service.proto#L185 for details.
21+
- `project` (String) The project fullname in projects/{id} format.
22+
- `resource_id` (String) The database group unique resource id.
23+
- `title` (String) The database group title.
24+
25+
### Read-Only
26+
27+
- `id` (String) The ID of this resource.
28+
- `matched_databases` (Set of String) The matched databases in the group.
29+
30+

docs/resources/risk.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ The risk resource. Require ENTERPRISE subscription. Check the docs https://www.b
1717

1818
### Required
1919

20-
- `condition` (String) The risk condition.
20+
- `condition` (String) The risk condition. Check the proto message https://github.com/bytebase/bytebase/blob/main/proto/v1/v1/risk_service.proto#L210 for details.
2121
- `level` (Number) The risk level.
2222
- `source` (String) The risk source.
2323
- `title` (String) The risk title.

examples/database_group/main.tf

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
terraform {
2+
required_providers {
3+
bytebase = {
4+
version = "3.6.0"
5+
# For local development, please use "terraform.local/bytebase/bytebase" instead
6+
source = "registry.terraform.io/bytebase/bytebase"
7+
}
8+
}
9+
}
10+
11+
provider "bytebase" {
12+
# You need to replace the account and key with your Bytebase service account.
13+
service_account = "[email protected]"
14+
service_key = "bbs_BxVIp7uQsARl8nR92ZZV"
15+
# The Bytebase service URL. You can use the external URL in production.
16+
# Check the docs about external URL: https://www.bytebase.com/docs/get-started/install/external-url
17+
url = "https://bytebase.example.com"
18+
}
19+
20+
data "bytebase_project" "sample_project" {
21+
resource_id = "sample-project"
22+
}
23+
24+
data "bytebase_database_group_list" "all" {
25+
depends_on = [data.bytebase_project.sample_project]
26+
project = data.bytebase_project.sample_project.name
27+
}
28+
29+
output "database_group_list" {
30+
value = data.bytebase_database_group_list.all
31+
}
32+
33+
resource "bytebase_database_group" "databases_in_test" {
34+
depends_on = [data.bytebase_project.sample_project]
35+
36+
resource_id = "databases-in-test"
37+
project = data.bytebase_project.sample_project.name
38+
title = "Databases in test env"
39+
condition = "resource.environment_name == \"test\""
40+
}
41+
42+
data "bytebase_database_group" "databases_in_test" {
43+
depends_on = [bytebase_database_group.databases_in_test]
44+
45+
resource_id = bytebase_database_group.databases_in_test.resource_id
46+
project = data.bytebase_project.sample_project.name
47+
}
48+
49+
output "database_group" {
50+
value = data.bytebase_database_group.databases_in_test
51+
}

0 commit comments

Comments
 (0)