Skip to content

Adding resources to the CLI SDK

Ronan Watkins edited this page Jun 4, 2021 · 5 revisions

Adding a resource to preprocess-swagger.js

The usage commands are the best reference for this.

  • Create a folder under extensions/cmd with the name of the command. In the following example, it would be named mycustomcommand
  • Create 2 .go files in the folder; one with an appropriate name and the other postfixed with _test. In the following example, they would be named mycustomcommandquery.go and mycustomcommandquery_test.go

The main file will contain your command logic. The package name of both files must match the command name, for example, gc usage has the package name usage. If the command hasn't been defined in resourceDefinitions it must first be defined manually, it would look like so:

package mycustomcommand

import (
	"github.com/spf13/cobra"
)

var mycustomcommandrootCmd = &cobra.Command{
	Use:   "mycustomcommandroot",
	Short: "Manages Genesys Cloud mycustomcommandroot",
	Long:  `Manages Genesys Cloud mycustomcommandroot`,
}

func Cmdmycustomcommandroot() *cobra.Command {
	return mycustomcommandrootCmd
}

It's important that the func has the name Cmd[commandName] because this is used to add it to the gc root command.

We'll define a command named mycustomcommandCmd to carry out the query. This needs to be added to the mycustomcommandrootCmd command in the init function, and any flags are also defined here. For example:

func init() {
	mycustomcommandCmd.Flags().StringP("file", "f", "", "File name containing the JSON for creating a query")
	mycustomcommandCmd.Flags().IntP("timeout", "t", 0, "Maximum time to wait for the results (X minutes) to complete.  The code will wait 5 seconds between each call")
	
	mycustomcommandrootCmd.AddCommand(mycustomcommandCmd)
}

Define the operations used by the command as global variables. This is done to enable testing against the swagger definition.

var (
	mycustomcommandQueryOperation = models.HandWrittenOperation{
		Path:   "/api/v2/usage/query",
		Method: http.MethodPost,
	}
	mycustomcommandQueryResultsOperation = models.HandWrittenOperation{
		Path:   "/api/v2/usage/query/{executionId}/results",
		Method: http.MethodGet,
	}
)

Create the command and implement the Run function. The Run function will contain all the command logic

var mycustomcommandQueryCmd = &cobra.Command{
	Use:   "query",
	Short: "Creates a query for Genesys Cloud API Usage",
	Long:  `Creates a query for Genesys Cloud API Usage`,
	Args:  cobra.NoArgs,

        Run: func(cmd *cobra.Command, args []string) {
            ...
        }
}

Or, if the command takes arguments

var mycustomcommandQueryCmd = &cobra.Command{
	Use:   "query [queryId]",
	Short: "Creates a query for Genesys Cloud API Usage",
	Long:  `Creates a query for Genesys Cloud API Usage`,
	Args:  cobra.ExactArgs(1),

        Run: func(cmd *cobra.Command, args []string) {
            ...
        }
}

The implementation of the Run function is dependent on what the objectives of the command are. Some points to note are as follows.

Flags can be parsed as follows

timeout, _ := cmd.Flags().GetInt("timeout")

Or, for strings

timeoutStr, _ := cmd.Flags().GetString("timeout")

Arguments can be retrieved and added to the path like so

queryId, args := args[0], args[1:]
path := strings.Replace(mycustomcommandQueryOperation.Path, "{queryId}", fmt.Sprintf("%v", queryId), -1)

Input data passed as a file or piped to the command can be retrieved by

inputData := utils.ResolveInputData(cmd)

The API is called with retry logic using the following syntax. Set RetryMax to 0 for no retries in the case of connections errors, or rate limits.

retryFunc := retry.RetryWithData(path, inputData, CommandService.Post)
retryConfig := &retry.RetryConfiguration{
	RetryWaitMin: 5 * time.Second,
	RetryWaitMax: 60 * time.Second,
	RetryMax:     20,
}
results, err := retryFunc(retryConfig)

Log errors to the log file, and stderr and exit the program with an exit code of 1 with

if err != nil {
	logger.Fatal(err)
}

Write the results to stdout with

utils.Render(results)

Testing for custom API commands

Unit tests for testing the operation method and path against the current swagger schema are essential in maintaining the quality and consistency of the CLI.

In the test file, firstly import the dependencies

import (
	"github.com/mypurecloud/platform-client-sdk-cli/build/gc/utils"
	"testing"
)

For each HandWrittenOperation, write a unit test with the following pattern to have it tested against the swagger schema

func TestMycustomcommandQueryOperation(t *testing.T) {
	utils.TestAgainstSwaggerDefinition(t, mycustomcommandQueryOperation)
}