Skip to content

feat: support database group #109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,15 @@ type Client interface {
UpdateRisk(ctx context.Context, patch *v1pb.Risk, updateMasks []string) (*v1pb.Risk, error)
// DeleteRisk deletes the risk by name.
DeleteRisk(ctx context.Context, name string) error

// ListDatabaseGroup list all database groups in a project.
ListDatabaseGroup(ctx context.Context, project string) (*v1pb.ListDatabaseGroupsResponse, error)
// CreateDatabaseGroup creates the database group.
CreateDatabaseGroup(ctx context.Context, project, groupID string, group *v1pb.DatabaseGroup) (*v1pb.DatabaseGroup, error)
// GetDatabaseGroup gets the database group by name.
GetDatabaseGroup(ctx context.Context, name string, view v1pb.DatabaseGroupView) (*v1pb.DatabaseGroup, error)
// UpdateDatabaseGroup updates the database group.
UpdateDatabaseGroup(ctx context.Context, patch *v1pb.DatabaseGroup, updateMasks []string) (*v1pb.DatabaseGroup, error)
// DeleteDatabaseGroup deletes the database group by name.
DeleteDatabaseGroup(ctx context.Context, name string) error
}
4 changes: 2 additions & 2 deletions client/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func (c *client) updateResource(ctx context.Context, name string, patch protoref
}

// getResource gets the resource by name.
func (c *client) getResource(ctx context.Context, name string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, url.QueryEscape(name)), nil)
func (c *client) getResource(ctx context.Context, name, query string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s?%s", c.url, c.version, url.QueryEscape(name), query), nil)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions client/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

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

// GetDatabaseCatalog gets the database catalog by the database full name.
func (c *client) GetDatabaseCatalog(ctx context.Context, databaseName string) (*v1pb.DatabaseCatalog, error) {
body, err := c.getResource(ctx, fmt.Sprintf("%s/catalog", databaseName))
body, err := c.getResource(ctx, fmt.Sprintf("%s/catalog", databaseName), "")
if err != nil {
return nil, err
}
Expand Down
93 changes: 93 additions & 0 deletions client/database_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package client

import (
"context"
"fmt"
"net/http"
"strings"

v1pb "github.com/bytebase/bytebase/proto/generated-go/v1"
"google.golang.org/protobuf/encoding/protojson"
)

// ListDatabaseGroup list all database groups in a project.
func (c *client) ListDatabaseGroup(ctx context.Context, project string) (*v1pb.ListDatabaseGroupsResponse, error) {
req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s/databaseGroups", c.url, c.version, project), nil)
if err != nil {
return nil, err
}

body, err := c.doRequest(req)
if err != nil {
return nil, err
}

var res v1pb.ListDatabaseGroupsResponse
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
return nil, err
}

return &res, nil
}

// CreateDatabaseGroup creates the database group.
func (c *client) CreateDatabaseGroup(ctx context.Context, project, groupID string, group *v1pb.DatabaseGroup) (*v1pb.DatabaseGroup, error) {
payload, err := protojson.Marshal(group)
if err != nil {
return nil, err
}

req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s/databaseGroups?databaseGroupId=%s", c.url, c.version, project, groupID), strings.NewReader(string(payload)))

if err != nil {
return nil, err
}

body, err := c.doRequest(req)
if err != nil {
return nil, err
}

var res v1pb.DatabaseGroup
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
return nil, err
}

return &res, nil
}

// GetDatabaseGroup gets the database group by name.
func (c *client) GetDatabaseGroup(ctx context.Context, name string, view v1pb.DatabaseGroupView) (*v1pb.DatabaseGroup, error) {
// TODO(ed): query
body, err := c.getResource(ctx, name, fmt.Sprintf("view=%s", view.String()))
if err != nil {
return nil, err
}

var res v1pb.DatabaseGroup
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
return nil, err
}

return &res, nil
}

// UpdateDatabaseGroup updates the database group.
func (c *client) UpdateDatabaseGroup(ctx context.Context, patch *v1pb.DatabaseGroup, updateMasks []string) (*v1pb.DatabaseGroup, error) {
body, err := c.updateResource(ctx, patch.Name, patch, updateMasks, false /* allow missing = false*/)
if err != nil {
return nil, err
}

var res v1pb.DatabaseGroup
if err := ProtojsonUnmarshaler.Unmarshal(body, &res); err != nil {
return nil, err
}

return &res, nil
}

