mirror of
https://github.com/googleapis/genai-toolbox.git
synced 2026-01-08 15:14:00 -05:00
1881 lines
60 KiB
Go
1881 lines
60 KiB
Go
// Copyright 2024 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 looker
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/googleapis/genai-toolbox/internal/log"
|
|
"github.com/googleapis/genai-toolbox/internal/testutils"
|
|
"github.com/googleapis/genai-toolbox/internal/util"
|
|
"github.com/googleapis/genai-toolbox/tests"
|
|
|
|
"github.com/looker-open-source/sdk-codegen/go/rtl"
|
|
v4 "github.com/looker-open-source/sdk-codegen/go/sdk/v4"
|
|
)
|
|
|
|
var (
|
|
LookerSourceKind = "looker"
|
|
LookerBaseUrl = os.Getenv("LOOKER_BASE_URL")
|
|
LookerVerifySsl = os.Getenv("LOOKER_VERIFY_SSL")
|
|
LookerClientId = os.Getenv("LOOKER_CLIENT_ID")
|
|
LookerClientSecret = os.Getenv("LOOKER_CLIENT_SECRET")
|
|
LookerProject = os.Getenv("LOOKER_PROJECT")
|
|
LookerLocation = os.Getenv("LOOKER_LOCATION")
|
|
)
|
|
|
|
func getLookerVars(t *testing.T) map[string]any {
|
|
switch "" {
|
|
case LookerBaseUrl:
|
|
t.Fatal("'LOOKER_BASE_URL' not set")
|
|
case LookerVerifySsl:
|
|
t.Fatal("'LOOKER_VERIFY_SSL' not set")
|
|
case LookerClientId:
|
|
t.Fatal("'LOOKER_CLIENT_ID' not set")
|
|
case LookerClientSecret:
|
|
t.Fatal("'LOOKER_CLIENT_SECRET' not set")
|
|
case LookerProject:
|
|
t.Fatal("'LOOKER_PROJECT' not set")
|
|
case LookerLocation:
|
|
t.Fatal("'LOOKER_LOCATION' not set")
|
|
}
|
|
|
|
return map[string]any{
|
|
"kind": LookerSourceKind,
|
|
"base_url": LookerBaseUrl,
|
|
"verify_ssl": (LookerVerifySsl == "true"),
|
|
"client_id": LookerClientId,
|
|
"client_secret": LookerClientSecret,
|
|
"project": LookerProject,
|
|
"location": LookerLocation,
|
|
}
|
|
}
|
|
|
|
func TestLooker(t *testing.T) {
|
|
sourceConfig := getLookerVars(t)
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
|
defer cancel()
|
|
|
|
testLogger, err := log.NewStdLogger(os.Stdout, os.Stderr, "info")
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %s", err)
|
|
}
|
|
ctx = util.WithLogger(ctx, testLogger)
|
|
|
|
var args []string
|
|
|
|
// Write config into a file and pass it to command
|
|
|
|
toolsFile := map[string]any{
|
|
"sources": map[string]any{
|
|
"my-instance": sourceConfig,
|
|
},
|
|
"tools": map[string]any{
|
|
"get_models": map[string]any{
|
|
"kind": "looker-get-models",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_explores": map[string]any{
|
|
"kind": "looker-get-explores",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_dimensions": map[string]any{
|
|
"kind": "looker-get-dimensions",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_measures": map[string]any{
|
|
"kind": "looker-get-measures",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_filters": map[string]any{
|
|
"kind": "looker-get-filters",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_parameters": map[string]any{
|
|
"kind": "looker-get-parameters",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"query": map[string]any{
|
|
"kind": "looker-query",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"query_sql": map[string]any{
|
|
"kind": "looker-query-sql",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"query_url": map[string]any{
|
|
"kind": "looker-query-url",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_looks": map[string]any{
|
|
"kind": "looker-get-looks",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"make_look": map[string]any{
|
|
"kind": "looker-make-look",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_dashboards": map[string]any{
|
|
"kind": "looker-get-dashboards",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"make_dashboard": map[string]any{
|
|
"kind": "looker-make-dashboard",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"add_dashboard_filter": map[string]any{
|
|
"kind": "looker-add-dashboard-filter",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"add_dashboard_element": map[string]any{
|
|
"kind": "looker-add-dashboard-element",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"conversational_analytics": map[string]any{
|
|
"kind": "looker-conversational-analytics",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"health_pulse": map[string]any{
|
|
"kind": "looker-health-pulse",
|
|
"source": "my-instance",
|
|
"description": "Checks the health of a Looker instance by running a series of checks on the system.",
|
|
},
|
|
"health_analyze": map[string]any{
|
|
"kind": "looker-health-analyze",
|
|
"source": "my-instance",
|
|
"description": "Provides analysis of a Looker instance's projects, models, or explores.",
|
|
},
|
|
"health_vacuum": map[string]any{
|
|
"kind": "looker-health-vacuum",
|
|
"source": "my-instance",
|
|
"description": "Vacuums unused content from a Looker instance.",
|
|
},
|
|
"dev_mode": map[string]any{
|
|
"kind": "looker-dev-mode",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_projects": map[string]any{
|
|
"kind": "looker-get-projects",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_project_files": map[string]any{
|
|
"kind": "looker-get-project-files",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_project_file": map[string]any{
|
|
"kind": "looker-get-project-file",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"create_project_file": map[string]any{
|
|
"kind": "looker-create-project-file",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"update_project_file": map[string]any{
|
|
"kind": "looker-update-project-file",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"delete_project_file": map[string]any{
|
|
"kind": "looker-delete-project-file",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"generate_embed_url": map[string]any{
|
|
"kind": "looker-generate-embed-url",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_connections": map[string]any{
|
|
"kind": "looker-get-connections",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_connection_schemas": map[string]any{
|
|
"kind": "looker-get-connection-schemas",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_connection_databases": map[string]any{
|
|
"kind": "looker-get-connection-databases",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_connection_tables": map[string]any{
|
|
"kind": "looker-get-connection-tables",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
"get_connection_table_columns": map[string]any{
|
|
"kind": "looker-get-connection-table-columns",
|
|
"source": "my-instance",
|
|
"description": "Simple tool to test end to end functionality.",
|
|
},
|
|
},
|
|
}
|
|
|
|
cmd, cleanup, err := tests.StartCmd(ctx, toolsFile, args...)
|
|
if err != nil {
|
|
t.Fatalf("command initialization returned an error: %s", err)
|
|
}
|
|
defer cleanup()
|
|
|
|
waitCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
|
defer cancel()
|
|
out, err := testutils.WaitForString(waitCtx, regexp.MustCompile(`Server ready to serve`), cmd.Out)
|
|
if err != nil {
|
|
t.Logf("toolbox command logs: \n%s", out)
|
|
t.Fatalf("toolbox didn't start successfully: %s", err)
|
|
}
|
|
|
|
tests.RunToolGetTestByName(t, "get_models",
|
|
map[string]any{
|
|
"get_models": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_explores",
|
|
map[string]any{
|
|
"get_explores": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explores.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_dimensions",
|
|
map[string]any{
|
|
"get_dimensions": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore containing the fields.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_measures",
|
|
map[string]any{
|
|
"get_measures": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore containing the fields.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_parameters",
|
|
map[string]any{
|
|
"get_parameters": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore containing the fields.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_filters",
|
|
map[string]any{
|
|
"get_filters": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore containing the fields.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "query",
|
|
map[string]any{
|
|
"query": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore to be queried.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The fields to be retrieved.",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be returned in the query",
|
|
"name": "field",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
"name": "fields",
|
|
"required": true,
|
|
"type": "array",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The filters for the query",
|
|
"name": "filters",
|
|
"required": false,
|
|
"default": map[string]any{},
|
|
"type": "object",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query pivots (must be included in fields as well).",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a pivot in the query",
|
|
"name": "pivot_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "pivots",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The sorts like \"field.id desc 0\".",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a sort in the query",
|
|
"name": "sort_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "sorts",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The row limit.",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(500),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query timezone.",
|
|
"name": "tz",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "query_sql",
|
|
map[string]any{
|
|
"query_sql": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore to be queried.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The fields to be retrieved.",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be returned in the query",
|
|
"name": "field",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
"name": "fields",
|
|
"required": true,
|
|
"type": "array",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The filters for the query",
|
|
"name": "filters",
|
|
"required": false,
|
|
"default": map[string]any{},
|
|
"type": "object",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query pivots (must be included in fields as well).",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a pivot in the query",
|
|
"name": "pivot_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "pivots",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The sorts like \"field.id desc 0\".",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a sort in the query",
|
|
"name": "sort_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "sorts",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The row limit.",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(500),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query timezone.",
|
|
"name": "tz",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "query_url",
|
|
map[string]any{
|
|
"query_url": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore to be queried.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The fields to be retrieved.",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be returned in the query",
|
|
"name": "field",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
"name": "fields",
|
|
"required": true,
|
|
"type": "array",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The filters for the query",
|
|
"name": "filters",
|
|
"required": false,
|
|
"default": map[string]any{},
|
|
"type": "object",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query pivots (must be included in fields as well).",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a pivot in the query",
|
|
"name": "pivot_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "pivots",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The sorts like \"field.id desc 0\".",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a sort in the query",
|
|
"name": "sort_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "sorts",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The row limit.",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(500),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query timezone.",
|
|
"name": "tz",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The visualization config for the query",
|
|
"name": "vis_config",
|
|
"required": false,
|
|
"type": "object",
|
|
"default": map[string]any{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_looks",
|
|
map[string]any{
|
|
"get_looks": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The title of the look.",
|
|
"name": "title",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The description of the look.",
|
|
"name": "desc",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The number of looks to fetch. Default 100",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(100),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The number of looks to skip before fetching. Default 0",
|
|
"name": "offset",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "make_look",
|
|
map[string]any{
|
|
"make_look": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore to be queried.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The fields to be retrieved.",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be returned in the query",
|
|
"name": "field",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
"name": "fields",
|
|
"required": true,
|
|
"type": "array",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The filters for the query",
|
|
"name": "filters",
|
|
"required": false,
|
|
"default": map[string]any{},
|
|
"type": "object",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query pivots (must be included in fields as well).",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a pivot in the query",
|
|
"name": "pivot_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "pivots",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The sorts like \"field.id desc 0\".",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a sort in the query",
|
|
"name": "sort_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "sorts",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The row limit.",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(500),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query timezone.",
|
|
"name": "tz",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The title of the Look",
|
|
"name": "title",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The description of the Look",
|
|
"name": "description",
|
|
"required": false,
|
|
"default": "",
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The folder id where the Look will be created. Leave blank to use the user's personal folder",
|
|
"name": "folder",
|
|
"required": false,
|
|
"default": "",
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The visualization config for the query",
|
|
"name": "vis_config",
|
|
"required": false,
|
|
"type": "object",
|
|
"default": map[string]any{},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_dashboards",
|
|
map[string]any{
|
|
"get_dashboards": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The title of the dashboard.",
|
|
"name": "title",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The description of the dashboard.",
|
|
"name": "desc",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The number of dashboards to fetch. Default 100",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(100),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The number of dashboards to skip before fetching. Default 0",
|
|
"name": "offset",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "make_dashboard",
|
|
map[string]any{
|
|
"make_dashboard": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The title of the Dashboard",
|
|
"name": "title",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The description of the Dashboard",
|
|
"name": "description",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The folder id where the Dashboard will be created. Leave blank to use the user's personal folder",
|
|
"name": "folder",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "add_dashboard_filter",
|
|
map[string]any{
|
|
"add_dashboard_filter": 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 dashboard where this filter will exist",
|
|
"name": "dashboard_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The name of the Dashboard Filter",
|
|
"name": "name",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The title of the Dashboard Filter",
|
|
"name": "title",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The filter_type of the Dashboard Filter: date_filter, number_filter, string_filter, field_filter (default field_filter)",
|
|
"name": "filter_type",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "field_filter",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The default_value of the Dashboard Filter (optional)",
|
|
"name": "default_value",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model of a field type Dashboard Filter (required if type field)",
|
|
"name": "model",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore of a field type Dashboard Filter (required if type field)",
|
|
"name": "explore",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The dimension of a field type Dashboard Filter (required if type field)",
|
|
"name": "dimension",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Dashboard Filter should allow multiple values (default true)",
|
|
"name": "allow_multiple_values",
|
|
"required": false,
|
|
"type": "boolean",
|
|
"default": true,
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Dashboard Filter is required to run dashboard (default false)",
|
|
"name": "required",
|
|
"required": false,
|
|
"type": "boolean",
|
|
"default": false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "add_dashboard_element",
|
|
map[string]any{
|
|
"add_dashboard_element": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The model containing the explore.",
|
|
"name": "model",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The explore to be queried.",
|
|
"name": "explore",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The fields to be retrieved.",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be returned in the query",
|
|
"name": "field",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
"name": "fields",
|
|
"required": true,
|
|
"type": "array",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The filters for the query",
|
|
"name": "filters",
|
|
"required": false,
|
|
"default": map[string]any{},
|
|
"type": "object",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query pivots (must be included in fields as well).",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a pivot in the query",
|
|
"name": "pivot_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "pivots",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The sorts like \"field.id desc 0\".",
|
|
"items": map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A field to be used as a sort in the query",
|
|
"name": "sort_field",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
"name": "sorts",
|
|
"required": false,
|
|
"type": "array",
|
|
"default": []any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The row limit.",
|
|
"name": "limit",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(500),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The query timezone.",
|
|
"name": "tz",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The id of the dashboard where this tile will exist",
|
|
"name": "dashboard_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The title of the Dashboard Element",
|
|
"name": "title",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": "The visualization config for the query",
|
|
"name": "vis_config",
|
|
"required": false,
|
|
"type": "object",
|
|
"default": map[string]any{},
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": `An array of dashboard filters like [{"dashboard_filter_name": "name", "field": "view_name.field_name"}, ...]`,
|
|
"items": map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"description": `A dashboard filter like {"dashboard_filter_name": "name", "field": "view_name.field_name"}`,
|
|
"name": "dashboard_filter",
|
|
"required": false,
|
|
"type": "object",
|
|
"default": map[string]any{},
|
|
},
|
|
"name": "dashboard_filters",
|
|
"required": false,
|
|
"type": "array",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "conversational_analytics",
|
|
map[string]any{
|
|
"conversational_analytics": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The user's question, potentially including conversation history and system instructions for context.",
|
|
"name": "user_query_with_context",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "An Array of at least one and up to 5 explore references like [{'model': 'MODEL_NAME', 'explore': 'EXPLORE_NAME'}]",
|
|
"items": map[string]any{
|
|
"additionalProperties": true,
|
|
"authSources": []any{},
|
|
"name": "explore_reference",
|
|
"description": "An explore reference like {'model': 'MODEL_NAME', 'explore': 'EXPLORE_NAME'}",
|
|
"required": true,
|
|
"type": "object",
|
|
},
|
|
"name": "explore_references",
|
|
"required": true,
|
|
"type": "array",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "health_pulse",
|
|
map[string]any{
|
|
"health_pulse": map[string]any{
|
|
"description": "Checks the health of a Looker instance by running a series of checks on the system.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The health check to run. Can be either: `check_db_connections`, `check_dashboard_performance`,`check_dashboard_errors`,`check_explore_performance`,`check_schedule_failures`, or `check_legacy_features`",
|
|
"name": "action",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "health_analyze",
|
|
map[string]any{
|
|
"health_analyze": map[string]any{
|
|
"description": "Provides analysis of a Looker instance's projects, models, or explores.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The analysis to run. Can be 'projects', 'models', or 'explores'.",
|
|
"name": "action",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Looker project to analyze (optional).",
|
|
"name": "project",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Looker model to analyze (optional).",
|
|
"name": "model",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Looker explore to analyze (optional).",
|
|
"name": "explore",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The timeframe in days to analyze.",
|
|
"name": "timeframe",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(90),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The minimum number of queries for a model or explore to be considered used.",
|
|
"name": "min_queries",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "health_vacuum",
|
|
map[string]any{
|
|
"health_vacuum": map[string]any{
|
|
"description": "Vacuums unused content from a Looker instance.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The vacuum action to run. Can be 'models', or 'explores'.",
|
|
"name": "action",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Looker project to vacuum (optional).",
|
|
"name": "project",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Looker model to vacuum (optional).",
|
|
"name": "model",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The Looker explore to vacuum (optional).",
|
|
"name": "explore",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The timeframe in days to analyze.",
|
|
"name": "timeframe",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(90),
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The minimum number of queries for a model or explore to be considered used.",
|
|
"name": "min_queries",
|
|
"required": false,
|
|
"type": "integer",
|
|
"default": float64(1),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "dev_mode",
|
|
map[string]any{
|
|
"dev_mode": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "Whether to set Dev Mode.",
|
|
"name": "devMode",
|
|
"required": false,
|
|
"type": "boolean",
|
|
"default": true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_projects",
|
|
map[string]any{
|
|
"get_projects": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_project_files",
|
|
map[string]any{
|
|
"get_project_files": 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 containing the files",
|
|
"name": "project_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_project_file",
|
|
map[string]any{
|
|
"get_project_file": 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 containing the files",
|
|
"name": "project_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The path of the file within the project",
|
|
"name": "file_path",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "create_project_file",
|
|
map[string]any{
|
|
"create_project_file": 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 containing the files",
|
|
"name": "project_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The path of the file within the project",
|
|
"name": "file_path",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The content of the file",
|
|
"name": "file_content",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "update_project_file",
|
|
map[string]any{
|
|
"update_project_file": 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 containing the files",
|
|
"name": "project_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The path of the file within the project",
|
|
"name": "file_path",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The content of the file",
|
|
"name": "file_content",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "delete_project_file",
|
|
map[string]any{
|
|
"delete_project_file": 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 containing the files",
|
|
"name": "project_id",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The path of the file within the project",
|
|
"name": "file_path",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "generate_embed_url",
|
|
map[string]any{
|
|
"generate_embed_url": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "Type of Looker content to embed (ie. dashboards, looks, query-visualization)",
|
|
"name": "type",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The ID of the content to embed.",
|
|
"name": "id",
|
|
"required": false,
|
|
"type": "string",
|
|
"default": "",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_connections",
|
|
map[string]any{
|
|
"get_connections": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_connection_schemas",
|
|
map[string]any{
|
|
"get_connection_schemas": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The connection containing the schemas.",
|
|
"name": "conn",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The optional database to search",
|
|
"name": "db",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_connection_databases",
|
|
map[string]any{
|
|
"get_connection_databases": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The connection containing the databases.",
|
|
"name": "conn",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_connection_tables",
|
|
map[string]any{
|
|
"get_connection_tables": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The connection containing the tables.",
|
|
"name": "conn",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The optional database to search",
|
|
"name": "db",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The schema containing the tables.",
|
|
"name": "schema",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
tests.RunToolGetTestByName(t, "get_connection_table_columns",
|
|
map[string]any{
|
|
"get_connection_table_columns": map[string]any{
|
|
"description": "Simple tool to test end to end functionality.",
|
|
"authRequired": []any{},
|
|
"parameters": []any{
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The connection containing the tables.",
|
|
"name": "conn",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The optional database to search",
|
|
"name": "db",
|
|
"required": false,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "The schema containing the tables.",
|
|
"name": "schema",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
map[string]any{
|
|
"authSources": []any{},
|
|
"description": "A comma separated list of tables containing the columns.",
|
|
"name": "tables",
|
|
"required": true,
|
|
"type": "string",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
)
|
|
|
|
wantResult := "{\"connections\":[],\"label\":\"System Activity\",\"name\":\"system__activity\",\"project_name\":\"system__activity\"}"
|
|
tests.RunToolInvokeSimpleTest(t, "get_models", wantResult)
|
|
|
|
wantResult = "{\"description\":\"Data about Look and dashboard usage, including frequency of views, favoriting, scheduling, embedding, and access via the API. Also includes details about individual Looks and dashboards.\",\"group_label\":\"System Activity\",\"label\":\"Content Usage\",\"name\":\"content_usage\"}"
|
|
tests.RunToolInvokeParametersTest(t, "get_explores", []byte(`{"model": "system__activity"}`), wantResult)
|
|
|
|
wantResult = "{\"description\":\"Number of times this content has been viewed via the Looker API\",\"label\":\"Content Usage API Count\",\"label_short\":\"API Count\",\"name\":\"content_usage.api_count\",\"type\":\"number\"}"
|
|
tests.RunToolInvokeParametersTest(t, "get_dimensions", []byte(`{"model": "system__activity", "explore": "content_usage"}`), wantResult)
|
|
|
|
wantResult = "{\"description\":\"The total number of views via the Looker API\",\"label\":\"Content Usage API Total\",\"label_short\":\"API Total\",\"name\":\"content_usage.api_total\",\"type\":\"sum\"}"
|
|
tests.RunToolInvokeParametersTest(t, "get_measures", []byte(`{"model": "system__activity", "explore": "content_usage"}`), wantResult)
|
|
|
|
wantResult = "[]"
|
|
tests.RunToolInvokeParametersTest(t, "get_filters", []byte(`{"model": "system__activity", "explore": "content_usage"}`), wantResult)
|
|
|
|
wantResult = "[]"
|
|
tests.RunToolInvokeParametersTest(t, "get_parameters", []byte(`{"model": "system__activity", "explore": "content_usage"}`), wantResult)
|
|
|
|
wantResult = "{\"look.count\":"
|
|
tests.RunToolInvokeParametersTest(t, "query", []byte(`{"model": "system__activity", "explore": "look", "fields": ["look.count"]}`), wantResult)
|
|
|
|
wantResult = "SELECT"
|
|
tests.RunToolInvokeParametersTest(t, "query_sql", []byte(`{"model": "system__activity", "explore": "look", "fields": ["look.count"]}`), wantResult)
|
|
|
|
wantResult = "system__activity"
|
|
tests.RunToolInvokeParametersTest(t, "query_url", []byte(`{"model": "system__activity", "explore": "look", "fields": ["look.count"]}`), wantResult)
|
|
|
|
// A system that is just being used for testing has no looks or dashboards
|
|
wantResult = "null"
|
|
tests.RunToolInvokeParametersTest(t, "get_looks", []byte(`{"title": "FOO", "desc": "BAR"}`), wantResult)
|
|
|
|
wantResult = "null"
|
|
tests.RunToolInvokeParametersTest(t, "get_dashboards", []byte(`{"title": "FOO", "desc": "BAR"}`), wantResult)
|
|
|
|
wantResult = "\"Connection\":\"thelook\""
|
|
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_db_connections"}`), wantResult)
|
|
|
|
wantResult = "[]"
|
|
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_schedule_failures"}`), wantResult)
|
|
|
|
wantResult = "[{\"Feature\":\"Unsupported in Looker (Google Cloud core)\"}]"
|
|
tests.RunToolInvokeParametersTest(t, "health_pulse", []byte(`{"action": "check_legacy_features"}`), wantResult)
|
|
|
|
wantResult = "\"Project\":\"the_look\""
|
|
tests.RunToolInvokeParametersTest(t, "health_analyze", []byte(`{"action": "projects"}`), wantResult)
|
|
|
|
wantResult = "\"Model\":\"the_look\""
|
|
tests.RunToolInvokeParametersTest(t, "health_analyze", []byte(`{"action": "explores", "project": "the_look", "model": "the_look", "explore": "inventory_items"}`), wantResult)
|
|
|
|
wantResult = "\"Model\":\"the_look\""
|
|
tests.RunToolInvokeParametersTest(t, "health_vacuum", []byte(`{"action": "models"}`), wantResult)
|
|
|
|
wantResult = "the_look"
|
|
tests.RunToolInvokeSimpleTest(t, "get_projects", wantResult)
|
|
|
|
wantResult = "order_items.view"
|
|
tests.RunToolInvokeParametersTest(t, "get_project_files", []byte(`{"project_id": "the_look"}`), wantResult)
|
|
|
|
wantResult = "view"
|
|
tests.RunToolInvokeParametersTest(t, "get_project_file", []byte(`{"project_id": "the_look", "file_path": "order_items.view.lkml"}`), wantResult)
|
|
|
|
wantResult = "dev"
|
|
tests.RunToolInvokeParametersTest(t, "dev_mode", []byte(`{"devMode": true}`), wantResult)
|
|
|
|
wantResult = "created"
|
|
tests.RunToolInvokeParametersTest(t, "create_project_file", []byte(`{"project_id": "the_look", "file_path": "foo.view.lkml", "file_content": "view"}`), wantResult)
|
|
|
|
wantResult = "updated"
|
|
tests.RunToolInvokeParametersTest(t, "update_project_file", []byte(`{"project_id": "the_look", "file_path": "foo.view.lkml", "file_content": "model"}`), wantResult)
|
|
|
|
wantResult = "deleted"
|
|
tests.RunToolInvokeParametersTest(t, "delete_project_file", []byte(`{"project_id": "the_look", "file_path": "foo.view.lkml"}`), wantResult)
|
|
|
|
wantResult = "production"
|
|
tests.RunToolInvokeParametersTest(t, "dev_mode", []byte(`{"devMode": false}`), wantResult)
|
|
|
|
wantResult = "thelook"
|
|
tests.RunToolInvokeSimpleTest(t, "get_connections", wantResult)
|
|
|
|
wantResult = "{\"name\":\"demo_db\",\"is_default\":true}"
|
|
tests.RunToolInvokeParametersTest(t, "get_connection_schemas", []byte(`{"conn": "thelook"}`), wantResult)
|
|
|
|
wantResult = "[]"
|
|
tests.RunToolInvokeParametersTest(t, "get_connection_databases", []byte(`{"conn": "thelook"}`), wantResult)
|
|
|
|
wantResult = "Employees"
|
|
tests.RunToolInvokeParametersTest(t, "get_connection_tables", []byte(`{"conn": "thelook", "schema": "demo_db"}`), wantResult)
|
|
|
|
wantResult = "{\"column_name\":\"EmpID\",\"data_type_database\":\"int\",\"data_type_looker\":\"number\",\"sql_escaped_column_name\":\"EmpID\"}"
|
|
tests.RunToolInvokeParametersTest(t, "get_connection_table_columns", []byte(`{"conn": "thelook", "schema": "demo_db", "tables": "Employees"}`), wantResult)
|
|
|
|
wantResult = "/login/embed?t=" // testing for specific substring, since url is dynamic
|
|
tests.RunToolInvokeParametersTest(t, "generate_embed_url", []byte(`{"type": "dashboards", "id": "1"}`), wantResult)
|
|
|
|
runConversationalAnalytics(t, "system__activity", "content_usage")
|
|
|
|
deleteLook := testMakeLook(t)
|
|
defer deleteLook()
|
|
|
|
dashboardId, deleteDashboard := testMakeDashboard(t)
|
|
defer deleteDashboard()
|
|
testAddDashboardFilter(t, dashboardId)
|
|
testAddDashboardElement(t, dashboardId)
|
|
}
|
|
|
|
func runConversationalAnalytics(t *testing.T, modelName, exploreName string) {
|
|
exploreRefsJSON := fmt.Sprintf(`[{"model":"%s","explore":"%s"}]`, modelName, exploreName)
|
|
|
|
var refs []map[string]any
|
|
if err := json.Unmarshal([]byte(exploreRefsJSON), &refs); err != nil {
|
|
t.Fatalf("failed to unmarshal explore refs: %v", err)
|
|
}
|
|
|
|
testCases := []struct {
|
|
name string
|
|
exploreRefs []map[string]any
|
|
wantStatusCode int
|
|
wantInResult string
|
|
wantInError string
|
|
}{
|
|
{
|
|
name: "invoke conversational analytics with explore",
|
|
exploreRefs: refs,
|
|
wantStatusCode: http.StatusOK,
|
|
wantInResult: `Answer`,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
requestBodyMap := map[string]any{
|
|
"user_query_with_context": "What is in the explore?",
|
|
"explore_references": tc.exploreRefs,
|
|
}
|
|
bodyBytes, err := json.Marshal(requestBodyMap)
|
|
if err != nil {
|
|
t.Fatalf("failed to marshal request body: %v", err)
|
|
}
|
|
url := "http://127.0.0.1:5000/api/tool/conversational_analytics/invoke"
|
|
resp, bodyBytes := tests.RunRequest(t, http.MethodPost, url, bytes.NewBuffer(bodyBytes), nil)
|
|
|
|
if resp.StatusCode != tc.wantStatusCode {
|
|
t.Fatalf("unexpected status code: got %d, want %d. Body: %s", resp.StatusCode, tc.wantStatusCode, string(bodyBytes))
|
|
}
|
|
|
|
if tc.wantInResult != "" {
|
|
var respBody map[string]interface{}
|
|
if err := json.Unmarshal(bodyBytes, &respBody); err != nil {
|
|
t.Fatalf("error parsing response body: %v", err)
|
|
}
|
|
got, ok := respBody["result"].(string)
|
|
if !ok {
|
|
t.Fatalf("unable to find result in response body")
|
|
}
|
|
if !strings.Contains(got, tc.wantInResult) {
|
|
t.Errorf("unexpected result: got %q, want to contain %q", got, tc.wantInResult)
|
|
}
|
|
}
|
|
|
|
if tc.wantInError != "" {
|
|
if !strings.Contains(string(bodyBytes), tc.wantInError) {
|
|
t.Errorf("unexpected error message: got %q, want to contain %q", string(bodyBytes), tc.wantInError)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func newLookerTestSDK(t *testing.T) *v4.LookerSDK {
|
|
t.Helper()
|
|
cfg := rtl.ApiSettings{
|
|
BaseUrl: LookerBaseUrl,
|
|
ApiVersion: "4.0",
|
|
VerifySsl: LookerVerifySsl == "true",
|
|
Timeout: 120,
|
|
ClientId: LookerClientId,
|
|
ClientSecret: LookerClientSecret,
|
|
}
|
|
return v4.NewLookerSDK(rtl.NewAuthSession(cfg))
|
|
}
|
|
|
|
func testMakeLook(t *testing.T) func() {
|
|
var id string
|
|
t.Run("TestMakeLook", func(t *testing.T) {
|
|
reqBody := []byte(`{"model": "system__activity", "explore": "look", "fields": ["look.count"], "title": "TestLook"}`)
|
|
|
|
url := "http://127.0.0.1:5000/api/tool/make_look/invoke"
|
|
resp, bodyBytes := tests.RunRequest(t, http.MethodPost, url, bytes.NewBuffer(reqBody), nil)
|
|
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("unexpected status code: got %d, want %d. Body: %s", resp.StatusCode, 200, string(bodyBytes))
|
|
}
|
|
|
|
var respBody map[string]interface{}
|
|
if err := json.Unmarshal(bodyBytes, &respBody); err != nil {
|
|
t.Fatalf("error parsing response body: %v", err)
|
|
}
|
|
|
|
result := respBody["result"].(string)
|
|
if err := json.Unmarshal([]byte(result), &respBody); err != nil {
|
|
t.Fatalf("error parsing result body: %v", err)
|
|
}
|
|
|
|
var ok bool
|
|
if id, ok = respBody["id"].(string); !ok || id == "" {
|
|
t.Fatalf("didn't get TestLook id, got %s", string(bodyBytes))
|
|
}
|
|
})
|
|
|
|
return func() {
|
|
sdk := newLookerTestSDK(t)
|
|
|
|
if _, err := sdk.DeleteLook(id, nil); err != nil {
|
|
t.Fatalf("error deleting look: %v", err)
|
|
}
|
|
t.Logf("deleted Look %s", id)
|
|
}
|
|
}
|
|
|
|
func testAddDashboardFilter(t *testing.T, dashboardId string) {
|
|
t.Run("TestAddDashboardFilter", func(t *testing.T) {
|
|
reqBody := []byte(fmt.Sprintf(`{"dashboard_id": "%s", "model": "system__activity", "explore": "look", "dimension": "look.created_year", "name": "test_filter", "title": "TestDashboardFilter"}`, dashboardId))
|
|
|
|
url := "http://127.0.0.1:5000/api/tool/add_dashboard_filter/invoke"
|
|
resp, bodyBytes := tests.RunRequest(t, http.MethodPost, url, bytes.NewBuffer(reqBody), nil)
|
|
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("unexpected status code: got %d, want %d. Body: %s", resp.StatusCode, 200, string(bodyBytes))
|
|
}
|
|
|
|
t.Logf("got %s", string(bodyBytes))
|
|
})
|
|
}
|
|
|
|
func testAddDashboardElement(t *testing.T, dashboardId string) {
|
|
t.Run("TestAddDashboardElement", func(t *testing.T) {
|
|
reqBody := []byte(fmt.Sprintf(`{"dashboard_id": "%s", "model": "system__activity", "explore": "look", "fields": ["look.count"], "title": "TestDashboardElement"}`, dashboardId))
|
|
|
|
url := "http://127.0.0.1:5000/api/tool/add_dashboard_element/invoke"
|
|
resp, bodyBytes := tests.RunRequest(t, http.MethodPost, url, bytes.NewBuffer(reqBody), nil)
|
|
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("unexpected status code: got %d, want %d. Body: %s", resp.StatusCode, 200, string(bodyBytes))
|
|
}
|
|
|
|
t.Logf("got %s", string(bodyBytes))
|
|
})
|
|
}
|
|
|
|
func testMakeDashboard(t *testing.T) (string, func()) {
|
|
var id string
|
|
t.Run("TestMakeDashboard", func(t *testing.T) {
|
|
reqBody := []byte(`{"title": "TestDashboard"}`)
|
|
|
|
url := "http://127.0.0.1:5000/api/tool/make_dashboard/invoke"
|
|
resp, bodyBytes := tests.RunRequest(t, http.MethodPost, url, bytes.NewBuffer(reqBody), nil)
|
|
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("unexpected status code: got %d, want %d. Body: %s", resp.StatusCode, 200, string(bodyBytes))
|
|
}
|
|
|
|
var respBody map[string]interface{}
|
|
if err := json.Unmarshal(bodyBytes, &respBody); err != nil {
|
|
t.Fatalf("error parsing response body: %v", err)
|
|
}
|
|
|
|
result := respBody["result"].(string)
|
|
if err := json.Unmarshal([]byte(result), &respBody); err != nil {
|
|
t.Fatalf("error parsing result body: %v", err)
|
|
}
|
|
|
|
var ok bool
|
|
if id, ok = respBody["id"].(string); !ok || id == "" {
|
|
t.Fatalf("didn't get TestDashboard id, got %s", string(bodyBytes))
|
|
}
|
|
})
|
|
|
|
return id, func() {
|
|
sdk := newLookerTestSDK(t)
|
|
|
|
if _, err := sdk.DeleteDashboard(id, nil); err != nil {
|
|
t.Fatalf("error deleting dashboard: %v", err)
|
|
}
|
|
t.Logf("deleted Dashboard %s", id)
|
|
}
|
|
}
|