diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b0be04e..81983ff 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,21 +13,20 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.23.2 - run: go generate ./... - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v6 with: - version: v1.49.0 - args: -v - skip-cache: true + version: v1.60.2 + args: --verbose --timeout 20m --max-same-issues=30 --allow-parallel-runners go-tidy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.23.2 - name: Verify tidy run: | go mod tidy @@ -41,7 +40,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v3 with: - go-version: 1.19 + go-version: 1.23.2 - uses: hashicorp/setup-terraform@v2 with: terraform_version: "1.3.*" diff --git a/.golangci.yaml b/.golangci.yaml index 21ac82b..27ee1e4 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -73,6 +73,10 @@ linters-settings: disabled: true - name: early-return disabled: true + - name: use-any + disabled: true + - name: unchecked-type-assertion + disabled: true gocritic: disabled-checks: - ifElseChain diff --git a/api/auth.go b/api/auth.go deleted file mode 100644 index 9737da5..0000000 --- a/api/auth.go +++ /dev/null @@ -1,12 +0,0 @@ -package api - -// Login is the API message for user login. -type Login struct { - Email string `json:"email"` - Password string `json:"password"` -} - -// AuthResponse is the API message for user login response. -type AuthResponse struct { - Token string `json:"token"` -} diff --git a/api/client.go b/api/client.go index 483363f..32fa5b7 100644 --- a/api/client.go +++ b/api/client.go @@ -1,40 +1,44 @@ package api -import "context" +import ( + "context" + + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" +) // Client is the API message for Bytebase OpenAPI client. type Client interface { // Auth // Login will login the user and get the response. - Login() (*AuthResponse, error) + Login() (*v1pb.LoginResponse, error) // Environment // CreateEnvironment creates the environment. - CreateEnvironment(ctx context.Context, environmentID string, create *EnvironmentMessage) (*EnvironmentMessage, error) + CreateEnvironment(ctx context.Context, environmentID string, create *v1pb.Environment) (*v1pb.Environment, error) // GetEnvironment gets the environment by id. - GetEnvironment(ctx context.Context, environmentName string) (*EnvironmentMessage, error) + GetEnvironment(ctx context.Context, environmentName string) (*v1pb.Environment, error) // ListEnvironment finds all environments. - ListEnvironment(ctx context.Context, showDeleted bool) (*ListEnvironmentMessage, error) + ListEnvironment(ctx context.Context, showDeleted bool) (*v1pb.ListEnvironmentsResponse, error) // UpdateEnvironment updates the environment. - UpdateEnvironment(ctx context.Context, patch *EnvironmentPatchMessage) (*EnvironmentMessage, error) + UpdateEnvironment(ctx context.Context, patch *v1pb.Environment, updateMask []string) (*v1pb.Environment, error) // DeleteEnvironment deletes the environment. DeleteEnvironment(ctx context.Context, environmentName string) error // UndeleteEnvironment undeletes the environment. - UndeleteEnvironment(ctx context.Context, environmentName string) (*EnvironmentMessage, error) + UndeleteEnvironment(ctx context.Context, environmentName string) (*v1pb.Environment, error) // Instance // ListInstance will return instances. - ListInstance(ctx context.Context, find *InstanceFindMessage) (*ListInstanceMessage, error) + ListInstance(ctx context.Context, showDeleted bool) (*v1pb.ListInstancesResponse, error) // GetInstance gets the instance by id. - GetInstance(ctx context.Context, instanceName string) (*InstanceMessage, error) + GetInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) // CreateInstance creates the instance. - CreateInstance(ctx context.Context, instanceID string, instance *InstanceMessage) (*InstanceMessage, error) + CreateInstance(ctx context.Context, instanceID string, instance *v1pb.Instance) (*v1pb.Instance, error) // UpdateInstance updates the instance. - UpdateInstance(ctx context.Context, patch *InstancePatchMessage) (*InstanceMessage, error) + UpdateInstance(ctx context.Context, patch *v1pb.Instance, updateMasks []string) (*v1pb.Instance, error) // DeleteInstance deletes the instance. DeleteInstance(ctx context.Context, instanceName string) error // UndeleteInstance undeletes the instance. - UndeleteInstance(ctx context.Context, instanceName string) (*InstanceMessage, error) + UndeleteInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) // SyncInstanceSchema will trigger the schema sync for an instance. SyncInstanceSchema(ctx context.Context, instanceName string) error @@ -50,23 +54,23 @@ type Client interface { // Database // GetDatabase gets the database by instance resource id and the database name. - GetDatabase(ctx context.Context, databaseName string) (*DatabaseMessage, error) + GetDatabase(ctx context.Context, databaseName string) (*v1pb.Database, error) // ListDatabase list the databases. - ListDatabase(ctx context.Context, find *DatabaseFindMessage) (*ListDatabaseMessage, error) + ListDatabase(ctx context.Context, instanceID, filter string) (*v1pb.ListDatabasesResponse, error) // UpdateDatabase patches the database. - UpdateDatabase(ctx context.Context, patch *DatabasePatchMessage) (*DatabaseMessage, error) + UpdateDatabase(ctx context.Context, patch *v1pb.Database, updateMasks []string) (*v1pb.Database, error) // Project // GetProject gets the project by resource id. - GetProject(ctx context.Context, projectName string) (*ProjectMessage, error) + GetProject(ctx context.Context, projectName string) (*v1pb.Project, error) // ListProject list the projects, - ListProject(ctx context.Context, showDeleted bool) (*ListProjectMessage, error) + ListProject(ctx context.Context, showDeleted bool) (*v1pb.ListProjectsResponse, error) // CreateProject creates the project. - CreateProject(ctx context.Context, projectID string, project *ProjectMessage) (*ProjectMessage, error) + CreateProject(ctx context.Context, projectID string, project *v1pb.Project) (*v1pb.Project, error) // UpdateProject updates the project. - UpdateProject(ctx context.Context, patch *ProjectPatchMessage) (*ProjectMessage, error) + UpdateProject(ctx context.Context, patch *v1pb.Project, updateMask []string) (*v1pb.Project, error) // DeleteProject deletes the project. DeleteProject(ctx context.Context, projectName string) error // UndeleteProject undeletes the project. - UndeleteProject(ctx context.Context, projectName string) (*ProjectMessage, error) + UndeleteProject(ctx context.Context, projectName string) (*v1pb.Project, error) } diff --git a/api/common.go b/api/common.go deleted file mode 100644 index b6a5daf..0000000 --- a/api/common.go +++ /dev/null @@ -1,45 +0,0 @@ -package api - -// State is the state for a row. -type State string - -const ( - // Active is the state for a normal row. - Active State = "ACTIVE" - // Deleted is the state for an removed row. - Deleted State = "DELETED" -) - -// EngineType is the type of the instance engine. -type EngineType string - -const ( - // EngineTypeMySQL is the database type for MYSQL. - EngineTypeMySQL EngineType = "MYSQL" - // EngineTypePostgres is the database type for POSTGRES. - EngineTypePostgres EngineType = "POSTGRES" - // EngineTypeTiDB is the database type for TiDB. - EngineTypeTiDB EngineType = "TIDB" - // EngineTypeSnowflake is the database type for SNOWFLAKE. - EngineTypeSnowflake EngineType = "SNOWFLAKE" - // EngineTypeClickHouse is the database type for CLICKHOUSE. - EngineTypeClickHouse EngineType = "CLICKHOUSE" - // EngineTypeMongoDB is the database type for MongoDB. - EngineTypeMongoDB EngineType = "MONGODB" - // EngineTypeSQLite is the database type for SQLite. - EngineTypeSQLite EngineType = "SQLITE" - // EngineTypeRedis is the database type for REDIS. - EngineTypeRedis EngineType = "REDIS" - // EngineTypeOracle is the database type for ORACLE. - EngineTypeOracle EngineType = "ORACLE" - // EngineTypeSpanner is the database type for SPANNER. - EngineTypeSpanner EngineType = "SPANNER" - // EngineTypeMSSQL is the database type for MSSQL. - EngineTypeMSSQL EngineType = "MSSQL" - // EngineTypeRedshift is the database type for REDSHIFT. - EngineTypeRedshift EngineType = "REDSHIFT" - // EngineTypeMariaDB is the database type for MARIADB. - EngineTypeMariaDB EngineType = "MARIADB" - // EngineTypeOceanbase is the database type for OCEANBASE. - EngineTypeOceanbase EngineType = "OCEANBASE" -) diff --git a/api/data_source.go b/api/data_source.go deleted file mode 100644 index d174bb4..0000000 --- a/api/data_source.go +++ /dev/null @@ -1,25 +0,0 @@ -package api - -// DataSourceType is the type for data source. -type DataSourceType string - -const ( - // DataSourceAdmin is the ADMIN type of data source. - DataSourceAdmin DataSourceType = "ADMIN" - // DataSourceRO is the read-only type of data source. - DataSourceRO DataSourceType = "READ_ONLY" -) - -// DataSourceMessage is the API message for a data source. -type DataSourceMessage struct { - ID string `json:"id"` - Type DataSourceType `json:"type"` - Username string `json:"username"` - Password string `json:"password"` - SslCa string `json:"sslCa"` - SslCert string `json:"sslCert"` - SslKey string `json:"sslKey"` - Host string `json:"host"` - Port string `json:"port"` - Database string `json:"database"` -} diff --git a/api/database.go b/api/database.go deleted file mode 100644 index 2f7cf3c..0000000 --- a/api/database.go +++ /dev/null @@ -1,35 +0,0 @@ -package api - -// DatabaseFindMessage is the API message for finding database. -type DatabaseFindMessage struct { - InstanceID string - DatabaseName string - Filter *string -} - -// DatabaseMessage is the API message for database. -type DatabaseMessage struct { - // Format: instances/{unique resource id}/databases/{database name} - Name string `json:"name"` - // Format: projects/{unique resource id} - Project string `json:"project"` - // Format: environments/{unique resource id} - Environment string `json:"environment"` - SchemaVersion string `json:"schemaVersion"` - SyncState State `json:"syncState"` - SuccessfulSyncTime string `json:"successfulSyncTime"` - Labels map[string]string `json:"labels"` -} - -// ListDatabaseMessage is the API message for list database response. -type ListDatabaseMessage struct { - Databases []*DatabaseMessage `json:"databases"` - NextPageToken string `json:"nextPageToken"` -} - -// DatabasePatchMessage is the API message to patch the database. -type DatabasePatchMessage struct { - Name string `json:"name"` - Project *string `json:"project"` - Labels *map[string]string `json:"labels"` -} diff --git a/api/environment.go b/api/environment.go deleted file mode 100644 index 5a1bd8b..0000000 --- a/api/environment.go +++ /dev/null @@ -1,36 +0,0 @@ -package api - -// EnvironmentTier is the protection info for environment. -type EnvironmentTier string - -const ( - // EnvironmentTierProtected is the PROTECTED tier. - EnvironmentTierProtected EnvironmentTier = "PROTECTED" - // EnvironmentTierUnProtected is the UNPROTECTED tier. - EnvironmentTierUnProtected EnvironmentTier = "UNPROTECTED" -) - -// EnvironmentMessage is the API message for an environment. -type EnvironmentMessage struct { - // Domain specific fields - // Format: environments/{unique resource id} - Name string `json:"name"` - Title string `json:"title"` - Order int `json:"order"` - State State `json:"state,omitempty"` - Tier EnvironmentTier `json:"tier"` -} - -// ListEnvironmentMessage is the API message for list environment response. -type ListEnvironmentMessage struct { - Environments []*EnvironmentMessage `json:"environments"` - NextPageToken string `json:"nextPageToken"` -} - -// EnvironmentPatchMessage is the API message to patch the environment. -type EnvironmentPatchMessage struct { - Name string `json:"name"` - Title *string `json:"title,omitempty"` - Order *int `json:"order,omitempty"` - Tier *EnvironmentTier `json:"tier,omitempty"` -} diff --git a/api/instance.go b/api/instance.go deleted file mode 100644 index 0b4423d..0000000 --- a/api/instance.go +++ /dev/null @@ -1,34 +0,0 @@ -package api - -// InstanceMessage is the API message for an instance. -type InstanceMessage struct { - // Format: instances/{unique resource id} - Name string `json:"name"` - State State `json:"state,omitempty"` - Title string `json:"title"` - Engine EngineType `json:"engine"` - ExternalLink string `json:"externalLink"` - DataSources []*DataSourceMessage `json:"dataSources"` - // Environment is the environment id with format environments/{resource id} - Environment string `json:"environment"` -} - -// InstancePatchMessage is the API message to patch the instance. -type InstancePatchMessage struct { - Name string `json:"name"` - Title *string `json:"title,omitempty"` - ExternalLink *string `json:"externalLink,omitempty"` - DataSources []*DataSourceMessage `json:"dataSources,omitempty"` -} - -// InstanceFindMessage is the API message for finding instance. -type InstanceFindMessage struct { - InstanceID string - ShowDeleted bool -} - -// ListInstanceMessage is the API message for list instance response. -type ListInstanceMessage struct { - Instances []*InstanceMessage `json:"instances"` - NextPageToken string `json:"nextPageToken"` -} diff --git a/api/project.go b/api/project.go deleted file mode 100644 index 2bed62e..0000000 --- a/api/project.go +++ /dev/null @@ -1,35 +0,0 @@ -package api - -// ProjectWorkflow is the workflow for project. -type ProjectWorkflow string - -const ( - // ProjectWorkflowUI is the UI workflow type. - ProjectWorkflowUI ProjectWorkflow = "UI" - // ProjectWorkflowVCS is the VCS workflow type. - ProjectWorkflowVCS ProjectWorkflow = "VCS" -) - -// ProjectMessage is the API message for project. -type ProjectMessage struct { - // Format: projects/{unique resource id} - Name string `json:"name"` - Title string `json:"title"` - Key string `json:"key"` - Workflow ProjectWorkflow `json:"workflow"` - State State `json:"state,omitempty"` -} - -// ListProjectMessage is the API message for list project response. -type ListProjectMessage struct { - Projects []*ProjectMessage `json:"projects"` - NextPageToken string `json:"nextPageToken"` -} - -// ProjectPatchMessage is the API message to patch the project. -type ProjectPatchMessage struct { - // Format: projects/{unique resource id} - Name string `json:"name"` - Title *string `json:"title,omitempty"` - Key *string `json:"key,omitempty"` -} diff --git a/client/auth.go b/client/auth.go index 71d1a85..31b7fed 100644 --- a/client/auth.go +++ b/client/auth.go @@ -1,22 +1,22 @@ package client import ( - "encoding/json" "fmt" "net/http" "strings" "github.com/pkg/errors" + "google.golang.org/protobuf/encoding/protojson" - "github.com/bytebase/terraform-provider-bytebase/api" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" ) // Login will login the user and get the response. -func (c *client) Login() (*api.AuthResponse, error) { +func (c *client) Login() (*v1pb.LoginResponse, error) { if c.auth.Email == "" || c.auth.Password == "" { return nil, errors.Errorf("define username and password") } - rb, err := json.Marshal(c.auth) + rb, err := protojson.Marshal(c.auth) if err != nil { return nil, err } @@ -31,9 +31,8 @@ func (c *client) Login() (*api.AuthResponse, error) { return nil, err } - ar := api.AuthResponse{} - err = json.Unmarshal(body, &ar) - if err != nil { + ar := v1pb.LoginResponse{} + if err := ProtojsonUnmarshaler.Unmarshal(body, &ar); err != nil { return nil, err } diff --git a/client/client.go b/client/client.go index 608d897..208fbeb 100644 --- a/client/client.go +++ b/client/client.go @@ -9,6 +9,8 @@ import ( "github.com/pkg/errors" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "github.com/bytebase/terraform-provider-bytebase/api" ) @@ -18,7 +20,7 @@ type client struct { version string client *http.Client token string - auth *api.Login + auth *v1pb.LoginRequest } // NewClient returns the new Bytebase API client. @@ -29,7 +31,7 @@ func NewClient(url, version, email, password string) (api.Client, error) { version: version, } - c.auth = &api.Login{ + c.auth = &v1pb.LoginRequest{ Email: email, Password: password, } diff --git a/client/common.go b/client/common.go new file mode 100644 index 0000000..92d30fa --- /dev/null +++ b/client/common.go @@ -0,0 +1,8 @@ +package client + +import ( + "google.golang.org/protobuf/encoding/protojson" +) + +// ProtojsonUnmarshaler is the unmarshal for protocol. +var ProtojsonUnmarshaler = protojson.UnmarshalOptions{DiscardUnknown: true} diff --git a/client/database.go b/client/database.go index 04b704f..6788eb4 100644 --- a/client/database.go +++ b/client/database.go @@ -2,17 +2,17 @@ package client import ( "context" - "encoding/json" "fmt" "net/http" "net/url" "strings" - "github.com/bytebase/terraform-provider-bytebase/api" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "google.golang.org/protobuf/encoding/protojson" ) // GetDatabase gets the database by environment resource id, instance resource id and the database name. -func (c *client) GetDatabase(ctx context.Context, databaseName string) (*api.DatabaseMessage, error) { +func (c *client) GetDatabase(ctx context.Context, databaseName string) (*v1pb.Database, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, databaseName), nil) if err != nil { return nil, err @@ -23,8 +23,8 @@ func (c *client) GetDatabase(ctx context.Context, databaseName string) (*api.Dat return nil, err } - var res api.DatabaseMessage - err = json.Unmarshal(body, &res) + var res v1pb.Database + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -33,10 +33,10 @@ func (c *client) GetDatabase(ctx context.Context, databaseName string) (*api.Dat } // ListDatabase list the databases. -func (c *client) ListDatabase(ctx context.Context, find *api.DatabaseFindMessage) (*api.ListDatabaseMessage, error) { - requestURL := fmt.Sprintf("%s/%s/instances/%s/databases", c.url, c.version, find.InstanceID) - if v := find.Filter; v != nil { - requestURL = fmt.Sprintf("%s?filter=%s", requestURL, url.QueryEscape(*v)) +func (c *client) ListDatabase(ctx context.Context, instanceID, filter string) (*v1pb.ListDatabasesResponse, error) { + requestURL := fmt.Sprintf("%s/%s/instances/%s/databases", c.url, c.version, instanceID) + if filter != "" { + requestURL = fmt.Sprintf("%s?filter=%s", requestURL, url.QueryEscape(filter)) } req, err := http.NewRequestWithContext(ctx, "GET", requestURL, nil) @@ -49,8 +49,8 @@ func (c *client) ListDatabase(ctx context.Context, find *api.DatabaseFindMessage return nil, err } - var res api.ListDatabaseMessage - err = json.Unmarshal(body, &res) + var res v1pb.ListDatabasesResponse + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -59,21 +59,21 @@ func (c *client) ListDatabase(ctx context.Context, find *api.DatabaseFindMessage } // UpdateDatabase patches the database. -func (c *client) UpdateDatabase(ctx context.Context, patch *api.DatabasePatchMessage) (*api.DatabaseMessage, error) { - payload, err := json.Marshal(patch) +func (c *client) UpdateDatabase(ctx context.Context, patch *v1pb.Database, updateMasks []string) (*v1pb.Database, error) { + payload, err := protojson.Marshal(patch) if err != nil { return nil, err } - updateMask := []string{} - if patch.Project != nil { - updateMask = append(updateMask, "project") - } - if patch.Labels != nil { - updateMask = append(updateMask, "labels") - } + // updateMask := []string{} + // if patch.Project != nil { + // updateMask = append(updateMask, "project") + // } + // if patch.Labels != nil { + // updateMask = append(updateMask, "labels") + // } - req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(updateMask, ",")), strings.NewReader(string(payload))) + req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(updateMasks, ",")), strings.NewReader(string(payload))) if err != nil { return nil, err } @@ -83,8 +83,8 @@ func (c *client) UpdateDatabase(ctx context.Context, patch *api.DatabasePatchMes return nil, err } - var res api.DatabaseMessage - err = json.Unmarshal(body, &res) + var res v1pb.Database + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } diff --git a/client/environment.go b/client/environment.go index afbc1af..b2478fb 100644 --- a/client/environment.go +++ b/client/environment.go @@ -2,17 +2,17 @@ package client import ( "context" - "encoding/json" "fmt" "net/http" "strings" - "github.com/bytebase/terraform-provider-bytebase/api" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "google.golang.org/protobuf/encoding/protojson" ) // CreateEnvironment creates the environment. -func (c *client) CreateEnvironment(ctx context.Context, environmentID string, create *api.EnvironmentMessage) (*api.EnvironmentMessage, error) { - payload, err := json.Marshal(create) +func (c *client) CreateEnvironment(ctx context.Context, environmentID string, create *v1pb.Environment) (*v1pb.Environment, error) { + payload, err := protojson.Marshal(create) if err != nil { return nil, err } @@ -27,8 +27,8 @@ func (c *client) CreateEnvironment(ctx context.Context, environmentID string, cr return nil, err } - var env api.EnvironmentMessage - err = json.Unmarshal(body, &env) + var env v1pb.Environment + err = ProtojsonUnmarshaler.Unmarshal(body, &env) if err != nil { return nil, err } @@ -37,7 +37,7 @@ func (c *client) CreateEnvironment(ctx context.Context, environmentID string, cr } // GetEnvironment gets the environment by id. -func (c *client) GetEnvironment(ctx context.Context, environmentName string) (*api.EnvironmentMessage, error) { +func (c *client) GetEnvironment(ctx context.Context, environmentName string) (*v1pb.Environment, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, environmentName), nil) if err != nil { return nil, err @@ -48,8 +48,8 @@ func (c *client) GetEnvironment(ctx context.Context, environmentName string) (*a return nil, err } - var env api.EnvironmentMessage - err = json.Unmarshal(body, &env) + var env v1pb.Environment + err = ProtojsonUnmarshaler.Unmarshal(body, &env) if err != nil { return nil, err } @@ -58,7 +58,7 @@ func (c *client) GetEnvironment(ctx context.Context, environmentName string) (*a } // ListEnvironment finds all environments. -func (c *client) ListEnvironment(ctx context.Context, showDeleted bool) (*api.ListEnvironmentMessage, error) { +func (c *client) ListEnvironment(ctx context.Context, showDeleted bool) (*v1pb.ListEnvironmentsResponse, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/environments?showDeleted=%v", c.url, c.version, showDeleted), nil) if err != nil { return nil, err @@ -69,8 +69,8 @@ func (c *client) ListEnvironment(ctx context.Context, showDeleted bool) (*api.Li return nil, err } - var res api.ListEnvironmentMessage - err = json.Unmarshal(body, &res) + var res v1pb.ListEnvironmentsResponse + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -79,24 +79,13 @@ func (c *client) ListEnvironment(ctx context.Context, showDeleted bool) (*api.Li } // UpdateEnvironment updates the environment. -func (c *client) UpdateEnvironment(ctx context.Context, patch *api.EnvironmentPatchMessage) (*api.EnvironmentMessage, error) { - payload, err := json.Marshal(patch) +func (c *client) UpdateEnvironment(ctx context.Context, patch *v1pb.Environment, updateMask []string) (*v1pb.Environment, error) { + payload, err := protojson.Marshal(patch) if err != nil { return nil, err } - paths := []string{} - if patch.Title != nil { - paths = append(paths, "title") - } - if patch.Order != nil { - paths = append(paths, "order") - } - if patch.Tier != nil { - paths = append(paths, "tier") - } - - req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(paths, ",")), strings.NewReader(string(payload))) + req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(updateMask, ",")), strings.NewReader(string(payload))) if err != nil { return nil, err } @@ -106,8 +95,8 @@ func (c *client) UpdateEnvironment(ctx context.Context, patch *api.EnvironmentPa return nil, err } - var env api.EnvironmentMessage - err = json.Unmarshal(body, &env) + var env v1pb.Environment + err = ProtojsonUnmarshaler.Unmarshal(body, &env) if err != nil { return nil, err } @@ -129,7 +118,7 @@ func (c *client) DeleteEnvironment(ctx context.Context, environmentName string) } // UndeleteEnvironment undeletes the environment. -func (c *client) UndeleteEnvironment(ctx context.Context, environmentName string) (*api.EnvironmentMessage, error) { +func (c *client) UndeleteEnvironment(ctx context.Context, environmentName string) (*v1pb.Environment, error) { req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s:undelete", c.url, c.version, environmentName), nil) if err != nil { return nil, err @@ -140,8 +129,8 @@ func (c *client) UndeleteEnvironment(ctx context.Context, environmentName string return nil, err } - var res api.EnvironmentMessage - err = json.Unmarshal(body, &res) + var res v1pb.Environment + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } diff --git a/client/instance.go b/client/instance.go index ac5977a..569fbe5 100644 --- a/client/instance.go +++ b/client/instance.go @@ -2,17 +2,17 @@ package client import ( "context" - "encoding/json" "fmt" "net/http" "strings" - "github.com/bytebase/terraform-provider-bytebase/api" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "google.golang.org/protobuf/encoding/protojson" ) // ListInstance will return instances in environment. -func (c *client) ListInstance(ctx context.Context, find *api.InstanceFindMessage) (*api.ListInstanceMessage, error) { - req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/instances?showDeleted=%v", c.url, c.version, find.ShowDeleted), nil) +func (c *client) ListInstance(ctx context.Context, showDeleted bool) (*v1pb.ListInstancesResponse, error) { + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/instances?showDeleted=%v", c.url, c.version, showDeleted), nil) if err != nil { return nil, err } @@ -22,8 +22,8 @@ func (c *client) ListInstance(ctx context.Context, find *api.InstanceFindMessage return nil, err } - var res api.ListInstanceMessage - err = json.Unmarshal(body, &res) + var res v1pb.ListInstancesResponse + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -32,7 +32,7 @@ func (c *client) ListInstance(ctx context.Context, find *api.InstanceFindMessage } // GetInstance gets the instance by id. -func (c *client) GetInstance(ctx context.Context, instanceName string) (*api.InstanceMessage, error) { +func (c *client) GetInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, instanceName), nil) if err != nil { return nil, err @@ -43,8 +43,8 @@ func (c *client) GetInstance(ctx context.Context, instanceName string) (*api.Ins return nil, err } - var res api.InstanceMessage - err = json.Unmarshal(body, &res) + var res v1pb.Instance + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -53,8 +53,8 @@ func (c *client) GetInstance(ctx context.Context, instanceName string) (*api.Ins } // CreateInstance creates the instance. -func (c *client) CreateInstance(ctx context.Context, instanceID string, instance *api.InstanceMessage) (*api.InstanceMessage, error) { - payload, err := json.Marshal(instance) +func (c *client) CreateInstance(ctx context.Context, instanceID string, instance *v1pb.Instance) (*v1pb.Instance, error) { + payload, err := protojson.Marshal(instance) if err != nil { return nil, err } @@ -70,8 +70,8 @@ func (c *client) CreateInstance(ctx context.Context, instanceID string, instance return nil, err } - var res api.InstanceMessage - err = json.Unmarshal(body, &res) + var res v1pb.Instance + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -80,24 +80,13 @@ func (c *client) CreateInstance(ctx context.Context, instanceID string, instance } // UpdateInstance updates the instance. -func (c *client) UpdateInstance(ctx context.Context, patch *api.InstancePatchMessage) (*api.InstanceMessage, error) { - payload, err := json.Marshal(patch) +func (c *client) UpdateInstance(ctx context.Context, patch *v1pb.Instance, updateMasks []string) (*v1pb.Instance, error) { + payload, err := protojson.Marshal(patch) if err != nil { return nil, err } - paths := []string{} - if patch.Title != nil { - paths = append(paths, "title") - } - if patch.ExternalLink != nil { - paths = append(paths, "external_link") - } - if patch.DataSources != nil { - paths = append(paths, "data_sources") - } - - req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(paths, ",")), strings.NewReader(string(payload))) + req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(updateMasks, ",")), strings.NewReader(string(payload))) if err != nil { return nil, err @@ -108,8 +97,8 @@ func (c *client) UpdateInstance(ctx context.Context, patch *api.InstancePatchMes return nil, err } - var res api.InstanceMessage - err = json.Unmarshal(body, &res) + var res v1pb.Instance + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -131,7 +120,7 @@ func (c *client) DeleteInstance(ctx context.Context, instanceName string) error } // UndeleteInstance undeletes the instance. -func (c *client) UndeleteInstance(ctx context.Context, instanceName string) (*api.InstanceMessage, error) { +func (c *client) UndeleteInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) { req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s:undelete", c.url, c.version, instanceName), nil) if err != nil { return nil, err @@ -142,8 +131,8 @@ func (c *client) UndeleteInstance(ctx context.Context, instanceName string) (*ap return nil, err } - var res api.InstanceMessage - err = json.Unmarshal(body, &res) + var res v1pb.Instance + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } diff --git a/client/project.go b/client/project.go index 82011b4..dcb21f8 100644 --- a/client/project.go +++ b/client/project.go @@ -2,16 +2,16 @@ package client import ( "context" - "encoding/json" "fmt" "net/http" "strings" - "github.com/bytebase/terraform-provider-bytebase/api" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "google.golang.org/protobuf/encoding/protojson" ) // GetProject gets the project by resource id. -func (c *client) GetProject(ctx context.Context, projectName string) (*api.ProjectMessage, error) { +func (c *client) GetProject(ctx context.Context, projectName string) (*v1pb.Project, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/%s", c.url, c.version, projectName), nil) if err != nil { return nil, err @@ -22,8 +22,8 @@ func (c *client) GetProject(ctx context.Context, projectName string) (*api.Proje return nil, err } - var res api.ProjectMessage - err = json.Unmarshal(body, &res) + var res v1pb.Project + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -32,7 +32,7 @@ func (c *client) GetProject(ctx context.Context, projectName string) (*api.Proje } // ListProject list the projects. -func (c *client) ListProject(ctx context.Context, showDeleted bool) (*api.ListProjectMessage, error) { +func (c *client) ListProject(ctx context.Context, showDeleted bool) (*v1pb.ListProjectsResponse, error) { req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/%s/projects?showDeleted=%v", c.url, c.version, showDeleted), nil) if err != nil { return nil, err @@ -43,8 +43,8 @@ func (c *client) ListProject(ctx context.Context, showDeleted bool) (*api.ListPr return nil, err } - var res api.ListProjectMessage - err = json.Unmarshal(body, &res) + var res v1pb.ListProjectsResponse + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -53,8 +53,8 @@ func (c *client) ListProject(ctx context.Context, showDeleted bool) (*api.ListPr } // CreateProject creates the project. -func (c *client) CreateProject(ctx context.Context, projectID string, project *api.ProjectMessage) (*api.ProjectMessage, error) { - payload, err := json.Marshal(project) +func (c *client) CreateProject(ctx context.Context, projectID string, project *v1pb.Project) (*v1pb.Project, error) { + payload, err := protojson.Marshal(project) if err != nil { return nil, err } @@ -70,8 +70,8 @@ func (c *client) CreateProject(ctx context.Context, projectID string, project *a return nil, err } - var res api.ProjectMessage - err = json.Unmarshal(body, &res) + var res v1pb.Project + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -80,21 +80,13 @@ func (c *client) CreateProject(ctx context.Context, projectID string, project *a } // UpdateProject updates the project. -func (c *client) UpdateProject(ctx context.Context, patch *api.ProjectPatchMessage) (*api.ProjectMessage, error) { - payload, err := json.Marshal(patch) +func (c *client) UpdateProject(ctx context.Context, patch *v1pb.Project, updateMask []string) (*v1pb.Project, error) { + payload, err := protojson.Marshal(patch) if err != nil { return nil, err } - paths := []string{} - if patch.Title != nil { - paths = append(paths, "title") - } - if patch.Key != nil { - paths = append(paths, "key") - } - - req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(paths, ",")), strings.NewReader(string(payload))) + req, err := http.NewRequestWithContext(ctx, "PATCH", fmt.Sprintf("%s/%s/%s?update_mask=%s", c.url, c.version, patch.Name, strings.Join(updateMask, ",")), strings.NewReader(string(payload))) if err != nil { return nil, err @@ -105,8 +97,8 @@ func (c *client) UpdateProject(ctx context.Context, patch *api.ProjectPatchMessa return nil, err } - var res api.ProjectMessage - err = json.Unmarshal(body, &res) + var res v1pb.Project + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } @@ -128,7 +120,7 @@ func (c *client) DeleteProject(ctx context.Context, projectName string) error { } // UndeleteProject undeletes the project. -func (c *client) UndeleteProject(ctx context.Context, projectName string) (*api.ProjectMessage, error) { +func (c *client) UndeleteProject(ctx context.Context, projectName string) (*v1pb.Project, error) { req, err := http.NewRequestWithContext(ctx, "POST", fmt.Sprintf("%s/%s/%s:undelete", c.url, c.version, projectName), nil) if err != nil { return nil, err @@ -139,8 +131,8 @@ func (c *client) UndeleteProject(ctx context.Context, projectName string) (*api. return nil, err } - var res api.ProjectMessage - err = json.Unmarshal(body, &res) + var res v1pb.Project + err = ProtojsonUnmarshaler.Unmarshal(body, &res) if err != nil { return nil, err } diff --git a/go.mod b/go.mod index effbb9b..3adf98e 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,15 @@ module github.com/bytebase/terraform-provider-bytebase -go 1.19 +go 1.23.2 require ( + buf.build/gen/go/bytebase/bytebase/protocolbuffers/go v1.35.2-20240417031025-3a5c93e22bec.1 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-docs v0.13.0 github.com/hashicorp/terraform-plugin-log v0.7.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 github.com/pkg/errors v0.9.1 + google.golang.org/protobuf v1.35.2 ) require ( @@ -66,5 +68,4 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect ) diff --git a/go.sum b/go.sum index 008a40c..7f16df1 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +buf.build/gen/go/bytebase/bytebase/protocolbuffers/go v1.35.2-20240417031025-3a5c93e22bec.1 h1:MA91yfslAinPBPzB0ZGXCW97kcmYBVy9QhM4X7M9nKY= +buf.build/gen/go/bytebase/bytebase/protocolbuffers/go v1.35.2-20240417031025-3a5c93e22bec.1/go.mod h1:fFdEhMRFdbiK/xOo8mzc5bmoNJ4cxeEfBMXodq5wRE8= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -18,6 +20,7 @@ github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXva github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= +github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= @@ -39,6 +42,7 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= @@ -49,6 +53,7 @@ github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6 github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -126,18 +131,21 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= +github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -165,6 +173,7 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= +github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -176,11 +185,13 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -275,8 +286,8 @@ google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/provider/data_source_environment_list.go b/provider/data_source_environment_list.go index 3a1d15e..6940413 100644 --- a/provider/data_source_environment_list.go +++ b/provider/data_source_environment_list.go @@ -83,7 +83,7 @@ func dataSourceEnvironmentListRead(ctx context.Context, d *schema.ResourceData, env["title"] = environment.Title env["name"] = environment.Name env["order"] = environment.Order - env["environment_tier_policy"] = string(environment.Tier) + env["environment_tier_policy"] = environment.Tier.String() environments = append(environments, env) } diff --git a/provider/data_source_instance_list.go b/provider/data_source_instance_list.go index 9ddcde4..8961904 100644 --- a/provider/data_source_instance_list.go +++ b/provider/data_source_instance_list.go @@ -133,9 +133,7 @@ func dataSourceInstanceListRead(ctx context.Context, d *schema.ResourceData, m i // Warning or errors can be collected in a slice type var diags diag.Diagnostics - response, err := c.ListInstance(ctx, &api.InstanceFindMessage{ - ShowDeleted: d.Get("show_deleted").(bool), - }) + response, err := c.ListInstance(ctx, d.Get("show_deleted").(bool)) if err != nil { return diag.FromErr(err) } @@ -151,7 +149,7 @@ func dataSourceInstanceListRead(ctx context.Context, d *schema.ResourceData, m i ins["resource_id"] = instanceID ins["title"] = instance.Title ins["name"] = instance.Name - ins["engine"] = instance.Engine + ins["engine"] = instance.Engine.String() ins["external_link"] = instance.ExternalLink ins["environment"] = instance.Environment diff --git a/provider/data_source_project.go b/provider/data_source_project.go index 83e27e4..2001e3f 100644 --- a/provider/data_source_project.go +++ b/provider/data_source_project.go @@ -9,6 +9,8 @@ import ( "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" + + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" ) func dataSourceProject() *schema.Resource { @@ -95,10 +97,7 @@ func dataSourceProjectRead(ctx context.Context, d *schema.ResourceData, m interf } filter := fmt.Sprintf(`project == "%s"`, project.Name) - response, err := c.ListDatabase(ctx, &api.DatabaseFindMessage{ - InstanceID: "-", - Filter: &filter, - }) + response, err := c.ListDatabase(ctx, "-", filter) if err != nil { return diag.FromErr(err) } @@ -107,7 +106,7 @@ func dataSourceProjectRead(ctx context.Context, d *schema.ResourceData, m interf return setProjectWithDatabases(d, project, response.Databases) } -func setProjectWithDatabases(d *schema.ResourceData, project *api.ProjectMessage, databases []*api.DatabaseMessage) diag.Diagnostics { +func setProjectWithDatabases(d *schema.ResourceData, project *v1pb.Project, databases []*v1pb.Database) diag.Diagnostics { d.SetId(project.Name) projectID, err := internal.GetProjectID(project.Name) @@ -129,7 +128,7 @@ func setProjectWithDatabases(d *schema.ResourceData, project *api.ProjectMessage if err := d.Set("title", project.Title); err != nil { return diag.Errorf("cannot set title for project: %s", err.Error()) } - if err := d.Set("workflow", project.Workflow); err != nil { + if err := d.Set("workflow", project.Workflow.String()); err != nil { return diag.Errorf("cannot set workflow for project: %s", err.Error()) } @@ -138,7 +137,7 @@ func setProjectWithDatabases(d *schema.ResourceData, project *api.ProjectMessage db := map[string]interface{}{} db["name"] = database.Name db["environment"] = database.Environment - db["sync_state"] = database.SyncState + db["sync_state"] = database.SyncState.String() db["successful_sync_time"] = database.SuccessfulSyncTime db["schema_version"] = database.SchemaVersion db["labels"] = database.Labels diff --git a/provider/data_source_project_list.go b/provider/data_source_project_list.go index 40d90bc..025d165 100644 --- a/provider/data_source_project_list.go +++ b/provider/data_source_project_list.go @@ -124,13 +124,10 @@ func dataSourceProjectListRead(ctx context.Context, d *schema.ResourceData, m in proj["name"] = project.Name proj["title"] = project.Title proj["key"] = project.Key - proj["workflow"] = project.Workflow + proj["workflow"] = project.Workflow.String() filter := fmt.Sprintf(`project == "%s"`, project.Name) - response, err := c.ListDatabase(ctx, &api.DatabaseFindMessage{ - InstanceID: "-", - Filter: &filter, - }) + response, err := c.ListDatabase(ctx, "-", filter) if err != nil { return diag.FromErr(err) } @@ -140,7 +137,7 @@ func dataSourceProjectListRead(ctx context.Context, d *schema.ResourceData, m in db := map[string]interface{}{} db["name"] = database.Name db["environment"] = database.Environment - db["sync_state"] = database.SyncState + db["sync_state"] = database.SyncState.String() db["successful_sync_time"] = database.SuccessfulSyncTime db["schema_version"] = database.SchemaVersion db["labels"] = database.Labels diff --git a/provider/internal/mock_client.go b/provider/internal/mock_client.go index 3c23ee7..36343a7 100644 --- a/provider/internal/mock_client.go +++ b/provider/internal/mock_client.go @@ -3,33 +3,36 @@ package internal import ( "context" "fmt" + "slices" "strings" "github.com/pkg/errors" "github.com/bytebase/terraform-provider-bytebase/api" + + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" ) -var environmentMap map[string]*api.EnvironmentMessage -var instanceMap map[string]*api.InstanceMessage +var environmentMap map[string]*v1pb.Environment +var instanceMap map[string]*v1pb.Instance var policyMap map[string]*api.PolicyMessage -var projectMap map[string]*api.ProjectMessage -var databaseMap map[string]*api.DatabaseMessage +var projectMap map[string]*v1pb.Project +var databaseMap map[string]*v1pb.Database func init() { - environmentMap = map[string]*api.EnvironmentMessage{} - instanceMap = map[string]*api.InstanceMessage{} + environmentMap = map[string]*v1pb.Environment{} + instanceMap = map[string]*v1pb.Instance{} policyMap = map[string]*api.PolicyMessage{} - projectMap = map[string]*api.ProjectMessage{} - databaseMap = map[string]*api.DatabaseMessage{} + projectMap = map[string]*v1pb.Project{} + databaseMap = map[string]*v1pb.Database{} } type mockClient struct { - environmentMap map[string]*api.EnvironmentMessage - instanceMap map[string]*api.InstanceMessage + environmentMap map[string]*v1pb.Environment + instanceMap map[string]*v1pb.Instance policyMap map[string]*api.PolicyMessage - projectMap map[string]*api.ProjectMessage - databaseMap map[string]*api.DatabaseMessage + projectMap map[string]*v1pb.Project + databaseMap map[string]*v1pb.Database } // newMockClient returns the new Bytebase API mock client. @@ -44,17 +47,17 @@ func newMockClient(_, _, _ string) (api.Client, error) { } // Login will login the user and get the response. -func (*mockClient) Login() (*api.AuthResponse, error) { - return &api.AuthResponse{}, nil +func (*mockClient) Login() (*v1pb.LoginResponse, error) { + return &v1pb.LoginResponse{}, nil } // CreateEnvironment creates the environment. -func (c *mockClient) CreateEnvironment(_ context.Context, environmentID string, create *api.EnvironmentMessage) (*api.EnvironmentMessage, error) { - env := &api.EnvironmentMessage{ +func (c *mockClient) CreateEnvironment(_ context.Context, environmentID string, create *v1pb.Environment) (*v1pb.Environment, error) { + env := &v1pb.Environment{ Name: fmt.Sprintf("%s%s", EnvironmentNamePrefix, environmentID), Order: create.Order, Title: create.Title, - State: api.Active, + State: v1pb.State_ACTIVE, Tier: create.Tier, } @@ -68,7 +71,7 @@ func (c *mockClient) CreateEnvironment(_ context.Context, environmentID string, } // GetEnvironment gets the environment by id. -func (c *mockClient) GetEnvironment(_ context.Context, environmentName string) (*api.EnvironmentMessage, error) { +func (c *mockClient) GetEnvironment(_ context.Context, environmentName string) (*v1pb.Environment, error) { env, ok := c.environmentMap[environmentName] if !ok { return nil, errors.Errorf("Cannot found environment %s", environmentName) @@ -78,35 +81,35 @@ func (c *mockClient) GetEnvironment(_ context.Context, environmentName string) ( } // ListEnvironment finds all environments. -func (c *mockClient) ListEnvironment(_ context.Context, showDeleted bool) (*api.ListEnvironmentMessage, error) { - environments := make([]*api.EnvironmentMessage, 0) +func (c *mockClient) ListEnvironment(_ context.Context, showDeleted bool) (*v1pb.ListEnvironmentsResponse, error) { + environments := make([]*v1pb.Environment, 0) for _, env := range c.environmentMap { - if env.State == api.Deleted && !showDeleted { + if env.State == v1pb.State_DELETED && !showDeleted { continue } environments = append(environments, env) } - return &api.ListEnvironmentMessage{ + return &v1pb.ListEnvironmentsResponse{ Environments: environments, }, nil } // UpdateEnvironment updates the environment. -func (c *mockClient) UpdateEnvironment(ctx context.Context, patch *api.EnvironmentPatchMessage) (*api.EnvironmentMessage, error) { +func (c *mockClient) UpdateEnvironment(ctx context.Context, patch *v1pb.Environment, updateMasks []string) (*v1pb.Environment, error) { env, err := c.GetEnvironment(ctx, patch.Name) if err != nil { return nil, err } - if v := patch.Title; v != nil { - env.Title = *v + if slices.Contains(updateMasks, "title") { + env.Title = patch.Title } - if v := patch.Order; v != nil { - env.Order = *v + if slices.Contains(updateMasks, "order") { + env.Order = patch.Order } - if v := patch.Tier; v != nil { - env.Tier = *v + if slices.Contains(updateMasks, "tier") { + env.Tier = patch.Tier } c.environmentMap[env.Name] = env @@ -121,40 +124,40 @@ func (c *mockClient) DeleteEnvironment(ctx context.Context, environmentName stri return err } - env.State = api.Deleted + env.State = v1pb.State_DELETED c.environmentMap[env.Name] = env return nil } // UndeleteEnvironment undeletes the environment. -func (c *mockClient) UndeleteEnvironment(ctx context.Context, environmentName string) (*api.EnvironmentMessage, error) { +func (c *mockClient) UndeleteEnvironment(ctx context.Context, environmentName string) (*v1pb.Environment, error) { env, err := c.GetEnvironment(ctx, environmentName) if err != nil { return nil, err } - env.State = api.Active + env.State = v1pb.State_ACTIVE c.environmentMap[env.Name] = env return env, nil } // ListInstance will return instances in environment. -func (c *mockClient) ListInstance(_ context.Context, find *api.InstanceFindMessage) (*api.ListInstanceMessage, error) { - instances := make([]*api.InstanceMessage, 0) +func (c *mockClient) ListInstance(_ context.Context, showDeleted bool) (*v1pb.ListInstancesResponse, error) { + instances := make([]*v1pb.Instance, 0) for _, ins := range c.instanceMap { - if ins.State == api.Deleted && !find.ShowDeleted { + if ins.State == v1pb.State_DELETED && !showDeleted { continue } instances = append(instances, ins) } - return &api.ListInstanceMessage{ + return &v1pb.ListInstancesResponse{ Instances: instances, }, nil } // GetInstance gets the instance by id. -func (c *mockClient) GetInstance(_ context.Context, instanceName string) (*api.InstanceMessage, error) { +func (c *mockClient) GetInstance(_ context.Context, instanceName string) (*v1pb.Instance, error) { ins, ok := c.instanceMap[instanceName] if !ok { return nil, errors.Errorf("Cannot found instance %s", instanceName) @@ -164,10 +167,10 @@ func (c *mockClient) GetInstance(_ context.Context, instanceName string) (*api.I } // CreateInstance creates the instance. -func (c *mockClient) CreateInstance(_ context.Context, instanceID string, instance *api.InstanceMessage) (*api.InstanceMessage, error) { - ins := &api.InstanceMessage{ +func (c *mockClient) CreateInstance(_ context.Context, instanceID string, instance *v1pb.Instance) (*v1pb.Instance, error) { + ins := &v1pb.Instance{ Name: fmt.Sprintf("%s%s", InstanceNamePrefix, instanceID), - State: api.Active, + State: v1pb.State_ACTIVE, Title: instance.Title, Engine: instance.Engine, ExternalLink: instance.ExternalLink, @@ -180,9 +183,9 @@ func (c *mockClient) CreateInstance(_ context.Context, instanceID string, instan return nil, err } - database := &api.DatabaseMessage{ + database := &v1pb.Database{ Name: fmt.Sprintf("%s/%sdefault", ins.Name, DatabaseIDPrefix), - SyncState: api.Active, + SyncState: v1pb.State_ACTIVE, Labels: map[string]string{ "bb.environment": envID, }, @@ -194,20 +197,20 @@ func (c *mockClient) CreateInstance(_ context.Context, instanceID string, instan } // UpdateInstance updates the instance. -func (c *mockClient) UpdateInstance(ctx context.Context, patch *api.InstancePatchMessage) (*api.InstanceMessage, error) { +func (c *mockClient) UpdateInstance(ctx context.Context, patch *v1pb.Instance, updateMasks []string) (*v1pb.Instance, error) { ins, err := c.GetInstance(ctx, patch.Name) if err != nil { return nil, err } - if v := patch.Title; v != nil { - ins.Title = *v + if slices.Contains(updateMasks, "title") { + ins.Title = patch.Title } - if v := patch.ExternalLink; v != nil { - ins.ExternalLink = *v + if slices.Contains(updateMasks, "external_link") { + ins.ExternalLink = patch.ExternalLink } - if v := patch.DataSources; v != nil { - ins.DataSources = v + if slices.Contains(updateMasks, "data_sources") { + ins.DataSources = patch.DataSources } c.instanceMap[ins.Name] = ins @@ -221,20 +224,20 @@ func (c *mockClient) DeleteInstance(ctx context.Context, instanceName string) er return err } - ins.State = api.Deleted + ins.State = v1pb.State_DELETED c.instanceMap[ins.Name] = ins return nil } // UndeleteInstance undeletes the instance. -func (c *mockClient) UndeleteInstance(ctx context.Context, instanceName string) (*api.InstanceMessage, error) { +func (c *mockClient) UndeleteInstance(ctx context.Context, instanceName string) (*v1pb.Instance, error) { ins, err := c.GetInstance(ctx, instanceName) if err != nil { return nil, err } - ins.State = api.Active + ins.State = v1pb.State_ACTIVE c.instanceMap[ins.Name] = ins return ins, nil @@ -343,7 +346,7 @@ func (c *mockClient) DeletePolicy(_ context.Context, policyName string) error { } // GetDatabase gets the database by instance resource id and the database name. -func (c *mockClient) GetDatabase(_ context.Context, databaseName string) (*api.DatabaseMessage, error) { +func (c *mockClient) GetDatabase(_ context.Context, databaseName string) (*v1pb.Database, error) { db, ok := c.databaseMap[databaseName] if !ok { return nil, errors.Errorf("Cannot found database %s", databaseName) @@ -353,45 +356,45 @@ func (c *mockClient) GetDatabase(_ context.Context, databaseName string) (*api.D } // ListDatabase list the databases. -func (c *mockClient) ListDatabase(_ context.Context, find *api.DatabaseFindMessage) (*api.ListDatabaseMessage, error) { +func (c *mockClient) ListDatabase(_ context.Context, instaceID, filter string) (*v1pb.ListDatabasesResponse, error) { projectID := "-" - if v := find.Filter; v != nil && strings.HasPrefix(*v, "project == ") { - projectID = strings.Split(*v, "project == ")[1] + if strings.HasPrefix(filter, "project == ") { + projectID = strings.Split(filter, "project == ")[1] } - databases := make([]*api.DatabaseMessage, 0) + databases := make([]*v1pb.Database, 0) for _, db := range c.databaseMap { if projectID != "-" && fmt.Sprintf(`"%s"`, db.Project) != projectID { continue } - if find.InstanceID != "-" && !strings.HasPrefix(db.Name, fmt.Sprintf("%s%s", InstanceNamePrefix, find.InstanceID)) { + if instaceID != "-" && !strings.HasPrefix(db.Name, fmt.Sprintf("%s%s", InstanceNamePrefix, instaceID)) { continue } databases = append(databases, db) } - return &api.ListDatabaseMessage{ + return &v1pb.ListDatabasesResponse{ Databases: databases, }, nil } // UpdateDatabase patches the database. -func (c *mockClient) UpdateDatabase(ctx context.Context, patch *api.DatabasePatchMessage) (*api.DatabaseMessage, error) { +func (c *mockClient) UpdateDatabase(ctx context.Context, patch *v1pb.Database, updateMasks []string) (*v1pb.Database, error) { db, err := c.GetDatabase(ctx, patch.Name) if err != nil { return nil, err } - if v := patch.Project; v != nil { - db.Project = *v + if slices.Contains(updateMasks, "project") { + db.Project = patch.Project } - if v := patch.Labels; v != nil { - db.Labels = *v + if slices.Contains(updateMasks, "labels") { + db.Labels = patch.Labels } c.databaseMap[db.Name] = db return db, nil } // GetProject gets the project by resource id. -func (c *mockClient) GetProject(_ context.Context, projectName string) (*api.ProjectMessage, error) { +func (c *mockClient) GetProject(_ context.Context, projectName string) (*v1pb.Project, error) { proj, ok := c.projectMap[projectName] if !ok { return nil, errors.Errorf("Cannot found project %s", projectName) @@ -401,28 +404,28 @@ func (c *mockClient) GetProject(_ context.Context, projectName string) (*api.Pro } // ListProject list the projects. -func (c *mockClient) ListProject(_ context.Context, showDeleted bool) (*api.ListProjectMessage, error) { - projects := make([]*api.ProjectMessage, 0) +func (c *mockClient) ListProject(_ context.Context, showDeleted bool) (*v1pb.ListProjectsResponse, error) { + projects := make([]*v1pb.Project, 0) for _, proj := range c.projectMap { - if proj.State == api.Deleted && !showDeleted { + if proj.State == v1pb.State_DELETED && !showDeleted { continue } projects = append(projects, proj) } - return &api.ListProjectMessage{ + return &v1pb.ListProjectsResponse{ Projects: projects, }, nil } // CreateProject creates the project. -func (c *mockClient) CreateProject(_ context.Context, projectID string, project *api.ProjectMessage) (*api.ProjectMessage, error) { - proj := &api.ProjectMessage{ +func (c *mockClient) CreateProject(_ context.Context, projectID string, project *v1pb.Project) (*v1pb.Project, error) { + proj := &v1pb.Project{ Name: fmt.Sprintf("%s%s", ProjectNamePrefix, projectID), - State: api.Active, + State: v1pb.State_ACTIVE, Title: project.Title, Key: project.Key, - Workflow: api.ProjectWorkflowUI, + Workflow: v1pb.Workflow_UI, } c.projectMap[proj.Name] = proj @@ -430,17 +433,17 @@ func (c *mockClient) CreateProject(_ context.Context, projectID string, project } // UpdateProject updates the project. -func (c *mockClient) UpdateProject(ctx context.Context, patch *api.ProjectPatchMessage) (*api.ProjectMessage, error) { +func (c *mockClient) UpdateProject(ctx context.Context, patch *v1pb.Project, updateMasks []string) (*v1pb.Project, error) { proj, err := c.GetProject(ctx, patch.Name) if err != nil { return nil, err } - if v := patch.Title; v != nil { - proj.Title = *v + if slices.Contains(updateMasks, "title") { + proj.Title = patch.Title } - if v := patch.Key; v != nil { - proj.Key = *v + if slices.Contains(updateMasks, "key") { + proj.Key = patch.Key } c.projectMap[proj.Name] = proj @@ -454,20 +457,20 @@ func (c *mockClient) DeleteProject(ctx context.Context, projectName string) erro return err } - proj.State = api.Deleted + proj.State = v1pb.State_DELETED c.projectMap[proj.Name] = proj return nil } // UndeleteProject undeletes the project. -func (c *mockClient) UndeleteProject(ctx context.Context, projectName string) (*api.ProjectMessage, error) { +func (c *mockClient) UndeleteProject(ctx context.Context, projectName string) (*v1pb.Project, error) { proj, err := c.GetProject(ctx, projectName) if err != nil { return nil, err } - proj.State = api.Active + proj.State = v1pb.State_ACTIVE c.projectMap[proj.Name] = proj return proj, nil diff --git a/provider/resource_environment.go b/provider/resource_environment.go index 3847f99..9c8cc7d 100644 --- a/provider/resource_environment.go +++ b/provider/resource_environment.go @@ -10,6 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" ) @@ -54,8 +56,8 @@ func resourceEnvironment() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(api.EnvironmentTierProtected), - string(api.EnvironmentTierUnProtected), + v1pb.EnvironmentTier_PROTECTED.String(), + v1pb.EnvironmentTier_UNPROTECTED.String(), }, false), Description: "If marked as PROTECTED, developers cannot execute any query on this environment's databases using SQL Editor by default.", }, @@ -76,7 +78,7 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, m in title := d.Get("title").(string) order := d.Get("order").(int) - tier := api.EnvironmentTier(d.Get("environment_tier_policy").(string)) + tier := v1pb.EnvironmentTier(v1pb.EnvironmentTier_value[d.Get("environment_tier_policy").(string)]) var diags diag.Diagnostics if existedEnv != nil && err == nil { @@ -86,7 +88,7 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, m in Detail: fmt.Sprintf("Environment %s already exists, try to exec the update operation", environmentID), }) - if existedEnv.State == api.Deleted { + if existedEnv.State == v1pb.State_DELETED { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Environment is deleted", @@ -102,12 +104,12 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, m in } } - env, err := c.UpdateEnvironment(ctx, &api.EnvironmentPatchMessage{ + env, err := c.UpdateEnvironment(ctx, &v1pb.Environment{ Name: environmentName, - Title: &title, - Order: &order, - Tier: &tier, - }) + Title: title, + Order: int32(order), + Tier: tier, + }, []string{"title", "order", "tier"}) if err != nil { diags = append(diags, diag.Diagnostic{ Severity: diag.Error, @@ -119,10 +121,10 @@ func resourceEnvironmentCreate(ctx context.Context, d *schema.ResourceData, m in d.SetId(env.Name) } else { - env, err := c.CreateEnvironment(ctx, environmentID, &api.EnvironmentMessage{ + env, err := c.CreateEnvironment(ctx, environmentID, &v1pb.Environment{ Name: environmentName, Title: title, - Order: order, + Order: int32(order), Tier: tier, }) if err != nil { @@ -166,7 +168,7 @@ func resourceEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, m in } var diags diag.Diagnostics - if existedEnv.State == api.Deleted { + if existedEnv.State == v1pb.State_DELETED { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Environment is deleted", @@ -182,29 +184,29 @@ func resourceEnvironmentUpdate(ctx context.Context, d *schema.ResourceData, m in } } - patch := &api.EnvironmentPatchMessage{ - Name: environmentName, - } + paths := []string{} if d.HasChange("title") { - title, ok := d.Get("title").(string) - if ok { - patch.Title = &title - } + paths = append(paths, "title") } if d.HasChange("order") { - order, ok := d.Get("order").(int) - if ok { - patch.Order = &order - } + paths = append(paths, "order") } if d.HasChange("environment_tier_policy") { - tier := api.EnvironmentTier(d.Get("environment_tier_policy").(string)) - patch.Tier = &tier + paths = append(paths, "tier") } - if _, err := c.UpdateEnvironment(ctx, patch); err != nil { + title := d.Get("title").(string) + order := d.Get("order").(int) + tier := v1pb.EnvironmentTier(v1pb.EnvironmentTier_value[d.Get("environment_tier_policy").(string)]) + + if _, err := c.UpdateEnvironment(ctx, &v1pb.Environment{ + Name: environmentName, + Title: title, + Order: int32(order), + Tier: tier, + }, paths); err != nil { return diag.FromErr(err) } @@ -232,7 +234,7 @@ func resourceEnvironmentDelete(ctx context.Context, d *schema.ResourceData, m in return diags } -func setEnvironment(d *schema.ResourceData, env *api.EnvironmentMessage) diag.Diagnostics { +func setEnvironment(d *schema.ResourceData, env *v1pb.Environment) diag.Diagnostics { environmentID, err := internal.GetEnvironmentID(env.Name) if err != nil { return diag.FromErr(err) @@ -250,7 +252,7 @@ func setEnvironment(d *schema.ResourceData, env *api.EnvironmentMessage) diag.Di if err := d.Set("order", env.Order); err != nil { return diag.Errorf("cannot set order for environment: %s", err.Error()) } - if err := d.Set("environment_tier_policy", string(env.Tier)); err != nil { + if err := d.Set("environment_tier_policy", env.Tier.String()); err != nil { return diag.Errorf("cannot set environment_tier_policy for environment: %s", err.Error()) } diff --git a/provider/resource_environment_test.go b/provider/resource_environment_test.go index 0760c84..267a9a3 100644 --- a/provider/resource_environment_test.go +++ b/provider/resource_environment_test.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/pkg/errors" "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" @@ -98,7 +99,10 @@ func TestAccEnvironment_InvalidInput(t *testing.T) { } func testAccCheckEnvironmentDestroy(s *terraform.State) error { - c := testAccProvider.Meta().(api.Client) + c, ok := testAccProvider.Meta().(api.Client) + if !ok { + return errors.Errorf("cannot get the api client") + } for _, rs := range s.RootModule().Resources { if rs.Type != "bytebase_environment" { diff --git a/provider/resource_instance.go b/provider/resource_instance.go index 0444a35..595abfa 100644 --- a/provider/resource_instance.go +++ b/provider/resource_instance.go @@ -11,6 +11,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/pkg/errors" + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" + "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" ) @@ -53,20 +55,27 @@ func resourceInstance() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(api.EngineTypeMySQL), - string(api.EngineTypePostgres), - string(api.EngineTypeTiDB), - string(api.EngineTypeSnowflake), - string(api.EngineTypeClickHouse), - string(api.EngineTypeMongoDB), - string(api.EngineTypeSQLite), - string(api.EngineTypeRedis), - string(api.EngineTypeOracle), - string(api.EngineTypeSpanner), - string(api.EngineTypeMSSQL), - string(api.EngineTypeRedshift), - string(api.EngineTypeMariaDB), - string(api.EngineTypeOceanbase), + v1pb.Engine_CLICKHOUSE.String(), + v1pb.Engine_MYSQL.String(), + v1pb.Engine_POSTGRES.String(), + v1pb.Engine_SNOWFLAKE.String(), + v1pb.Engine_SQLITE.String(), + v1pb.Engine_TIDB.String(), + v1pb.Engine_MONGODB.String(), + v1pb.Engine_REDIS.String(), + v1pb.Engine_ORACLE.String(), + v1pb.Engine_SPANNER.String(), + v1pb.Engine_MSSQL.String(), + v1pb.Engine_REDSHIFT.String(), + v1pb.Engine_MARIADB.String(), + v1pb.Engine_OCEANBASE.String(), + v1pb.Engine_DM.String(), + v1pb.Engine_RISINGWAVE.String(), + v1pb.Engine_OCEANBASE_ORACLE.String(), + v1pb.Engine_STARROCKS.String(), + v1pb.Engine_DORIS.String(), + v1pb.Engine_HIVE.String(), + v1pb.Engine_ELASTICSEARCH.String(), }, false), Description: "The instance engine. Support MYSQL, POSTGRES, TIDB, SNOWFLAKE, CLICKHOUSE, MONGODB, SQLITE, REDIS, ORACLE, SPANNER, MSSQL, REDSHIFT, MARIADB, OCEANBASE.", }, @@ -92,8 +101,8 @@ func resourceInstance() *schema.Resource { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(api.DataSourceAdmin), - string(api.DataSourceRO), + v1pb.DataSourceType_ADMIN.String(), + v1pb.DataSourceType_READ_ONLY.String(), }, false), Description: "The data source type. Should be ADMIN or RO.", }, @@ -167,6 +176,13 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter instanceID := d.Get("resource_id").(string) instanceName := fmt.Sprintf("%s%s", internal.InstanceNamePrefix, instanceID) + engineString := d.Get("engine").(string) + engineValue, ok := v1pb.Engine_value[engineString] + if !ok { + return diag.Errorf("invalid engine type %v", engineString) + } + engine := v1pb.Engine(engineValue) + existedInstance, err := c.GetInstance(ctx, instanceName) if err != nil { tflog.Debug(ctx, fmt.Sprintf("get instance %s failed with error: %v", instanceName, err)) @@ -180,8 +196,7 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter Detail: fmt.Sprintf("Instance %s already exists, try to exec the update operation", instanceName), }) - engine := d.Get("engine").(string) - if string(existedInstance.Engine) != engine { + if existedInstance.Engine != engine { diags = append(diags, diag.Diagnostic{ Severity: diag.Error, Summary: "Invalid argument", @@ -190,7 +205,7 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter return diags } - if existedInstance.State == api.Deleted { + if existedInstance.State == v1pb.State_DELETED { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Instance is deleted", @@ -208,12 +223,13 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter title := d.Get("title").(string) externalLink := d.Get("external_link").(string) - if _, err := c.UpdateInstance(ctx, &api.InstancePatchMessage{ + if _, err := c.UpdateInstance(ctx, &v1pb.Instance{ Name: instanceName, - Title: &title, - ExternalLink: &externalLink, + Title: title, + ExternalLink: externalLink, DataSources: dataSourceList, - }); err != nil { + State: existedInstance.State, + }, []string{"title", "external_link", "data_sources"}); err != nil { diags = append(diags, diag.Diagnostic{ Severity: diag.Error, Summary: "Failed to update instance", @@ -222,12 +238,12 @@ func resourceInstanceCreate(ctx context.Context, d *schema.ResourceData, m inter return diags } } else { - if _, err := c.CreateInstance(ctx, instanceID, &api.InstanceMessage{ + if _, err := c.CreateInstance(ctx, instanceID, &v1pb.Instance{ Name: instanceName, Title: d.Get("title").(string), - Engine: api.EngineType(d.Get("engine").(string)), + Engine: engine, ExternalLink: d.Get("external_link").(string), - State: api.Active, + State: v1pb.State_ACTIVE, DataSources: dataSourceList, Environment: d.Get("environment").(string), }); err != nil { @@ -285,7 +301,7 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter } var diags diag.Diagnostics - if existedInstance.State == api.Deleted { + if existedInstance.State == v1pb.State_DELETED { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Instance is deleted", @@ -301,26 +317,29 @@ func resourceInstanceUpdate(ctx context.Context, d *schema.ResourceData, m inter } } - patch := &api.InstancePatchMessage{ - Name: instanceName, + dataSourceList, err := convertDataSourceCreateList(d, true /* validate */) + if err != nil { + return diag.FromErr(err) } + + paths := []string{} if d.HasChange("title") { - v := d.Get("title").(string) - patch.Title = &v + paths = append(paths, "title") } if d.HasChange("external_link") { - v := d.Get("external_link").(string) - patch.ExternalLink = &v + paths = append(paths, "external_link") } if d.HasChange("data_sources") { - dataSourceList, err := convertDataSourceCreateList(d, true /* validate */) - if err != nil { - return diag.FromErr(err) - } - patch.DataSources = dataSourceList + paths = append(paths, "data_sources") } - if _, err := c.UpdateInstance(ctx, patch); err != nil { + if _, err := c.UpdateInstance(ctx, &v1pb.Instance{ + Name: instanceName, + Title: d.Get("title").(string), + ExternalLink: d.Get("external_link").(string), + DataSources: dataSourceList, + State: existedInstance.State, + }, paths); err != nil { return diag.FromErr(err) } if err := c.SyncInstanceSchema(ctx, instanceName); err != nil { @@ -355,7 +374,7 @@ func resourceInstanceDelete(ctx context.Context, d *schema.ResourceData, m inter return diags } -func setInstanceMessage(d *schema.ResourceData, instance *api.InstanceMessage) diag.Diagnostics { +func setInstanceMessage(d *schema.ResourceData, instance *v1pb.Instance) diag.Diagnostics { instanceID, err := internal.GetInstanceID(instance.Name) if err != nil { return diag.FromErr(err) @@ -372,7 +391,7 @@ func setInstanceMessage(d *schema.ResourceData, instance *api.InstanceMessage) d if err := d.Set("environment", instance.Environment); err != nil { return diag.Errorf("cannot set environment for instance: %s", err.Error()) } - if err := d.Set("engine", instance.Engine); err != nil { + if err := d.Set("engine", instance.Engine.String()); err != nil { return diag.Errorf("cannot set engine for instance: %s", err.Error()) } if err := d.Set("external_link", instance.ExternalLink); err != nil { @@ -390,28 +409,28 @@ func setInstanceMessage(d *schema.ResourceData, instance *api.InstanceMessage) d return nil } -func flattenDataSourceList(d *schema.ResourceData, dataSourceList []*api.DataSourceMessage) ([]interface{}, error) { +func flattenDataSourceList(d *schema.ResourceData, dataSourceList []*v1pb.DataSource) ([]interface{}, error) { oldDataSourceList, err := convertDataSourceCreateList(d, false) if err != nil { return nil, err } - oldDataSourceMap := make(map[string]*api.DataSourceMessage) + oldDataSourceMap := make(map[string]*v1pb.DataSource) for _, ds := range oldDataSourceList { - oldDataSourceMap[ds.ID] = ds + oldDataSourceMap[ds.Id] = ds } res := []interface{}{} for _, dataSource := range dataSourceList { raw := map[string]interface{}{} - raw["id"] = dataSource.ID - raw["type"] = dataSource.Type + raw["id"] = dataSource.Id + raw["type"] = dataSource.Type.String() raw["username"] = dataSource.Username raw["host"] = dataSource.Host raw["port"] = dataSource.Port raw["database"] = dataSource.Database // These sensitive fields won't returned in the API. Propagate state value. - if ds, ok := oldDataSourceMap[dataSource.ID]; ok { + if ds, ok := oldDataSourceMap[dataSource.Id]; ok { raw["password"] = ds.Password raw["ssl_ca"] = ds.SslCa raw["ssl_cert"] = ds.SslCert @@ -422,17 +441,17 @@ func flattenDataSourceList(d *schema.ResourceData, dataSourceList []*api.DataSou return res, nil } -func convertDataSourceCreateList(d *schema.ResourceData, validate bool) ([]*api.DataSourceMessage, error) { - var dataSourceList []*api.DataSourceMessage +func convertDataSourceCreateList(d *schema.ResourceData, validate bool) ([]*v1pb.DataSource, error) { + var dataSourceList []*v1pb.DataSource if rawList, ok := d.Get("data_sources").([]interface{}); ok { - dataSourceTypeMap := map[api.DataSourceType]bool{} + dataSourceTypeMap := map[v1pb.DataSourceType]bool{} for _, raw := range rawList { obj := raw.(map[string]interface{}) - dataSource := &api.DataSourceMessage{ - ID: obj["id"].(string), - Type: api.DataSourceType(obj["type"].(string)), + dataSource := &v1pb.DataSource{ + Id: obj["id"].(string), + Type: v1pb.DataSourceType(v1pb.DataSourceType_value[obj["type"].(string)]), } - if dataSourceTypeMap[dataSource.Type] && dataSource.Type == api.DataSourceAdmin { + if dataSourceTypeMap[dataSource.Type] && dataSource.Type == v1pb.DataSourceType_ADMIN { return nil, errors.Errorf("duplicate data source type ADMIN") } dataSourceTypeMap[dataSource.Type] = true @@ -464,8 +483,8 @@ func convertDataSourceCreateList(d *schema.ResourceData, validate bool) ([]*api. dataSourceList = append(dataSourceList, dataSource) } - if !dataSourceTypeMap[api.DataSourceAdmin] && validate { - return nil, errors.Errorf("data source \"%v\" is required", api.DataSourceAdmin) + if !dataSourceTypeMap[v1pb.DataSourceType_ADMIN] && validate { + return nil, errors.Errorf("data source \"%v\" is required", v1pb.DataSourceType_ADMIN.String()) } } diff --git a/provider/resource_instance_test.go b/provider/resource_instance_test.go index c49af0c..20d4ce3 100644 --- a/provider/resource_instance_test.go +++ b/provider/resource_instance_test.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/pkg/errors" "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" @@ -142,7 +143,10 @@ func TestAccInstance_InvalidInput(t *testing.T) { } func testAccCheckInstanceDestroy(s *terraform.State) error { - c := testAccProvider.Meta().(api.Client) + c, ok := testAccProvider.Meta().(api.Client) + if !ok { + return errors.Errorf("cannot get the api client") + } for _, rs := range s.RootModule().Resources { if rs.Type != "bytebase_instance" { diff --git a/provider/resource_policy_test.go b/provider/resource_policy_test.go index 976796a..b2aa4d2 100644 --- a/provider/resource_policy_test.go +++ b/provider/resource_policy_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/pkg/errors" "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" @@ -166,7 +167,10 @@ func getDeploymentApprovalPolicy(defaultStrategy string, strategies []*api.Deplo } func testAccCheckPolicyDestroy(s *terraform.State) error { - c := testAccProvider.Meta().(api.Client) + c, ok := testAccProvider.Meta().(api.Client) + if !ok { + return errors.Errorf("cannot get the api client") + } for _, rs := range s.RootModule().Resources { if rs.Type != "bytebase_policy" { diff --git a/provider/resource_project.go b/provider/resource_project.go index a4f33b6..5958487 100644 --- a/provider/resource_project.go +++ b/provider/resource_project.go @@ -11,6 +11,8 @@ import ( "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" + + v1pb "buf.build/gen/go/bytebase/bytebase/protocolbuffers/go/v1" ) // defaultProj is the default project name. @@ -123,7 +125,7 @@ func resourceProjectCreate(ctx context.Context, d *schema.ResourceData, m interf Detail: fmt.Sprintf("Project %s already exists, try to exec the update operation", projectName), }) - if existedProject.State == api.Deleted { + if existedProject.State == v1pb.State_DELETED { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Project is deleted", @@ -139,11 +141,13 @@ func resourceProjectCreate(ctx context.Context, d *schema.ResourceData, m interf } } - project, err := c.UpdateProject(ctx, &api.ProjectPatchMessage{ - Name: projectName, - Title: &title, - Key: &key, - }) + project, err := c.UpdateProject(ctx, &v1pb.Project{ + Name: projectName, + Title: title, + Key: key, + State: existedProject.State, + Workflow: existedProject.Workflow, + }, []string{"title", "key"}) if err != nil { diags = append(diags, diag.Diagnostic{ Severity: diag.Error, @@ -155,10 +159,12 @@ func resourceProjectCreate(ctx context.Context, d *schema.ResourceData, m interf d.SetId(project.Name) } else { - project, err := c.CreateProject(ctx, projectID, &api.ProjectMessage{ - Name: projectName, - Title: title, - Key: key, + project, err := c.CreateProject(ctx, projectID, &v1pb.Project{ + Name: projectName, + Title: title, + Key: key, + State: v1pb.State_ACTIVE, + Workflow: v1pb.Workflow_UI, }) if err != nil { return diag.FromErr(err) @@ -195,7 +201,7 @@ func resourceProjectUpdate(ctx context.Context, d *schema.ResourceData, m interf } var diags diag.Diagnostics - if existedProject.State == api.Deleted { + if existedProject.State == v1pb.State_DELETED { diags = append(diags, diag.Diagnostic{ Severity: diag.Warning, Summary: "Project is deleted", @@ -211,19 +217,21 @@ func resourceProjectUpdate(ctx context.Context, d *schema.ResourceData, m interf } } - patch := &api.ProjectPatchMessage{ - Name: projectName, - } + paths := []string{} if d.HasChange("title") { - v := d.Get("title").(string) - patch.Title = &v + paths = append(paths, "title") } if d.HasChange("key") { - v := d.Get("key").(string) - patch.Key = &v + paths = append(paths, "key") } - if _, err := c.UpdateProject(ctx, patch); err != nil { + if _, err := c.UpdateProject(ctx, &v1pb.Project{ + Name: projectName, + Title: d.Get("title").(string), + Key: d.Get("key").(string), + State: existedProject.State, + Workflow: existedProject.Workflow, + }, paths); err != nil { diags = append(diags, diag.FromErr(err)...) return diags } @@ -253,10 +261,7 @@ func resourceProjectRead(ctx context.Context, d *schema.ResourceData, m interfac } filter := fmt.Sprintf(`project == "%s"`, project.Name) - response, err := c.ListDatabase(ctx, &api.DatabaseFindMessage{ - InstanceID: "-", - Filter: &filter, - }) + response, err := c.ListDatabase(ctx, "-", filter) if err != nil { return diag.Errorf("failed to list database with error: %v", err) } @@ -282,14 +287,11 @@ func resourceProjectDelete(ctx context.Context, d *schema.ResourceData, m interf func updateDatabasesInProject(ctx context.Context, d *schema.ResourceData, client api.Client, projectName string) diag.Diagnostics { filter := fmt.Sprintf(`project == "%s"`, projectName) - listDB, err := client.ListDatabase(ctx, &api.DatabaseFindMessage{ - InstanceID: "-", - Filter: &filter, - }) + listDB, err := client.ListDatabase(ctx, "-", filter) if err != nil { return diag.Errorf("failed to list database with error: %v", err) } - existedDBMap := map[string]*api.DatabaseMessage{} + existedDBMap := map[string]*v1pb.Database{} for _, db := range listDB.Databases { existedDBMap[db.Name] = db } @@ -298,7 +300,7 @@ func updateDatabasesInProject(ctx context.Context, d *schema.ResourceData, clien if !ok { return nil } - updatedDBMap := map[string]*api.DatabasePatchMessage{} + updatedDBMap := map[string]*v1pb.Database{} for _, raw := range rawList { obj := raw.(map[string]interface{}) dbName := obj["name"].(string) @@ -308,25 +310,23 @@ func updateDatabasesInProject(ctx context.Context, d *schema.ResourceData, clien labels[key] = val.(string) } - // TODO(ed): - patch := &api.DatabasePatchMessage{ + updatedDBMap[dbName] = &v1pb.Database{ Name: dbName, - Project: &projectName, - Labels: &labels, + Project: projectName, + Labels: labels, } - updatedDBMap[dbName] = patch - if _, err := client.UpdateDatabase(ctx, patch); err != nil { - return diag.Errorf("failed to update database %s with error: %v", patch.Name, err) + if _, err := client.UpdateDatabase(ctx, updatedDBMap[dbName], []string{"project", "label"}); err != nil { + return diag.Errorf("failed to update database %s with error: %v", dbName, err) } } for _, db := range existedDBMap { if _, ok := updatedDBMap[db.Name]; !ok { // move db to default project - if _, err := client.UpdateDatabase(ctx, &api.DatabasePatchMessage{ + if _, err := client.UpdateDatabase(ctx, &v1pb.Database{ Name: db.Name, - Project: &defaultProj, - }); err != nil { + Project: projectName, + }, []string{"project"}); err != nil { return diag.Errorf("failed to move database %s to project %s with error: %v", db.Name, defaultProj, err) } } diff --git a/provider/resource_project_test.go b/provider/resource_project_test.go index cb5d833..fb97d0c 100644 --- a/provider/resource_project_test.go +++ b/provider/resource_project_test.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/pkg/errors" "github.com/bytebase/terraform-provider-bytebase/api" "github.com/bytebase/terraform-provider-bytebase/provider/internal" @@ -51,7 +52,10 @@ func TestAccProject(t *testing.T) { } func testAccCheckProjectDestroy(s *terraform.State) error { - c := testAccProvider.Meta().(api.Client) + c, ok := testAccProvider.Meta().(api.Client) + if !ok { + return errors.Errorf("cannot get the api client") + } for _, rs := range s.RootModule().Resources { if rs.Type != "bytebase_project" {