-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #108 from trickest/feat/private-tools
Add private tools support
- Loading branch information
Showing
15 changed files
with
505 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,7 +89,7 @@ trickest list --project <project_name> --space <space_name> | |
|-----------|---------|---------|----------------------------------------------------| | ||
| --project | string | / | The name of the project to be listed. | | ||
| --space | string | / | The name of the space to which the project belongs | | ||
| --json | boolean | / | Display output in JSON format | | ||
| --json | boolean | false | Display output in JSON format | | ||
| --url | string | / | URL for referencing a space | | ||
|
||
|
||
|
@@ -109,8 +109,8 @@ trickest get --workflow <workflow_name> --space <space_name> [--watch] | |
| --project | string | / | The name of the project to which the workflow belongs | | ||
| --workflow | string | / | The name of the workflow | | ||
| --run | string | / | Get the status of a specific run | | ||
| --watch | boolean | / | Option to track execution status in case workflow is in running state | | ||
| --json | boolean | / | Display output in JSON format | | ||
| --watch | boolean | false | Option to track execution status in case workflow is in running state | | ||
| --json | boolean | false | Display output in JSON format | | ||
| --url | string | / | URL for referencing a space | | ||
|
||
##### If the supplied workflow has a running execution, you can jump in and watch it running with the `--watch` flag! | ||
|
@@ -126,12 +126,12 @@ trickest execute --workflow <workflow_or_tool_name> --space <space_name> --confi | |
|------------------|---------|---------|---------------------------------------------------------------------------------------------------------------------------------------------| | ||
| --config | file | / | YAML file for run configuration | | ||
| --workflow | string | / | Workflow from the Library to be executed | | ||
| --max | boolean | / | Use maximum number of machines for workflow execution | | ||
| --max | boolean | false | Use maximum number of machines for workflow execution | | ||
| --output | string | / | A comma-separated list of nodes whose outputs should be downloaded when the execution is finished | | ||
| --output-all | boolean | / | Download all outputs when the execution is finished | | ||
| --output-all | boolean | false | Download all outputs when the execution is finished | | ||
| --output-dir | string | . | Path to the directory which should be used to store outputs | | ||
| --show-params | boolean | / | Show parameters in the workflow tree | | ||
| --watch | boolean | / | Option to track execution status in case workflow is in running state | | ||
| --show-params | boolean | false | Show parameters in the workflow tree | | ||
| --watch | boolean | false | Option to track execution status in case workflow is in running state | | ||
| --set-name | string | / | Sets the new workflow name and will copy the workflow to space and project supplied | | ||
| --ci | boolean | false | Enable CI mode (in-progress executions will be stopped when the CLI is forcefully stopped - if not set, you will be asked for confirmation) | | ||
| --create-project | boolean | false | If the project doesn't exist, create one using the project flag as its name (or workflow/tool name if project flag is not set) | | ||
|
@@ -227,9 +227,6 @@ Use **library search** to search all Trickest tools & workflows available in the | |
trickest library search subdomain takeover | ||
``` | ||
|
||
[<img src="./banner.png" />](https://trickest.io/auth/register) | ||
|
||
|
||
## Files command | ||
Interact with the Trickest file storage | ||
|
||
|
@@ -244,7 +241,7 @@ trickest files get --file my_file.txt --output-dir out | |
|----------------------|--------|----------|---------------------------------------------------------------------| | ||
| --file | string | / | File or files (comma-separated) | | ||
| --output-dir | string | / | Path to directory which should be used to store files (default ".") | | ||
| --partial-name-match | boolean | / | Get all files with a partial name match | | ||
| --partial-name-match | boolean | false | Get all files with a partial name match | | ||
|
||
#### Create files | ||
Use the **create** command with the **--file** flag to upload one or more files | ||
|
@@ -270,7 +267,52 @@ trickest files delete --file delete_me.txt | |
| --file | string | / | File or files (comma-separated) | | ||
|
||
|
||
## Tools command | ||
Manage [private tools](https://trickest.com/docs/tutorials/private-tools/private-tools-library/) | ||
|
||
⚒️ Learn how to add your first tool integration [here](https://trickest.com/docs/tutorials/private-tools/dockerfile-and-trickest-yaml/). | ||
|
||
#### Create a new private tool integration | ||
``` | ||
trickest tools create --file tool.yaml | ||
``` | ||
|
||
| Flag | Type | Default | Description | | ||
|----------------------|--------|----------|---------------------------------------------------------------------| | ||
| --file | string | / | YAML file for tool definition | | ||
|
||
#### Update a private tool integration | ||
``` | ||
trickest tools update --file tool.yaml | ||
``` | ||
|
||
| Flag | Type | Default | Description | | ||
|----------------------|--------|----------|---------------------------------------------------------------------| | ||
| --file | string | / | YAML file for tool definition | | ||
|
||
#### List private tool integrations | ||
``` | ||
trickest tools list | ||
``` | ||
|
||
| Flag | Type | Default | Description | | ||
|----------------------|---------|-------------|---------------------------------------------------------------------| | ||
| --json | boolean | false | Display output in JSON format | | ||
|
||
#### Delete a private tool integration | ||
``` | ||
trickest tools delete --name "my-tool" | ||
``` | ||
|
||
| Flag | Type | Default | Description | | ||
|----------------------|--------|----------|---------------------------------------------------------------------| | ||
| --id | string | / | ID of the tool to delete | | ||
| --name | string | / | Name of the tool to delete | | ||
|
||
## Report Bugs / Feedback | ||
We look forward to any feedback you want to share with us or if you're stuck with a problem you can contact us at [[email protected]](mailto:[email protected]). | ||
|
||
You can also create an [Issue](https://github.com/trickest/trickest-cli/issues/new/choose) in the Github repository. | ||
|
||
[<img src="./banner.png" />](https://trickest.io/auth/register) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
package tools | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
"strings" | ||
|
||
"github.com/go-yaml/yaml" | ||
"github.com/google/uuid" | ||
"github.com/spf13/cobra" | ||
"github.com/trickest/trickest-cli/client/request" | ||
"github.com/trickest/trickest-cli/types" | ||
"github.com/trickest/trickest-cli/util" | ||
) | ||
|
||
var toolOutputTypes = map[string]string{ | ||
"file": "2", | ||
"folder": "3", | ||
} | ||
|
||
var ToolsCmd = &cobra.Command{ | ||
Use: "tools", | ||
Short: "Manage private tools", | ||
Long: ``, | ||
Run: func(cmd *cobra.Command, args []string) { | ||
cmd.Help() | ||
}, | ||
} | ||
|
||
func init() { | ||
ToolsCmd.SetHelpFunc(func(command *cobra.Command, strings []string) { | ||
_ = ToolsCmd.Flags().MarkHidden("workflow") | ||
_ = ToolsCmd.Flags().MarkHidden("project") | ||
_ = ToolsCmd.Flags().MarkHidden("space") | ||
_ = ToolsCmd.Flags().MarkHidden("url") | ||
|
||
command.Root().HelpFunc()(command, strings) | ||
}) | ||
} | ||
|
||
func ListPrivateTools(name string) ([]types.Tool, error) { | ||
endpoint := "library/tool/?public=False" | ||
endpoint += fmt.Sprintf("&vault=%s", util.GetVault()) | ||
if name != "" { | ||
endpoint += "&search=" + name | ||
} else { | ||
endpoint += "&page_size=100" | ||
} | ||
|
||
resp := request.Trickest.Get().Do(endpoint) | ||
if resp == nil || resp.Status() != http.StatusOK { | ||
request.ProcessUnexpectedResponse(resp) | ||
} | ||
|
||
var tools types.Tools | ||
err := json.Unmarshal(resp.Body(), &tools) | ||
if err != nil { | ||
return nil, fmt.Errorf("couldn't parse API response: %s", err) | ||
} | ||
|
||
return tools.Results, nil | ||
} | ||
|
||
func getToolIDByName(name string) (uuid.UUID, error) { | ||
tools, err := ListPrivateTools(name) | ||
if err != nil { | ||
return uuid.Nil, fmt.Errorf("couldn't search for %s: %w", name, err) | ||
} | ||
|
||
if len(tools) == 0 { | ||
return uuid.Nil, fmt.Errorf("couldn't find tool '%s'", name) | ||
} | ||
|
||
if len(tools) > 1 { | ||
return uuid.Nil, fmt.Errorf("found more than one match for '%s'", name) | ||
} | ||
|
||
return tools[0].ID, nil | ||
} | ||
|
||
func createToolImportRequestFromYAML(fileName string) (types.ToolImportRequest, error) { | ||
data, err := os.ReadFile(fileName) | ||
if err != nil { | ||
err = fmt.Errorf("couldn't read %s: %w", fileName, err) | ||
return types.ToolImportRequest{}, err | ||
} | ||
|
||
var toolImportRequest types.ToolImportRequest | ||
err = yaml.Unmarshal(data, &toolImportRequest) | ||
if err != nil { | ||
err = fmt.Errorf("couldn't parse %s: %w", fileName, err) | ||
return types.ToolImportRequest{}, err | ||
} | ||
|
||
categoryID, err := util.GetCategoryIDByName(toolImportRequest.Category) | ||
if err != nil { | ||
err = fmt.Errorf("couldn't use the category '%s': %w", toolImportRequest.Category, err) | ||
return types.ToolImportRequest{}, err | ||
} | ||
|
||
toolImportRequest.CategoryID = categoryID | ||
toolImportRequest.VaultInfo = util.GetVault() | ||
toolImportRequest.OutputType = toolOutputTypes[toolImportRequest.OutputType] | ||
for name := range toolImportRequest.Inputs { | ||
if input, ok := toolImportRequest.Inputs[name]; ok { | ||
input.Type = strings.ToUpper(toolImportRequest.Inputs[name].Type) | ||
toolImportRequest.Inputs[name] = input | ||
} | ||
} | ||
|
||
return toolImportRequest, nil | ||
} | ||
|
||
func importTool(fileName string, isUpdate bool) (string, uuid.UUID, error) { | ||
toolImportRequest, err := createToolImportRequestFromYAML(fileName) | ||
if err != nil { | ||
return "", uuid.Nil, err | ||
} | ||
|
||
toolJSON, err := json.Marshal(toolImportRequest) | ||
if err != nil { | ||
return "", uuid.Nil, fmt.Errorf("couldn't encode %s: %w", fileName, err) | ||
} | ||
|
||
var resp *request.Response | ||
if isUpdate { | ||
toolName := toolImportRequest.Name | ||
toolID, err := getToolIDByName(toolName) | ||
if err != nil { | ||
return "", uuid.Nil, fmt.Errorf("couldn't import '%s': %w", toolName, err) | ||
} | ||
resp = request.Trickest.Patch().Body(toolJSON).DoF("library/tool/%s/", toolID.String()) | ||
} else { | ||
resp = request.Trickest.Post().Body(toolJSON).Do("library/tool/") | ||
} | ||
|
||
if resp == nil { | ||
return "", uuid.Nil, fmt.Errorf("couldn't import %s", fileName) | ||
} | ||
|
||
if resp.Status() != http.StatusCreated && resp.Status() != http.StatusOK { | ||
request.ProcessUnexpectedResponse(resp) | ||
} | ||
|
||
var importedTool types.Tool | ||
err = json.Unmarshal(resp.Body(), &importedTool) | ||
if err != nil { | ||
return "", uuid.Nil, fmt.Errorf("couldn't import %s: %w", fileName, err) | ||
} | ||
|
||
return importedTool.Name, importedTool.ID, nil | ||
} |
Oops, something went wrong.