mirror of
https://github.com/LukeHagar/sailpoint-cli.git
synced 2025-12-09 20:57:44 +00:00
Merge pull request #101 from sailpoint-oss/hemanth-vakkapatla-sp/PLTFORMS-1982
PLTFORMS-1982: Adding New commands to CLI
This commit is contained in:
@@ -881,3 +881,107 @@ type invokeCommand struct {
|
|||||||
Config json.RawMessage `json:"config"`
|
Config json.RawMessage `json:"config"`
|
||||||
Input json.RawMessage `json:"input"`
|
Input json.RawMessage `json:"input"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sourceDataDiscoverInput struct {
|
||||||
|
Query map[string]any `json:"queryInput"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type sourceDataReadInput struct {
|
||||||
|
SourceDataKey string `json:"sourceDataKey"`
|
||||||
|
Query map[string]any `json:"queryInput"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type sourceData struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
Label string `json:"label"`
|
||||||
|
SubLabel string `json:"sublabel"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ConnClient) SourceDataDiscover(ctx context.Context, queryInput map[string]any) (sData []sourceData, raw []byte, err error) {
|
||||||
|
input, err := json.Marshal(sourceDataDiscoverInput{
|
||||||
|
Query: queryInput,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdRaw, err := cc.rawInvoke("std:source-data:discover", input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := cc.client.Post(ctx, connResourceUrl(cc.endpoint), "application/json", bytes.NewReader(cmdRaw))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return nil, nil, newResponseError(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err = io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawResp, err := parseResponse(raw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]sourceData, 0)
|
||||||
|
err = json.Unmarshal(rawResp.Data, &data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, rawResp.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *ConnClient) SourceDataRead(ctx context.Context, sourceDataKey string, queryInput map[string]any) (sData []sourceData, raw []byte, err error) {
|
||||||
|
input, err := json.Marshal(sourceDataReadInput{
|
||||||
|
SourceDataKey: sourceDataKey,
|
||||||
|
Query: queryInput,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdRaw, err := cc.rawInvoke("std:source-data:read", input)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := cc.client.Post(ctx, connResourceUrl(cc.endpoint, cc.connectorRef, "invoke-direct"), "application/json", bytes.NewReader(cmdRaw))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = resp.Body.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return nil, nil, newResponseError(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err = io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawResp, err := parseResponse(raw)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := make([]sourceData, 0)
|
||||||
|
err = json.Unmarshal(rawResp.Data, &data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, rawResp.Data, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,9 +16,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
connectorsEndpoint = "/beta/platform-connectors"
|
connectorsEndpoint = "/beta/platform-connectors"
|
||||||
connectorInstancesEndpoint = "/beta/connector-instances"
|
connectorInstancesEndpoint = "/beta/connector-instances"
|
||||||
connectorCustomizersEndpoint = "/beta/connector-customizers"
|
connectorCustomizersEndpoint = "/beta/connector-customizers"
|
||||||
|
connectorRuntimeDirectExecuteEndpoint = "/sp-conn-runtime-exec/runtime-connector-invoke"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewConnCmd(term terminal.Terminal) *cobra.Command {
|
func NewConnCmd(term terminal.Terminal) *cobra.Command {
|
||||||
|
|||||||
@@ -14,14 +14,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
stdAccountCreate = "std:account:create"
|
stdAccountCreate = "std:account:create"
|
||||||
stdAccountList = "std:account:list"
|
stdAccountList = "std:account:list"
|
||||||
stdAccountRead = "std:account:read"
|
stdAccountRead = "std:account:read"
|
||||||
stdAccountUpdate = "std:account:update"
|
stdAccountUpdate = "std:account:update"
|
||||||
stdAccountDelete = "std:account:delete"
|
stdAccountDelete = "std:account:delete"
|
||||||
stdEntitlementList = "std:entitlement:list"
|
stdEntitlementList = "std:entitlement:list"
|
||||||
stdEntitlementRead = "std:entitlement:read"
|
stdEntitlementRead = "std:entitlement:read"
|
||||||
stdTestConnection = "std:test-connection"
|
stdTestConnection = "std:test-connection"
|
||||||
|
stdSourceDataDiscover = "std:source-data:discover"
|
||||||
|
stdSourceDataRead = "std:source-data:read"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newConnInvokeCmd(client client.Client, term terminal.Terminal) *cobra.Command {
|
func newConnInvokeCmd(client client.Client, term terminal.Terminal) *cobra.Command {
|
||||||
@@ -53,6 +55,8 @@ func newConnInvokeCmd(client client.Client, term terminal.Terminal) *cobra.Comma
|
|||||||
newConnInvokeEntitlementListCmd(client),
|
newConnInvokeEntitlementListCmd(client),
|
||||||
newConnInvokeEntitlementReadCmd(client),
|
newConnInvokeEntitlementReadCmd(client),
|
||||||
newConnInvokeRaw(client),
|
newConnInvokeRaw(client),
|
||||||
|
newConnInvokeSourceDataDiscoverCmd(client),
|
||||||
|
newConnInvokeSourceDataReadCmd(client),
|
||||||
)
|
)
|
||||||
|
|
||||||
bindDevConfig(cmd.PersistentFlags())
|
bindDevConfig(cmd.PersistentFlags())
|
||||||
@@ -98,6 +102,28 @@ func connClient(cmd *cobra.Command, spClient client.Client) (*connclient.ConnCli
|
|||||||
return cc, nil
|
return cc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func connRuntimeClient(cmd *cobra.Command, spClient client.Client) (*connclient.ConnClient, error) {
|
||||||
|
connectorRef := cmd.Flags().Lookup("id").Value.String()
|
||||||
|
version := cmd.Flags().Lookup("version").Value.String()
|
||||||
|
|
||||||
|
var v *int
|
||||||
|
if version != "" {
|
||||||
|
ver, err := strconv.Atoi(version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
v = &ver
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := invokeConfig(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cc := connclient.NewConnClient(spClient, v, cfg, connectorRef, connectorRuntimeDirectExecuteEndpoint)
|
||||||
|
|
||||||
|
return cc, nil
|
||||||
|
}
|
||||||
|
|
||||||
func connClientWithCustomParams(spClient client.Client, cfg json.RawMessage, connectorID, version, endpoint string) (*connclient.ConnClient, error) {
|
func connClientWithCustomParams(spClient client.Client, cfg json.RawMessage, connectorID, version, endpoint string) (*connclient.ConnClient, error) {
|
||||||
v, err := strconv.Atoi(version)
|
v, err := strconv.Atoi(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
45
cmd/connector/conn_invoke_source_data_discover.go
Normal file
45
cmd/connector/conn_invoke_source_data_discover.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2023, SailPoint Technologies, Inc. All rights reserved.
|
||||||
|
|
||||||
|
package connector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/sailpoint-oss/sailpoint-cli/internal/client"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newConnInvokeSourceDataDiscoverCmd(client client.Client) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "source-data-discover [--query <value>]",
|
||||||
|
Short: "Invoke a std:source-data:discover command",
|
||||||
|
Example: `sail connectors invoke source-data-discover --query '{"query": "", "limit": 10}'`,
|
||||||
|
Args: cobra.RangeArgs(0, 1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
cc, err := connRuntimeClient(cmd, client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
queryRaw := cmd.Flags().Lookup("query").Value.String()
|
||||||
|
var queryInput map[string]any
|
||||||
|
if err := json.Unmarshal([]byte(queryRaw), &queryInput); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, rawResponse, err := cc.SourceDataDiscover(ctx, queryInput)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintln(cmd.OutOrStdout(), string(rawResponse))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringP("query", "q", "{}", "Optional - Query to filter")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
35
cmd/connector/conn_invoke_source_data_discover_test.go
Normal file
35
cmd/connector/conn_invoke_source_data_discover_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2023, SailPoint Technologies, Inc. All rights reserved.
|
||||||
|
package connector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/sailpoint-oss/sailpoint-cli/internal/mocks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSourceDataDiscoverWithoutInput(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
i := `{"connectorRef":"test-connector","tag":"latest","type":"std:source-data:discover","config":{},"input":{"queryInput":{}}}`
|
||||||
|
|
||||||
|
client := mocks.NewMockClient(ctrl)
|
||||||
|
client.EXPECT().
|
||||||
|
Post(gomock.Any(), gomock.Any(), "application/json", bytes.NewReader([]byte(i))).
|
||||||
|
Return(&http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("{}")))}, nil)
|
||||||
|
|
||||||
|
cmd := newConnInvokeSourceDataDiscoverCmd(client)
|
||||||
|
addRequiredFlagsFromParentCmd(cmd)
|
||||||
|
|
||||||
|
b := new(bytes.Buffer)
|
||||||
|
cmd.SetOut(b)
|
||||||
|
cmd.SetArgs([]string{"-c", "test-connector", "--config-json", "{}"})
|
||||||
|
|
||||||
|
err := cmd.Execute()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("failed to detect error: reading source data discover")
|
||||||
|
}
|
||||||
|
}
|
||||||
45
cmd/connector/conn_invoke_source_data_read.go
Normal file
45
cmd/connector/conn_invoke_source_data_read.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2023, SailPoint Technologies, Inc. All rights reserved.
|
||||||
|
|
||||||
|
package connector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/sailpoint-oss/sailpoint-cli/internal/client"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newConnInvokeSourceDataReadCmd(client client.Client) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "source-data-read [sourceDataKey] [--query <value>]",
|
||||||
|
Short: "Invoke a std:source-data:read command",
|
||||||
|
Example: `sail connectors invoke source-data-read john.doe --query '{"query": "jane doe", "excludeItems": ["jane","doe"], "limit": 10}'`,
|
||||||
|
Args: cobra.RangeArgs(1, 1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
cc, err := connRuntimeClient(cmd, client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
queryRaw := cmd.Flags().Lookup("query").Value.String()
|
||||||
|
var queryInput map[string]any
|
||||||
|
if err := json.Unmarshal([]byte(queryRaw), &queryInput); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, rawResponse, err := cc.SourceDataRead(ctx, args[0], queryInput)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = fmt.Fprintln(cmd.OutOrStdout(), string(rawResponse))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringP("query", "q", "{}", "Optional - Query to filter")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
35
cmd/connector/conn_invoke_source_data_read_test.go
Normal file
35
cmd/connector/conn_invoke_source_data_read_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2023, SailPoint Technologies, Inc. All rights reserved.
|
||||||
|
package connector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/sailpoint-oss/sailpoint-cli/internal/mocks"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSourceDataReadWithInput(t *testing.T) {
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
i := `{"connectorRef":"test-connector","tag":"latest","type":"std:source-data:read","config":{},"input":{"sourceDataKey":"john.doe","queryInput":{}}}`
|
||||||
|
|
||||||
|
client := mocks.NewMockClient(ctrl)
|
||||||
|
client.EXPECT().
|
||||||
|
Post(gomock.Any(), gomock.Any(), "application/json", bytes.NewReader([]byte(i))).
|
||||||
|
Return(&http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader([]byte("{}")))}, nil)
|
||||||
|
|
||||||
|
cmd := newConnInvokeSourceDataReadCmd(client)
|
||||||
|
addRequiredFlagsFromParentCmd(cmd)
|
||||||
|
|
||||||
|
b := new(bytes.Buffer)
|
||||||
|
cmd.SetOut(b)
|
||||||
|
cmd.SetArgs([]string{"john.doe", "-c", "test-connector", "--config-json", "{}"})
|
||||||
|
|
||||||
|
err := cmd.Execute()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("failed to detect error: reading source data discover")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ import (
|
|||||||
// Unit tests for conn_invoke.go and its subcommands
|
// Unit tests for conn_invoke.go and its subcommands
|
||||||
|
|
||||||
// Expected number of subcommands to `sp` root command
|
// Expected number of subcommands to `sp` root command
|
||||||
const numConnInvokeSubcommands = 11
|
const numConnInvokeSubcommands = 13
|
||||||
|
|
||||||
func TestNewConnInvokeCmd_noArgs(t *testing.T) {
|
func TestNewConnInvokeCmd_noArgs(t *testing.T) {
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
|
|||||||
Reference in New Issue
Block a user