Files
wehub-resource-sync e04ed9c211
CF: Deploy Dev Docs / deploy (push) Has been cancelled
Sync Labels / build (push) Has been cancelled
tests / unit tests (macos-latest) (push) Has been cancelled
tests / unit tests (windows-latest) (push) Has been cancelled
tests / unit tests (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:32:45 +08:00

124 lines
4.8 KiB
Go

// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dataplexcheckdataquality
import (
"context"
"fmt"
"net/http"
"github.com/goccy/go-yaml"
"github.com/googleapis/mcp-toolbox/internal/tools"
"github.com/googleapis/mcp-toolbox/internal/tools/dataplex/dataplexcommon"
"github.com/googleapis/mcp-toolbox/internal/util"
"github.com/googleapis/mcp-toolbox/internal/util/parameters"
)
const resourceType string = "dataplex-check-data-quality"
func init() {
if !tools.Register(resourceType, newConfig) {
panic(fmt.Sprintf("tool type %q already registered", resourceType))
}
}
func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) {
actual := Config{ConfigBase: tools.ConfigBase{Name: name}}
if err := decoder.DecodeContext(ctx, &actual); err != nil {
return nil, err
}
return actual, nil
}
type compatibleSource interface {
ProjectID() string
GenerateDataQuality(ctx context.Context, location, resourcePath string, specJSON string, publish bool) (string, error)
}
type Config struct {
tools.ConfigBase `yaml:",inline"`
Type string `yaml:"type" validate:"required"`
Source string `yaml:"source" validate:"required"`
Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"`
}
var _ tools.ToolConfig = Config{}
func (cfg Config) ToolConfigType() string {
return resourceType
}
func (cfg Config) Initialize(context.Context) (tools.Tool, error) {
resourcePath := parameters.NewStringParameter("resourcePath", "The BigQuery table or Cloud Storage path to check. For BigQuery: accepts raw table name (e.g. 'my_table'), dataset.table (e.g. 'my_dataset.my_table'), or fully-qualified path (e.g. '//bigquery.googleapis.com/projects/{project}/datasets/{dataset}/tables/{table}'). For Cloud Storage: accepts raw bucket name (e.g. 'my-bucket'), gs:// URI (e.g. 'gs://my-bucket'), or fully-qualified path (e.g. '//storage.googleapis.com/projects/{project}/buckets/{bucket}').")
location := parameters.NewStringParameter("location", "The Google Cloud region where the Dataplex scan should be created and executed (e.g., 'us-central1').")
specJSON := parameters.NewStringParameter("specJSON", "A JSON-serialized string of the Dataplex DataQualitySpec proto message containing the rules and optional configuration. Example format: {\"rules\": [{\"column\": \"my_col\", \"dimension\": \"COMPLETENESS\", \"nonNullExpectation\": {}}], \"catalogPublishingEnabled\": false}")
publish := parameters.NewBooleanParameter("publish", "Whether to publish the generated quality scores/results to the Dataplex Universal Catalog.")
allParameters := parameters.Parameters{resourcePath, location, specJSON, publish}
return Tool{
BaseTool: tools.NewBaseTool(
cfg,
tools.GetAnnotationsOrDefault(cfg.Annotations, tools.NewDestructiveAnnotations),
tools.Manifest{Description: cfg.Description, Parameters: allParameters.Manifest(), AuthRequired: cfg.AuthRequired},
allParameters,
),
}, nil
}
var _ tools.Tool = Tool{}
type Tool struct {
tools.BaseTool[Config]
}
func (t Tool) ToConfig() tools.ToolConfig {
return t.Cfg
}
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, util.ToolboxError) {
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Cfg.Source, t.Cfg.Name, t.Cfg.Type)
if err != nil {
return nil, util.NewClientServerError("source used is not compatible with the tool", http.StatusInternalServerError, err)
}
paramsMap := params.AsMap()
resourcePath, _ := paramsMap["resourcePath"].(string)
location, _ := paramsMap["location"].(string)
specJSON, _ := paramsMap["specJSON"].(string)
publish, _ := paramsMap["publish"].(bool)
if resourcePath == "" {
return nil, util.NewAgentError("resourcePath parameter is required", nil)
}
if location == "" {
return nil, util.NewAgentError("location parameter is required", nil)
}
if specJSON == "" {
return nil, util.NewAgentError("specJSON parameter is required", nil)
}
resourcePath = dataplexcommon.NormalizeResourcePath(resourcePath, source.ProjectID())
opName, err := source.GenerateDataQuality(ctx, location, resourcePath, specJSON, publish)
if err != nil {
return nil, util.ProcessGcpError(err)
}
return map[string]string{
"operation_id": opName,
}, nil
}