mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-02-11 15:45:06 -05:00
feat(tools/looker): tools to list/create/delete directories
within a LookML project. These tools only work on 26.4 and later.
This commit is contained in:
@@ -132,7 +132,9 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookeradddashboardelement"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookeradddashboardfilter"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerconversationalanalytics"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookercreateprojectdirectory"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookercreateprojectfile"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerdeleteprojectdirectory"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerdeleteprojectfile"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerdevmode"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergenerateembedurl"
|
||||
@@ -149,6 +151,7 @@ import (
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetmeasures"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetmodels"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetparameters"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetprojectdirectories"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetprojectfile"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetprojectfiles"
|
||||
_ "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetprojects"
|
||||
|
||||
@@ -488,6 +488,9 @@ See [Usage Examples](../reference/cli.md#examples).
|
||||
* `create_project_file`: Create a new LookML file.
|
||||
* `update_project_file`: Update an existing LookML file.
|
||||
* `delete_project_file`: Delete a LookML file.
|
||||
* `get_project_directories`: Retrieves a list of project directories for a given LookML project.
|
||||
* `create_project_directory`: Creates a new directory within a specified LookML project.
|
||||
* `delete_project_directory`: Deletes a directory from a specified LookML project.
|
||||
* `validate_project`: Check the syntax of a LookML project.
|
||||
* `get_connections`: Get the available connections in a Looker instance.
|
||||
* `get_connection_schemas`: Get the available schemas in a connection.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "looker-create-project-directory"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "looker-create-project-directory" tool creates a new directory in a LookML project.
|
||||
aliases:
|
||||
- /resources/tools/looker-create-project-directory
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `looker-create-project-directory` tool creates a new directory within a specified LookML project.
|
||||
|
||||
It's compatible with the following sources:
|
||||
|
||||
- [looker](../../sources/looker.md)
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
kind: tools
|
||||
name: looker-create-project-directory
|
||||
type: looker-create-project-directory
|
||||
source: looker-source
|
||||
description: |
|
||||
This tool creates a new directory within a specific LookML project.
|
||||
It is useful for organizing project files.
|
||||
|
||||
Parameters:
|
||||
- project_id (string): The ID of the LookML project.
|
||||
- path (string): The path of the directory to create.
|
||||
|
||||
Output:
|
||||
A string confirming the creation of the directory.
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:--------:|:------------:|----------------------------------------------------|
|
||||
| type | string | true | Must be "looker-create-project-directory". |
|
||||
| source | string | true | Name of the source Looker instance. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: "looker-delete-project-directory"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "looker-delete-project-directory" tool deletes a directory from a LookML project.
|
||||
aliases:
|
||||
- /resources/tools/looker-delete-project-directory
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `looker-delete-project-directory` tool deletes a directory from a specified LookML project.
|
||||
|
||||
It's compatible with the following sources:
|
||||
|
||||
- [looker](../../sources/looker.md)
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
kind: tools
|
||||
name: looker-delete-project-directory
|
||||
type: looker-delete-project-directory
|
||||
source: looker-source
|
||||
description: |
|
||||
This tool deletes a directory from a specific LookML project.
|
||||
It is useful for removing unnecessary or obsolete directories.
|
||||
|
||||
Parameters:
|
||||
- project_id (string): The ID of the LookML project.
|
||||
- path (string): The path of the directory to delete.
|
||||
|
||||
Output:
|
||||
A string confirming the deletion of the directory.
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:--------:|:------------:|----------------------------------------------------|
|
||||
| type | string | true | Must be "looker-delete-project-directory". |
|
||||
| source | string | true | Name of the source Looker instance. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
title: "looker-get-project-directories"
|
||||
type: docs
|
||||
weight: 1
|
||||
description: >
|
||||
A "looker-get-project-directories" tool returns the directories within a specific LookML project.
|
||||
aliases:
|
||||
- /resources/tools/looker-get-project-directories
|
||||
---
|
||||
|
||||
## About
|
||||
|
||||
A `looker-get-project-directories` tool retrieves the directories within a specified LookML project.
|
||||
|
||||
It's compatible with the following sources:
|
||||
|
||||
- [looker](../../sources/looker.md)
|
||||
|
||||
## Example
|
||||
|
||||
```yaml
|
||||
kind: tools
|
||||
name: looker-get-project-directories
|
||||
type: looker-get-project-directories
|
||||
source: looker-source
|
||||
description: |
|
||||
This tool retrieves a list of directories within a specific LookML project.
|
||||
It is useful for exploring the project structure.
|
||||
|
||||
Parameters:
|
||||
- project_id (string): The ID of the LookML project.
|
||||
|
||||
Output:
|
||||
A JSON array of strings, representing the directories within the project.
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
| **field** | **type** | **required** | **description** |
|
||||
|-------------|:--------:|:------------:|----------------------------------------------------|
|
||||
| type | string | true | Must be "looker-get-project-directories". |
|
||||
| source | string | true | Name of the source Looker instance. |
|
||||
| description | string | true | Description of the tool that is passed to the LLM. |
|
||||
@@ -959,6 +959,48 @@ tools:
|
||||
Output:
|
||||
A confirmation message upon successful file deletion.
|
||||
|
||||
get_project_directories:
|
||||
kind: looker-get-project-directories
|
||||
source: looker-source
|
||||
description: |
|
||||
This tool retrieves the list of directories within a specified LookML project.
|
||||
|
||||
Parameters:
|
||||
- project_id (required): The unique ID of the LookML project.
|
||||
|
||||
Output:
|
||||
A JSON array of strings, where each string is the name of a directory within the project.
|
||||
|
||||
create_project_directory:
|
||||
kind: looker-create-project-directory
|
||||
source: looker-source
|
||||
description: |
|
||||
This tool creates a new directory within a specified LookML project.
|
||||
|
||||
Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first.
|
||||
|
||||
Parameters:
|
||||
- project_id (required): The unique ID of the LookML project.
|
||||
- directory_path (required): The path to the new directory within the project.
|
||||
|
||||
Output:
|
||||
A confirmation message upon successful directory creation.
|
||||
|
||||
delete_project_directory:
|
||||
kind: looker-delete-project-directory
|
||||
source: looker-source
|
||||
description: |
|
||||
This tool permanently deletes a specified directory within a LookML project.
|
||||
|
||||
Prerequisite: The Looker session must be in Development Mode. Use `dev_mode: true` first.
|
||||
|
||||
Parameters:
|
||||
- project_id (required): The unique ID of the LookML project.
|
||||
- directory_path (required): The path to the directory within the project.
|
||||
|
||||
Output:
|
||||
A confirmation message upon successful directory deletion.
|
||||
|
||||
validate_project:
|
||||
kind: looker-validate-project
|
||||
source: looker-source
|
||||
@@ -1087,6 +1129,9 @@ toolsets:
|
||||
- create_project_file
|
||||
- update_project_file
|
||||
- delete_project_file
|
||||
- get_project_directories
|
||||
- create_project_directory
|
||||
- delete_project_directory
|
||||
- validate_project
|
||||
- get_connections
|
||||
- get_connection_schemas
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2025 Google LLC
|
||||
// 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.
|
||||
@@ -301,3 +301,34 @@ func UpdateProjectFile(l *v4.LookerSDK, projectId string, fileContent FileConten
|
||||
err := l.AuthSession.Do(nil, "PUT", "/4.0", path, nil, fileContent, options)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetProjectDirectories(l *v4.LookerSDK, projectId string, options *rtl.ApiSettings) (string, error) {
|
||||
var result string
|
||||
path := fmt.Sprintf("/projects/%s/directories", url.PathEscape(projectId))
|
||||
err := l.AuthSession.Do(&result, "GET", "/4.0", path, nil, nil, options)
|
||||
return result, err
|
||||
}
|
||||
|
||||
type Directory struct {
|
||||
Path string `json:"path"`
|
||||
}
|
||||
|
||||
func CreateProjectDirectory(l *v4.LookerSDK, projectId string, directoryPath string, options *rtl.ApiSettings) (string, error) {
|
||||
d := Directory{
|
||||
Path: directoryPath,
|
||||
}
|
||||
var result string
|
||||
path := fmt.Sprintf("/projects/%s/directories", url.PathEscape(projectId))
|
||||
err := l.AuthSession.Do(&result, "POST", "/4.0", path, nil, d, options)
|
||||
return result, err
|
||||
}
|
||||
|
||||
func DeleteProjectDirectory(l *v4.LookerSDK, projectId string, directoryPath string, options *rtl.ApiSettings) (string, error) {
|
||||
var query = map[string]any{
|
||||
"path": directoryPath,
|
||||
}
|
||||
var result string
|
||||
path := fmt.Sprintf("/projects/%s/directories", url.PathEscape(projectId))
|
||||
err := l.AuthSession.Do(&result, "DELETE", "/4.0", path, query, nil, options)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
// 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 lookercreateprojectdirectory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools/looker/lookercommon"
|
||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||
|
||||
"github.com/looker-open-source/sdk-codegen/go/rtl"
|
||||
v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4"
|
||||
)
|
||||
|
||||
const resourceType string = "looker-create-project-directory"
|
||||
|
||||
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{Name: name}
|
||||
if err := decoder.DecodeContext(ctx, &actual); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return actual, nil
|
||||
}
|
||||
|
||||
type compatibleSource interface {
|
||||
UseClientAuthorization() bool
|
||||
GetAuthTokenHeaderName() string
|
||||
LookerApiSettings() *rtl.ApiSettings
|
||||
GetLookerSDK(string) (*v4.LookerSDK, error)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Type string `yaml:"type" validate:"required"`
|
||||
Source string `yaml:"source" validate:"required"`
|
||||
Description string `yaml:"description" validate:"required"`
|
||||
AuthRequired []string `yaml:"authRequired"`
|
||||
Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.ToolConfig = Config{}
|
||||
|
||||
func (cfg Config) ToolConfigType() string {
|
||||
return resourceType
|
||||
}
|
||||
|
||||
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
|
||||
projectIdParameter := parameters.NewStringParameter("project_id", "The id of the project")
|
||||
directoryPathParameter := parameters.NewStringParameter("directory_path", "The path to create in the project")
|
||||
params := parameters.Parameters{projectIdParameter, directoryPathParameter}
|
||||
|
||||
annotations := cfg.Annotations
|
||||
if annotations == nil {
|
||||
readOnlyHint := true
|
||||
annotations = &tools.ToolAnnotations{
|
||||
ReadOnlyHint: &readOnlyHint,
|
||||
}
|
||||
}
|
||||
|
||||
mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, params, annotations)
|
||||
|
||||
// finish tool setup
|
||||
return Tool{
|
||||
Config: cfg,
|
||||
Parameters: params,
|
||||
manifest: tools.Manifest{
|
||||
Description: cfg.Description,
|
||||
Parameters: params.Manifest(),
|
||||
AuthRequired: cfg.AuthRequired,
|
||||
},
|
||||
mcpManifest: mcpManifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.Tool = Tool{}
|
||||
|
||||
type Tool struct {
|
||||
Config
|
||||
Parameters parameters.Parameters `yaml:"parameters"`
|
||||
manifest tools.Manifest
|
||||
mcpManifest tools.McpManifest
|
||||
}
|
||||
|
||||
func (t Tool) ToConfig() tools.ToolConfig {
|
||||
return t.Config
|
||||
}
|
||||
|
||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sdk, err := source.GetLookerSDK(string(accessToken))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting sdk: %w", err)
|
||||
}
|
||||
|
||||
mapParams := params.AsMap()
|
||||
projectId, ok := mapParams["project_id"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'project_id' must be a string, got %T", mapParams["project_id"])
|
||||
}
|
||||
directoryPath, ok := mapParams["directory_path"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'directory_path' must be a string, got %T", mapParams["directory_path"])
|
||||
}
|
||||
|
||||
_, err = lookercommon.CreateProjectDirectory(sdk, projectId, directoryPath, source.LookerApiSettings())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error making create_project_directory request: %s", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Created directory %s in project %s", directoryPath, projectId), nil
|
||||
}
|
||||
|
||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||
return parameters.EmbedParams(ctx, t.Parameters, paramValues, embeddingModelsMap, nil)
|
||||
}
|
||||
|
||||
func (t Tool) Manifest() tools.Manifest {
|
||||
return t.manifest
|
||||
}
|
||||
|
||||
func (t Tool) McpManifest() tools.McpManifest {
|
||||
return t.mcpManifest
|
||||
}
|
||||
|
||||
func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return source.UseClientAuthorization(), nil
|
||||
}
|
||||
|
||||
func (t Tool) Authorized(verifiedAuthServices []string) bool {
|
||||
return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
|
||||
}
|
||||
|
||||
func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return source.GetAuthTokenHeaderName(), nil
|
||||
}
|
||||
|
||||
func (t Tool) GetParameters() parameters.Parameters {
|
||||
return t.Parameters
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// 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 lookercreateprojectdirectory_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/googleapis/genai-toolbox/internal/server"
|
||||
"github.com/googleapis/genai-toolbox/internal/testutils"
|
||||
lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookercreateprojectdirectory"
|
||||
)
|
||||
|
||||
func TestParseFromYamlLookerCreateProjectDirectory(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
want server.ToolConfigs
|
||||
}{
|
||||
{
|
||||
desc: "basic example",
|
||||
in: `
|
||||
kind: tools
|
||||
name: example_tool
|
||||
type: looker-create-project-directory
|
||||
source: my-instance
|
||||
description: some description
|
||||
`,
|
||||
want: server.ToolConfigs{
|
||||
"example_tool": lkr.Config{
|
||||
Name: "example_tool",
|
||||
Type: "looker-create-project-directory",
|
||||
Source: "my-instance",
|
||||
Description: "some description",
|
||||
AuthRequired: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
// Parse contents
|
||||
_, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to unmarshal: %s", err)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Fatalf("incorrect parse: diff %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFailParseFromYamlLookerCreateProjectDirectory(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
desc: "Invalid method",
|
||||
in: `
|
||||
kind: tools
|
||||
name: example_tool
|
||||
type: looker-create-project-directory
|
||||
source: my-instance
|
||||
method: GOT
|
||||
description: some description
|
||||
`,
|
||||
err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-create-project-directory\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-create-project-directory",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
_, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in))
|
||||
if err == nil {
|
||||
t.Fatalf("expect parsing to fail")
|
||||
}
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, tc.err) {
|
||||
t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
// 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 lookerdeleteprojectdirectory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools/looker/lookercommon"
|
||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||
|
||||
"github.com/looker-open-source/sdk-codegen/go/rtl"
|
||||
v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4"
|
||||
)
|
||||
|
||||
const resourceType string = "looker-delete-project-directory"
|
||||
|
||||
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{Name: name}
|
||||
if err := decoder.DecodeContext(ctx, &actual); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return actual, nil
|
||||
}
|
||||
|
||||
type compatibleSource interface {
|
||||
UseClientAuthorization() bool
|
||||
GetAuthTokenHeaderName() string
|
||||
LookerApiSettings() *rtl.ApiSettings
|
||||
GetLookerSDK(string) (*v4.LookerSDK, error)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Type string `yaml:"type" validate:"required"`
|
||||
Source string `yaml:"source" validate:"required"`
|
||||
Description string `yaml:"description" validate:"required"`
|
||||
AuthRequired []string `yaml:"authRequired"`
|
||||
Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.ToolConfig = Config{}
|
||||
|
||||
func (cfg Config) ToolConfigType() string {
|
||||
return resourceType
|
||||
}
|
||||
|
||||
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
|
||||
projectIdParameter := parameters.NewStringParameter("project_id", "The id of the project")
|
||||
directoryPathParameter := parameters.NewStringParameter("directory_path", "The path to delete in the project")
|
||||
params := parameters.Parameters{projectIdParameter, directoryPathParameter}
|
||||
|
||||
annotations := cfg.Annotations
|
||||
if annotations == nil {
|
||||
readOnlyHint := true
|
||||
annotations = &tools.ToolAnnotations{
|
||||
ReadOnlyHint: &readOnlyHint,
|
||||
}
|
||||
}
|
||||
|
||||
mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, params, annotations)
|
||||
|
||||
// finish tool setup
|
||||
return Tool{
|
||||
Config: cfg,
|
||||
Parameters: params,
|
||||
manifest: tools.Manifest{
|
||||
Description: cfg.Description,
|
||||
Parameters: params.Manifest(),
|
||||
AuthRequired: cfg.AuthRequired,
|
||||
},
|
||||
mcpManifest: mcpManifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.Tool = Tool{}
|
||||
|
||||
type Tool struct {
|
||||
Config
|
||||
Parameters parameters.Parameters `yaml:"parameters"`
|
||||
manifest tools.Manifest
|
||||
mcpManifest tools.McpManifest
|
||||
}
|
||||
|
||||
func (t Tool) ToConfig() tools.ToolConfig {
|
||||
return t.Config
|
||||
}
|
||||
|
||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sdk, err := source.GetLookerSDK(string(accessToken))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting sdk: %w", err)
|
||||
}
|
||||
|
||||
mapParams := params.AsMap()
|
||||
projectId, ok := mapParams["project_id"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'project_id' must be a string, got %T", mapParams["project_id"])
|
||||
}
|
||||
directoryPath, ok := mapParams["directory_path"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'directory_path' must be a string, got %T", mapParams["directory_path"])
|
||||
}
|
||||
|
||||
_, err = lookercommon.DeleteProjectDirectory(sdk, projectId, directoryPath, source.LookerApiSettings())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error making delete_project_directory request: %s", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Deleted directory %s in project %s", directoryPath, projectId), nil
|
||||
}
|
||||
|
||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||
return parameters.EmbedParams(ctx, t.Parameters, paramValues, embeddingModelsMap, nil)
|
||||
}
|
||||
|
||||
func (t Tool) Manifest() tools.Manifest {
|
||||
return t.manifest
|
||||
}
|
||||
|
||||
func (t Tool) McpManifest() tools.McpManifest {
|
||||
return t.mcpManifest
|
||||
}
|
||||
|
||||
func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return source.UseClientAuthorization(), nil
|
||||
}
|
||||
|
||||
func (t Tool) Authorized(verifiedAuthServices []string) bool {
|
||||
return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
|
||||
}
|
||||
|
||||
func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return source.GetAuthTokenHeaderName(), nil
|
||||
}
|
||||
|
||||
func (t Tool) GetParameters() parameters.Parameters {
|
||||
return t.Parameters
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// 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 lookerdeleteprojectdirectory_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/googleapis/genai-toolbox/internal/server"
|
||||
"github.com/googleapis/genai-toolbox/internal/testutils"
|
||||
lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookerdeleteprojectdirectory"
|
||||
)
|
||||
|
||||
func TestParseFromYamlLookerDeleteProjectDirectory(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
want server.ToolConfigs
|
||||
}{
|
||||
{
|
||||
desc: "basic example",
|
||||
in: `
|
||||
kind: tools
|
||||
name: example_tool
|
||||
type: looker-delete-project-directory
|
||||
source: my-instance
|
||||
description: some description
|
||||
`,
|
||||
want: server.ToolConfigs{
|
||||
"example_tool": lkr.Config{
|
||||
Name: "example_tool",
|
||||
Type: "looker-delete-project-directory",
|
||||
Source: "my-instance",
|
||||
Description: "some description",
|
||||
AuthRequired: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
// Parse contents
|
||||
_, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to unmarshal: %s", err)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Fatalf("incorrect parse: diff %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFailParseFromYamlLookerDeleteProjectDirectory(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
desc: "Invalid method",
|
||||
in: `
|
||||
kind: tools
|
||||
name: example_tool
|
||||
type: looker-delete-project-directory
|
||||
source: my-instance
|
||||
method: GOT
|
||||
description: some description
|
||||
`,
|
||||
err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-delete-project-directory\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-delete-project-directory",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
_, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in))
|
||||
if err == nil {
|
||||
t.Fatalf("expect parsing to fail")
|
||||
}
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, tc.err) {
|
||||
t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
// 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 lookergetprojectdirectories
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
yaml "github.com/goccy/go-yaml"
|
||||
"github.com/googleapis/genai-toolbox/internal/embeddingmodels"
|
||||
"github.com/googleapis/genai-toolbox/internal/sources"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools"
|
||||
"github.com/googleapis/genai-toolbox/internal/tools/looker/lookercommon"
|
||||
"github.com/googleapis/genai-toolbox/internal/util"
|
||||
"github.com/googleapis/genai-toolbox/internal/util/parameters"
|
||||
|
||||
"github.com/looker-open-source/sdk-codegen/go/rtl"
|
||||
v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4"
|
||||
)
|
||||
|
||||
const resourceType string = "looker-get-project-directories"
|
||||
|
||||
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{Name: name}
|
||||
if err := decoder.DecodeContext(ctx, &actual); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return actual, nil
|
||||
}
|
||||
|
||||
type compatibleSource interface {
|
||||
UseClientAuthorization() bool
|
||||
GetAuthTokenHeaderName() string
|
||||
LookerApiSettings() *rtl.ApiSettings
|
||||
GetLookerSDK(string) (*v4.LookerSDK, error)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string `yaml:"name" validate:"required"`
|
||||
Type string `yaml:"type" validate:"required"`
|
||||
Source string `yaml:"source" validate:"required"`
|
||||
Description string `yaml:"description" validate:"required"`
|
||||
AuthRequired []string `yaml:"authRequired"`
|
||||
Annotations *tools.ToolAnnotations `yaml:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.ToolConfig = Config{}
|
||||
|
||||
func (cfg Config) ToolConfigType() string {
|
||||
return resourceType
|
||||
}
|
||||
|
||||
func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
|
||||
projectIdParameter := parameters.NewStringParameter("project_id", "The id of the project")
|
||||
params := parameters.Parameters{projectIdParameter}
|
||||
|
||||
annotations := cfg.Annotations
|
||||
if annotations == nil {
|
||||
readOnlyHint := true
|
||||
annotations = &tools.ToolAnnotations{
|
||||
ReadOnlyHint: &readOnlyHint,
|
||||
}
|
||||
}
|
||||
|
||||
mcpManifest := tools.GetMcpManifest(cfg.Name, cfg.Description, cfg.AuthRequired, params, annotations)
|
||||
|
||||
// finish tool setup
|
||||
return Tool{
|
||||
Config: cfg,
|
||||
Parameters: params,
|
||||
manifest: tools.Manifest{
|
||||
Description: cfg.Description,
|
||||
Parameters: params.Manifest(),
|
||||
AuthRequired: cfg.AuthRequired,
|
||||
},
|
||||
mcpManifest: mcpManifest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// validate interface
|
||||
var _ tools.Tool = Tool{}
|
||||
|
||||
type Tool struct {
|
||||
Config
|
||||
Parameters parameters.Parameters `yaml:"parameters"`
|
||||
manifest tools.Manifest
|
||||
mcpManifest tools.McpManifest
|
||||
}
|
||||
|
||||
func (t Tool) ToConfig() tools.ToolConfig {
|
||||
return t.Config
|
||||
}
|
||||
|
||||
func (t Tool) Invoke(ctx context.Context, resourceMgr tools.SourceProvider, params parameters.ParamValues, accessToken tools.AccessToken) (any, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logger, err := util.LoggerFromContext(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to get logger from ctx: %s", err)
|
||||
}
|
||||
|
||||
sdk, err := source.GetLookerSDK(string(accessToken))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting sdk: %w", err)
|
||||
}
|
||||
|
||||
mapParams := params.AsMap()
|
||||
projectId, ok := mapParams["project_id"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("'project_id' must be a string, got %T", mapParams["project_id"])
|
||||
}
|
||||
|
||||
resp, err := lookercommon.GetProjectDirectories(sdk, projectId, source.LookerApiSettings())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error making get_project_directories request: %s", err)
|
||||
}
|
||||
|
||||
logger.DebugContext(ctx, "Got response of %v\n", resp)
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (t Tool) EmbedParams(ctx context.Context, paramValues parameters.ParamValues, embeddingModelsMap map[string]embeddingmodels.EmbeddingModel) (parameters.ParamValues, error) {
|
||||
return parameters.EmbedParams(ctx, t.Parameters, paramValues, embeddingModelsMap, nil)
|
||||
}
|
||||
|
||||
func (t Tool) Manifest() tools.Manifest {
|
||||
return t.manifest
|
||||
}
|
||||
|
||||
func (t Tool) McpManifest() tools.McpManifest {
|
||||
return t.mcpManifest
|
||||
}
|
||||
|
||||
func (t Tool) RequiresClientAuthorization(resourceMgr tools.SourceProvider) (bool, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return source.UseClientAuthorization(), nil
|
||||
}
|
||||
|
||||
func (t Tool) Authorized(verifiedAuthServices []string) bool {
|
||||
return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
|
||||
}
|
||||
|
||||
func (t Tool) GetAuthTokenHeaderName(resourceMgr tools.SourceProvider) (string, error) {
|
||||
source, err := tools.GetCompatibleSource[compatibleSource](resourceMgr, t.Source, t.Name, t.Type)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return source.GetAuthTokenHeaderName(), nil
|
||||
}
|
||||
|
||||
func (t Tool) GetParameters() parameters.Parameters {
|
||||
return t.Parameters
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// 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 lookergetprojectdirectories_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/googleapis/genai-toolbox/internal/server"
|
||||
"github.com/googleapis/genai-toolbox/internal/testutils"
|
||||
lkr "github.com/googleapis/genai-toolbox/internal/tools/looker/lookergetprojectdirectories"
|
||||
)
|
||||
|
||||
func TestParseFromYamlLookerGetProjectDirectories(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
want server.ToolConfigs
|
||||
}{
|
||||
{
|
||||
desc: "basic example",
|
||||
in: `
|
||||
kind: tools
|
||||
name: example_tool
|
||||
type: looker-get-project-directories
|
||||
source: my-instance
|
||||
description: some description
|
||||
`,
|
||||
want: server.ToolConfigs{
|
||||
"example_tool": lkr.Config{
|
||||
Name: "example_tool",
|
||||
Type: "looker-get-project-directories",
|
||||
Source: "my-instance",
|
||||
Description: "some description",
|
||||
AuthRequired: []string{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
// Parse contents
|
||||
_, _, _, got, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in))
|
||||
if err != nil {
|
||||
t.Fatalf("unable to unmarshal: %s", err)
|
||||
}
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Fatalf("incorrect parse: diff %v", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFailParseFromYamlLookerGetProjectDirectories(t *testing.T) {
|
||||
ctx, err := testutils.ContextWithNewLogger()
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %s", err)
|
||||
}
|
||||
tcs := []struct {
|
||||
desc string
|
||||
in string
|
||||
err string
|
||||
}{
|
||||
{
|
||||
desc: "Invalid method",
|
||||
in: `
|
||||
kind: tools
|
||||
name: example_tool
|
||||
type: looker-get-project-directories
|
||||
source: my-instance
|
||||
method: GOT
|
||||
description: some description
|
||||
`,
|
||||
err: "error unmarshaling tools: unable to parse tool \"example_tool\" as type \"looker-get-project-directories\": [3:1] unknown field \"method\"\n 1 | authRequired: []\n 2 | description: some description\n> 3 | method: GOT\n ^\n 4 | name: example_tool\n 5 | source: my-instance\n 6 | type: looker-get-project-directories",
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
_, _, _, _, _, _, err := server.UnmarshalResourceConfig(ctx, testutils.FormatYaml(tc.in))
|
||||
if err == nil {
|
||||
t.Fatalf("expect parsing to fail")
|
||||
}
|
||||
errStr := err.Error()
|
||||
if !strings.Contains(errStr, tc.err) {
|
||||
t.Fatalf("unexpected error string: got %q, want substring %q", errStr, tc.err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
@@ -222,6 +222,21 @@ func TestLooker(t *testing.T) {
|
||||
"source": "my-instance",
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
},
|
||||
"get_project_directories": map[string]any{
|
||||
"type": "looker-get-project-directories",
|
||||
"source": "my-instance",
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
},
|
||||
"create_project_directory": map[string]any{
|
||||
"type": "looker-create-project-directory",
|
||||
"source": "my-instance",
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
},
|
||||
"delete_project_directory": map[string]any{
|
||||
"type": "looker-delete-project-directory",
|
||||
"source": "my-instance",
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
},
|
||||
"validate_project": map[string]any{
|
||||
"type": "looker-validate-project",
|
||||
"source": "my-instance",
|
||||
@@ -1451,6 +1466,71 @@ func TestLooker(t *testing.T) {
|
||||
},
|
||||
},
|
||||
)
|
||||
tests.RunToolGetTestByName(t, "get_project_directories",
|
||||
map[string]any{
|
||||
"get_project_directories": map[string]any{
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
"authRequired": []any{},
|
||||
"parameters": []any{
|
||||
map[string]any{
|
||||
"authSources": []any{},
|
||||
"description": "The id of the project",
|
||||
"name": "project_id",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
tests.RunToolGetTestByName(t, "create_project_directory",
|
||||
map[string]any{
|
||||
"create_project_directory": map[string]any{
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
"authRequired": []any{},
|
||||
"parameters": []any{
|
||||
map[string]any{
|
||||
"authSources": []any{},
|
||||
"description": "The id of the project",
|
||||
"name": "project_id",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
},
|
||||
map[string]any{
|
||||
"authSources": []any{},
|
||||
"description": "The path to create in the project",
|
||||
"name": "directory_path",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
tests.RunToolGetTestByName(t, "delete_project_directory",
|
||||
map[string]any{
|
||||
"delete_project_directory": map[string]any{
|
||||
"description": "Simple tool to test end to end functionality.",
|
||||
"authRequired": []any{},
|
||||
"parameters": []any{
|
||||
map[string]any{
|
||||
"authSources": []any{},
|
||||
"description": "The id of the project",
|
||||
"name": "project_id",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
},
|
||||
map[string]any{
|
||||
"authSources": []any{},
|
||||
"description": "The path to delete in the project",
|
||||
"name": "directory_path",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
tests.RunToolGetTestByName(t, "validate_project",
|
||||
map[string]any{
|
||||
"validate_project": map[string]any{
|
||||
@@ -1687,6 +1767,15 @@ func TestLooker(t *testing.T) {
|
||||
wantResult = "deleted"
|
||||
tests.RunToolInvokeParametersTest(t, "delete_project_file", []byte(`{"project_id": "the_look", "file_path": "foo.view.lkml"}`), wantResult)
|
||||
|
||||
wantResult = "created"
|
||||
tests.RunToolInvokeParametersTest(t, "create_project_directory", []byte(`{"project_id": "the_look", "directory_path": "foo_dir"}`), wantResult)
|
||||
|
||||
wantResult = "foo_dir"
|
||||
tests.RunToolInvokeParametersTest(t, "get_project_directories", []byte(`{"project_id": "the_look"}`), wantResult)
|
||||
|
||||
wantResult = "deleted"
|
||||
tests.RunToolInvokeParametersTest(t, "delete_project_directory", []byte(`{"project_id": "the_look", "directory_path": "foo_dir"}`), wantResult)
|
||||
|
||||
wantResult = "\"errors\":[]"
|
||||
tests.RunToolInvokeParametersTest(t, "validate_project", []byte(`{"project_id": "the_look"}`), wantResult)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user