// DeleteDatabaseGroup deletes the database group by name.
func (c *client) DeleteDatabaseGroup(ctx context.Context, name string) error {
return c.deleteResource(ctx, name)
}
2 changes: 1 addition & 1 deletion client/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (c *client) CreateGroup(ctx context.Context, email string, group *v1pb.Grou

// GetGroup gets the group by name.
func (c *client) GetGroup(ctx context.Context, name string) (*v1pb.Group, error) {
body, err := c.getResource(ctx, name)
body, err := c.getResource(ctx, name, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (c *client) listInstancePerPage(ctx context.Context, query, pageToken strin

// GetInstance gets the instance by full name.
func (c *client) GetInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) {
body, err := c.getResource(ctx, instanceName)
body, err := c.getResource(ctx, instanceName, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func (c *client) ListPolicies(ctx context.Context, parent string) (*v1pb.ListPol

// GetPolicy gets a policy in a specific resource.
func (c *client) GetPolicy(ctx context.Context, policyName string) (*v1pb.Policy, error) {
body, err := c.getResource(ctx, policyName)
body, err := c.getResource(ctx, policyName, "")
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions client/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

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

// GetProjectIAMPolicy gets the project IAM policy by project full name.
func (c *client) GetProjectIAMPolicy(ctx context.Context, projectName string) (*v1pb.IamPolicy, error) {
body, err := c.getResource(ctx, fmt.Sprintf("%s:getIamPolicy", projectName))
body, err := c.getResource(ctx, fmt.Sprintf("%s:getIamPolicy", projectName), "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/review_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (c *client) ListReviewConfig(ctx context.Context) (*v1pb.ListReviewConfigsR

// GetReviewConfig gets the review config by full name.
func (c *client) GetReviewConfig(ctx context.Context, reviewName string) (*v1pb.ReviewConfig, error) {
body, err := c.getResource(ctx, reviewName)
body, err := c.getResource(ctx, reviewName, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/risk.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (c *client) ListRisk(ctx context.Context) ([]*v1pb.Risk, error) {

// GetRisk gets the risk by full name.
func (c *client) GetRisk(ctx context.Context, name string) (*v1pb.Risk, error) {
body, err := c.getResource(ctx, name)
body, err := c.getResource(ctx, name, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// GetRole gets the role by full name.
func (c *client) GetRole(ctx context.Context, name string) (*v1pb.Role, error) {
body, err := c.getResource(ctx, name)
body, err := c.getResource(ctx, name, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (c *client) ListSettings(ctx context.Context) (*v1pb.ListSettingsResponse,

// GetSetting gets the setting by the name.
func (c *client) GetSetting(ctx context.Context, settingName string) (*v1pb.Setting, error) {
body, err := c.getResource(ctx, settingName)
body, err := c.getResource(ctx, settingName, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (c *client) CreateUser(ctx context.Context, user *v1pb.User) (*v1pb.User, e

// GetUser gets the user by name.
func (c *client) GetUser(ctx context.Context, userName string) (*v1pb.User, error) {
body, err := c.getResource(ctx, userName)
body, err := c.getResource(ctx, userName, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion client/workspace.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// GetWorkspaceIAMPolicy gets the workspace IAM policy.
func (c *client) GetWorkspaceIAMPolicy(ctx context.Context) (*v1pb.IamPolicy, error) {
body, err := c.getResource(ctx, "workspaces/-:getIamPolicy")
body, err := c.getResource(ctx, "workspaces/-:getIamPolicy", "")
if err != nil {
return nil, err
}
Expand Down
30 changes: 30 additions & 0 deletions docs/data-sources/database_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "bytebase_database_group Data Source - terraform-provider-bytebase"
subcategory: ""
description: |-
The database group data source.
---

# bytebase_database_group (Data Source)

The database group data source.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `project` (String) The project fullname in projects/{id} format.
- `resource_id` (String) The database group unique resource id.

### Read-Only

- `condition` (String) The database group condition.
- `id` (String) The ID of this resource.
- `matched_databases` (Set of String) The matched databases in the group.
- `title` (String) The database group title.


36 changes: 36 additions & 0 deletions docs/data-sources/database_group_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "bytebase_database_group_list Data Source - terraform-provider-bytebase"
subcategory: ""
description: |-
The database group data source list.
---

# bytebase_database_group_list (Data Source)

The database group data source list.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `project` (String) The project fullname in projects/{id} format.

### Read-Only

- `database_groups` (List of Object) (see [below for nested schema](#nestedatt--database_groups))
- `id` (String) The ID of this resource.

<a id="nestedatt--database_groups"></a>
### Nested Schema for `database_groups`

Read-Only:

- `condition` (String)
- `name` (String)
- `title` (String)


30 changes: 30 additions & 0 deletions docs/resources/database_group.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "bytebase_database_group Resource - terraform-provider-bytebase"
subcategory: ""
description: |-
The database group resource.
---

# bytebase_database_group (Resource)

The database group resource.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `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.
- `project` (String) The project fullname in projects/{id} format.
- `resource_id` (String) The database group unique resource id.
- `title` (String) The database group title.

### Read-Only

- `id` (String) The ID of this resource.
- `matched_databases` (Set of String) The matched databases in the group.


2 changes: 1 addition & 1 deletion docs/resources/risk.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ The risk resource. Require ENTERPRISE subscription. Check the docs https://www.b

### Required

- `condition` (String) The risk condition.
- `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.
- `level` (Number) The risk level.
- `source` (String) The risk source.
- `title` (String) The risk title.
Expand Down
51 changes: 51 additions & 0 deletions examples/database_group/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
terraform {
required_providers {
bytebase = {
version = "3.6.0"
# For local development, please use "terraform.local/bytebase/bytebase" instead
source = "registry.terraform.io/bytebase/bytebase"
}
}
}

provider "bytebase" {
# You need to replace the account and key with your Bytebase service account.
service_account = "[email protected]"
service_key = "bbs_BxVIp7uQsARl8nR92ZZV"
# The Bytebase service URL. You can use the external URL in production.
# Check the docs about external URL: https://www.bytebase.com/docs/get-started/install/external-url
url = "https://bytebase.example.com"
}

data "bytebase_project" "sample_project" {
resource_id = "sample-project"
}

data "bytebase_database_group_list" "all" {
depends_on = [data.bytebase_project.sample_project]
project = data.bytebase_project.sample_project.name
}

output "database_group_list" {
value = data.bytebase_database_group_list.all
}

resource "bytebase_database_group" "databases_in_test" {
depends_on = [data.bytebase_project.sample_project]

resource_id = "databases-in-test"
project = data.bytebase_project.sample_project.name
title = "Databases in test env"
condition = "resource.environment_name == \"test\""
}

data "bytebase_database_group" "databases_in_test" {
depends_on = [bytebase_database_group.databases_in_test]

resource_id = bytebase_database_group.databases_in_test.resource_id
project = data.bytebase_project.sample_project.name
}

output "database_group" {
value = data.bytebase_database_group.databases_in_test
}
Loading