From 2ce2273f57e6b0e32d2d1b9908ef4b7ddc5cd39d Mon Sep 17 00:00:00 2001 From: traut Date: Tue, 1 Oct 2024 18:27:30 +0200 Subject: [PATCH] Extending Microsoft Graph data source --- .../microsoft/data-sources/microsoft_graph.md | 19 +++ docs/plugins/plugins.json | 3 + internal/microsoft/client/graph_client.go | 148 ++++++++++++++++-- internal/microsoft/data_microsoft_graph.go | 70 ++++++--- .../microsoft/data_microsoft_graph_test.go | 104 +++++++++--- internal/microsoft/plugin.go | 26 ++- .../microsoft/microsoft_graph_client.go | 97 ++++++++++-- plugin/runner/loader.go | 3 +- 8 files changed, 392 insertions(+), 78 deletions(-) diff --git a/docs/plugins/microsoft/data-sources/microsoft_graph.md b/docs/plugins/microsoft/data-sources/microsoft_graph.md index efd72c0d..2d259f73 100644 --- a/docs/plugins/microsoft/data-sources/microsoft_graph.md +++ b/docs/plugins/microsoft/data-sources/microsoft_graph.md @@ -101,5 +101,24 @@ data microsoft_graph { # Optional map of string. # Default value: query_params = null + + # Number of objects to be returned + # + # Optional number. + # Must be >= 1 + # Default value: + objects_size = 50 + + # Return only the list of objects. If `false`, returns an object with `objects` and `totalCount` fields + # + # Optional bool. + # Default value: + only_objects = true + + # If API endpoint response should be treated as a list or as an object. If set to `true`, `only_objects`, `query_params` and `objects_size` are ignored. + # + # Optional bool. + # Default value: + is_object_endpoint = false } ``` \ No newline at end of file diff --git a/docs/plugins/plugins.json b/docs/plugins/plugins.json index c55d36e6..66e920f3 100644 --- a/docs/plugins/plugins.json +++ b/docs/plugins/plugins.json @@ -347,6 +347,9 @@ "arguments": [ "api_version", "endpoint", + "is_object_endpoint", + "objects_size", + "only_objects", "query_params" ] }, diff --git a/internal/microsoft/client/graph_client.go b/internal/microsoft/client/graph_client.go index 3bf3a0f9..183b6a68 100644 --- a/internal/microsoft/client/graph_client.go +++ b/internal/microsoft/client/graph_client.go @@ -2,13 +2,20 @@ package client import ( "context" - "encoding/json" "fmt" + "io" + "log/slog" "net/http" "net/url" + "strconv" + + "github.com/blackstork-io/fabric/plugin/plugindata" ) -const graphUrl = "https://graph.microsoft.com" +const ( + graphUrl = "https://graph.microsoft.com" + defaultPageSize = 20 +) type graphClient struct { accessToken string @@ -28,30 +35,143 @@ func (cli *graphClient) prepare(r *http.Request) { r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", cli.accessToken)) } -func (cli *graphClient) QueryGraph(ctx context.Context, endpoint string, queryParams url.Values) (result interface{}, err error) { - requestUrl, err := url.Parse(graphUrl + fmt.Sprintf("/%s%s", cli.apiVersion, endpoint)) - if err != nil { - return - } - if queryParams != nil { - requestUrl.RawQuery = queryParams.Encode() - } +func (cli *graphClient) fetchURL(ctx context.Context, requestUrl *url.URL) (result plugindata.Data, err error) { r, err := http.NewRequestWithContext(ctx, http.MethodGet, requestUrl.String(), nil) if err != nil { return } cli.prepare(r) + slog.DebugContext(ctx, "Fetching an URL from API", "url", requestUrl.String()) res, err := cli.client.Do(r) if err != nil { return } + raw, err := io.ReadAll(res.Body) + if err != nil { + return nil, fmt.Errorf("failed to read the results: %s", err) + } + defer res.Body.Close() if res.StatusCode != http.StatusOK { - err = fmt.Errorf("microsoft graph client returned status code: %d", res.StatusCode) + slog.ErrorContext(ctx, "Error received from Microsoft Graph API", "status_code", res.StatusCode, "body", string(raw)) + err = fmt.Errorf("Microsoft Graph client returned status code: %d", res.StatusCode) return } - defer res.Body.Close() - if err := json.NewDecoder(res.Body).Decode(&result); err != nil { - return nil, err + result, err = plugindata.UnmarshalJSON(raw) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal results: %s", err) } return } + +func (cli *graphClient) QueryGraph( + ctx context.Context, + endpoint string, + queryParams url.Values, + size int, + onlyobjects bool, +) (result plugindata.Data, err error) { + objects := make(plugindata.List, 0) + + urlStr := graphUrl + fmt.Sprintf("/%s%s", cli.apiVersion, endpoint) + requestUrl, err := url.Parse(urlStr) + if err != nil { + return + } + + if queryParams == nil { + queryParams = url.Values{} + } + + queryParams.Set("$count", strconv.FormatBool(true)) + queryParams.Set("$skip", strconv.Itoa(0)) + + limit := min(size, defaultPageSize) + queryParams.Set("$top", strconv.Itoa(limit)) + + var totalCount int = -1 + var response plugindata.Data + + for { + + requestUrl.RawQuery = queryParams.Encode() + + response, err = cli.fetchURL(ctx, requestUrl) + if err != nil { + slog.ErrorContext(ctx, "Error while fetching objects", "url", requestUrl.String(), "error", err) + return nil, err + } + + resultMap, ok := response.(plugindata.Map) + if !ok { + return nil, fmt.Errorf("unexpected result type: %T", response) + } + + countRaw, ok := resultMap["@odata.count"] + if ok { + totalCount = int(countRaw.(plugindata.Number)) + } + + objectsPageRaw, ok := resultMap["value"] + if !ok { + break + } + + objectsPage, ok := objectsPageRaw.(plugindata.List) + if !ok { + return nil, fmt.Errorf("unexpected value type: %T", objectsPageRaw) + } + + if len(objectsPage) == 0 { + break + } + + slog.InfoContext( + ctx, "Objects fetched from Microsoft Graph API", + "fetched_overall", len(objects), + "fetched", len(objectsPage), + "total_available", totalCount, + "to_fetch_overall", size, + ) + + objects = append(objects, objectsPage...) + if len(objects) >= size { + break + } + queryParams.Set("$skip", strconv.Itoa(len(objects))) + + // Number of objects to get, >= 0 + objectsToGet := max(size-len(objects), 0) + pageSize := min(defaultPageSize, objectsToGet) + queryParams.Set("$top", strconv.Itoa(pageSize)) + } + + objectsToReturn := objects[:min(len(objects), size)] + + if onlyobjects { + return objectsToReturn, nil + } else { + data := plugindata.Map{ + "objects": objectsToReturn, + "total_count": plugindata.Number(totalCount), + } + return data, nil + } +} + +func (cli *graphClient) QueryGraphObject( + ctx context.Context, + endpoint string, +) (result plugindata.Data, err error) { + urlStr := graphUrl + fmt.Sprintf("/%s%s", cli.apiVersion, endpoint) + requestUrl, err := url.Parse(urlStr) + if err != nil { + return + } + response, err := cli.fetchURL(ctx, requestUrl) + if err != nil { + slog.ErrorContext(ctx, "Error while fetching an object", "url", requestUrl.String(), "error", err) + return nil, err + } + + return response, nil +} diff --git a/internal/microsoft/data_microsoft_graph.go b/internal/microsoft/data_microsoft_graph.go index 28435614..ab35a239 100644 --- a/internal/microsoft/data_microsoft_graph.go +++ b/internal/microsoft/data_microsoft_graph.go @@ -14,6 +14,8 @@ import ( "github.com/blackstork-io/fabric/plugin/plugindata" ) +const defaultSize = 50 + func makeMicrosoftGraphDataSource(loader MicrosoftGraphClientLoadFn) *plugin.DataSource { return &plugin.DataSource{ Doc: "The `microsoft_graph` data source queries Microsoft Graph.", @@ -58,23 +60,43 @@ func makeMicrosoftGraphDataSource(loader MicrosoftGraphClientLoadFn) *plugin.Dat Args: &dataspec.RootSpec{ Attrs: []*dataspec.AttrSpec{ { - Doc: "The API version", Name: "api_version", + Doc: "The API version", Type: cty.String, DefaultVal: cty.StringVal("beta"), }, { - Doc: "The endpoint to query", Name: "endpoint", + Doc: "The endpoint to query", Type: cty.String, Constraints: constraint.RequiredNonNull, ExampleVal: cty.StringVal("/security/incidents"), }, { - Doc: "The query parameters", Name: "query_params", + Doc: "The query parameters", Type: cty.Map(cty.String), }, + { + Name: "objects_size", + Doc: "Number of objects to be returned", + Type: cty.Number, + Constraints: constraint.NonNull, + DefaultVal: cty.NumberIntVal(defaultSize), + MinInclusive: cty.NumberIntVal(1), + }, + { + Name: "only_objects", + Doc: "Return only the list of objects. If `false`, returns an object with `objects` and `totalCount` fields", + Type: cty.Bool, + DefaultVal: cty.BoolVal(true), + }, + { + Name: "is_object_endpoint", + Doc: "If API endpoint response should be treated as a list or as an object. If set to `true`, `only_objects`, `query_params` and `objects_size` are ignored.", + Type: cty.Bool, + DefaultVal: cty.BoolVal(false), + }, }, }, } @@ -92,33 +114,39 @@ func fetchMicrosoftGraph(loader MicrosoftGraphClientLoadFn) plugin.RetrieveDataF }} } endPoint := params.Args.GetAttrVal("endpoint").AsString() - queryParamsAttr := params.Args.GetAttrVal("query_params") - var queryParams url.Values + isObjectEndpoint := params.Args.GetAttrVal("is_object_endpoint") - if !queryParamsAttr.IsNull() { - queryParams = url.Values{} - queryMap := queryParamsAttr.AsValueMap() - for k, v := range queryMap { - queryParams.Add(k, v.AsString()) + var response plugindata.Data + + if isObjectEndpoint.True() { + response, err = cli.QueryGraphObject(ctx, endPoint) + } else { + + queryParamsAttr := params.Args.GetAttrVal("query_params") + var queryParams url.Values + + if !queryParamsAttr.IsNull() { + queryParams = url.Values{} + queryMap := queryParamsAttr.AsValueMap() + for k, v := range queryMap { + queryParams.Add(k, v.AsString()) + } } - } - response, err := cli.QueryGraph(ctx, endPoint, queryParams) - if err != nil { - return nil, diagnostics.Diag{{ - Severity: hcl.DiagError, - Summary: "Failed to query microsoft graph", - Detail: err.Error(), - }} + onlyObjects := params.Args.GetAttrVal("only_objects") + + size64, _ := params.Args.GetAttrVal("objects_size").AsBigFloat().Int64() + size := int(size64) + + response, err = cli.QueryGraph(ctx, endPoint, queryParams, size, onlyObjects.True()) } - data, err := plugindata.ParseAny(response) if err != nil { return nil, diagnostics.Diag{{ Severity: hcl.DiagError, - Summary: "Failed to parse response", + Summary: "Failed to query microsoft graph", Detail: err.Error(), }} } - return data, nil + return response, nil } } diff --git a/internal/microsoft/data_microsoft_graph_test.go b/internal/microsoft/data_microsoft_graph_test.go index 3d5c61c6..ea57b08a 100644 --- a/internal/microsoft/data_microsoft_graph_test.go +++ b/internal/microsoft/data_microsoft_graph_test.go @@ -31,9 +31,14 @@ func TestMicrosoftGraphDataSourceTestSuite(t *testing.T) { } func (s *MicrosoftGraphDataSourceTestSuite) SetupSuite() { - s.plugin = microsoft.Plugin("1.0.0", nil, nil, (func(ctx context.Context, apiVersion string, cfg *dataspec.Block) (client microsoft.MicrosoftGraphClient, err error) { - return s.cli, nil - })) + s.plugin = microsoft.Plugin( + "1.0.0", + nil, + nil, + (func(ctx context.Context, apiVersion string, cfg *dataspec.Block) (client microsoft.MicrosoftGraphClient, err error) { + return s.cli, nil + }), + ) s.schema = s.plugin.DataSources["microsoft_graph"] } @@ -54,13 +59,14 @@ func (s *MicrosoftGraphDataSourceTestSuite) TestSchema() { } func (s *MicrosoftGraphDataSourceTestSuite) TestBasic() { - expectedData := map[string]interface{}{ - "value": []interface{}{map[string]interface{}{ - "severity": "High", - "displayName": "Incident 1", - }}, + expectedData := plugindata.List{ + plugindata.Map{ + "severity": plugindata.String("High"), + "displayName": plugindata.String("Incident 1"), + }, } - s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values{"$top": []string{"10"}}).Return(expectedData, nil) + s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values{"$top": []string{"10"}}, 1, true). + Return(expectedData, nil) ctx := context.Background() result, diags := s.schema.DataFunc(ctx, &plugin.RetrieveDataParams{ Config: plugintest.NewTestDecoder(s.T(), s.schema.Config). @@ -71,17 +77,70 @@ func (s *MicrosoftGraphDataSourceTestSuite) TestBasic() { Args: plugintest.NewTestDecoder(s.T(), s.schema.Args). SetAttr("endpoint", cty.StringVal("/security/incidents")). SetAttr("api_version", cty.StringVal("v1")). + SetAttr("objects_size", cty.NumberIntVal(1)). SetAttr("query_params", cty.MapVal(map[string]cty.Value{"$top": cty.StringVal("10")})). Decode(), }) s.Nil(diags) - parsedData, err := plugindata.ParseAny(expectedData) - s.Nil(err) - s.Equal(parsedData, result.AsPluginData()) + s.Equal(expectedData, result.AsPluginData()) +} + +func (s *MicrosoftGraphDataSourceTestSuite) TestBasicObject() { + expectedData := plugindata.Map{ + "value": plugindata.Map{ + "severity": plugindata.String("High"), + "displayName": plugindata.String("Incident 1"), + }, + } + s.cli.On("QueryGraphObject", mock.Anything, "/security/incidents/123").Return(expectedData, nil) + ctx := context.Background() + result, diags := s.schema.DataFunc(ctx, &plugin.RetrieveDataParams{ + Config: plugintest.NewTestDecoder(s.T(), s.schema.Config). + SetAttr("client_id", cty.StringVal("cid")). + SetAttr("tenant_id", cty.StringVal("tid")). + SetAttr("client_secret", cty.StringVal("csecret")). + Decode(), + Args: plugintest.NewTestDecoder(s.T(), s.schema.Args). + SetAttr("endpoint", cty.StringVal("/security/incidents/123")). + SetAttr("is_object_endpoint", cty.StringVal("true")). + Decode(), + }) + s.Nil(diags) + s.Equal(expectedData, result.AsPluginData()) +} + +func (s *MicrosoftGraphDataSourceTestSuite) TestBasicWithMeta() { + expectedData := plugindata.Map{ + "objects": plugindata.List{ + plugindata.Map{ + "severity": plugindata.String("High"), + "displayName": plugindata.String("Incident 1"), + }, + }, + } + // 50 is the default response size for the data source + s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values(nil), 50, false). + Return(expectedData, nil) + ctx := context.Background() + result, diags := s.schema.DataFunc(ctx, &plugin.RetrieveDataParams{ + Config: plugintest.NewTestDecoder(s.T(), s.schema.Config). + SetAttr("client_id", cty.StringVal("cid")). + SetAttr("tenant_id", cty.StringVal("tid")). + SetAttr("client_secret", cty.StringVal("csecret")). + Decode(), + Args: plugintest.NewTestDecoder(s.T(), s.schema.Args). + SetAttr("endpoint", cty.StringVal("/security/incidents")). + SetAttr("api_version", cty.StringVal("v1")). + SetAttr("only_objects", cty.StringVal("false")). + Decode(), + }) + s.Nil(diags) + s.Equal(expectedData, result.AsPluginData()) } func (s *MicrosoftGraphDataSourceTestSuite) TestClientError() { - s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values{"$top": []string{"10"}}).Return(nil, errors.New("microsoft graph client returned status code: 400")) + s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values{"$top": []string{"10"}}, 1, true). + Return(nil, errors.New("microsoft graph client returned status code: 400")) ctx := context.Background() result, diags := s.schema.DataFunc(ctx, &plugin.RetrieveDataParams{ Config: plugintest.NewTestDecoder(s.T(), s.schema.Config). @@ -92,6 +151,7 @@ func (s *MicrosoftGraphDataSourceTestSuite) TestClientError() { Args: plugintest.NewTestDecoder(s.T(), s.schema.Args). SetAttr("endpoint", cty.StringVal("/security/incidents")). SetAttr("api_version", cty.StringVal("v1")). + SetAttr("objects_size", cty.NumberIntVal(1)). SetAttr("query_params", cty.MapVal(map[string]cty.Value{"$top": cty.StringVal("10")})). Decode(), }) @@ -129,13 +189,14 @@ func (s *MicrosoftGraphDataSourceTestSuite) TestMissingConfig() { } func (s *MicrosoftGraphDataSourceTestSuite) TestMissingCredentials() { - expectedData := map[string]interface{}{ - "value": []interface{}{map[string]interface{}{ - "severity": "High", - "displayName": "Incident 1", - }}, + expectedData := plugindata.List{ + plugindata.Map{ + "severity": plugindata.String("High"), + "displayName": plugindata.String("Incident 1"), + }, } - s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values{"$top": []string{"10"}}).Return(expectedData, nil) + s.cli.On("QueryGraph", mock.Anything, "/security/incidents", url.Values{"$top": []string{"10"}}, 1, true). + Return(expectedData, nil) ctx := context.Background() result, diags := s.schema.DataFunc(ctx, &plugin.RetrieveDataParams{ Config: plugintest.NewTestDecoder(s.T(), s.schema.Config). @@ -146,10 +207,9 @@ func (s *MicrosoftGraphDataSourceTestSuite) TestMissingCredentials() { SetAttr("endpoint", cty.StringVal("/security/incidents")). SetAttr("api_version", cty.StringVal("v1")). SetAttr("query_params", cty.MapVal(map[string]cty.Value{"$top": cty.StringVal("10")})). + SetAttr("objects_size", cty.NumberIntVal(1)). Decode(), }) s.Nil(diags) - parsedData, err := plugindata.ParseAny(expectedData) - s.Nil(err) - s.Equal(parsedData, result.AsPluginData()) + s.Equal(expectedData, result.AsPluginData()) } diff --git a/internal/microsoft/plugin.go b/internal/microsoft/plugin.go index 94435d87..fd52502f 100644 --- a/internal/microsoft/plugin.go +++ b/internal/microsoft/plugin.go @@ -13,6 +13,7 @@ import ( "github.com/blackstork-io/fabric/internal/microsoft/client" "github.com/blackstork-io/fabric/plugin" "github.com/blackstork-io/fabric/plugin/dataspec" + "github.com/blackstork-io/fabric/plugin/plugindata" ) type ClientLoadFn func() client.Client @@ -22,7 +23,11 @@ var DefaultClientLoader ClientLoadFn = client.New type AzureOpenaiClientLoadFn func(azureOpenAIKey string, azureOpenAIEndpoint string) (client AzureOpenaiClient, err error) type AzureOpenaiClient interface { - GetCompletions(ctx context.Context, body azopenai.CompletionsOptions, options *azopenai.GetCompletionsOptions) (azopenai.GetCompletionsResponse, error) + GetCompletions( + ctx context.Context, + body azopenai.CompletionsOptions, + options *azopenai.GetCompletionsOptions, + ) (azopenai.GetCompletionsResponse, error) } var DefaultAzureOpenAIClientLoader AzureOpenaiClientLoadFn = func(azureOpenAIKey string, azureOpenAIEndpoint string) (client AzureOpenaiClient, err error) { @@ -32,7 +37,17 @@ var DefaultAzureOpenAIClientLoader AzureOpenaiClientLoadFn = func(azureOpenAIKey } type MicrosoftGraphClient interface { - QueryGraph(ctx context.Context, endpoint string, queryParams url.Values) (result interface{}, err error) + QueryGraph( + ctx context.Context, + endpoint string, + queryParams url.Values, + size int, + onlyObjects bool, + ) (objects plugindata.Data, err error) + QueryGraphObject( + ctx context.Context, + endpoint string, + ) (result plugindata.Data, err error) } type AcquireTokenFn func(ctx context.Context, tenantId string, clientId string, cred confidential.Credential) (string, error) @@ -99,7 +114,12 @@ func MakeDefaultMicrosoftGraphClientLoader(tokenFn AcquireTokenFn) MicrosoftGrap } } -func Plugin(version string, loader ClientLoadFn, openAiClientLoader AzureOpenaiClientLoadFn, graphClientLoader MicrosoftGraphClientLoadFn) *plugin.Schema { +func Plugin( + version string, + loader ClientLoadFn, + openAiClientLoader AzureOpenaiClientLoadFn, + graphClientLoader MicrosoftGraphClientLoadFn, +) *plugin.Schema { if loader == nil { loader = DefaultClientLoader } diff --git a/mocks/internalpkg/microsoft/microsoft_graph_client.go b/mocks/internalpkg/microsoft/microsoft_graph_client.go index 3bfe9916..3d7e6bbf 100644 --- a/mocks/internalpkg/microsoft/microsoft_graph_client.go +++ b/mocks/internalpkg/microsoft/microsoft_graph_client.go @@ -7,6 +7,8 @@ import ( mock "github.com/stretchr/testify/mock" + plugindata "github.com/blackstork-io/fabric/plugin/plugindata" + url "net/url" ) @@ -23,29 +25,29 @@ func (_m *MicrosoftGraphClient) EXPECT() *MicrosoftGraphClient_Expecter { return &MicrosoftGraphClient_Expecter{mock: &_m.Mock} } -// QueryGraph provides a mock function with given fields: ctx, endpoint, queryParams -func (_m *MicrosoftGraphClient) QueryGraph(ctx context.Context, endpoint string, queryParams url.Values) (interface{}, error) { - ret := _m.Called(ctx, endpoint, queryParams) +// QueryGraph provides a mock function with given fields: ctx, endpoint, queryParams, size, onlyObjects +func (_m *MicrosoftGraphClient) QueryGraph(ctx context.Context, endpoint string, queryParams url.Values, size int, onlyObjects bool) (plugindata.Data, error) { + ret := _m.Called(ctx, endpoint, queryParams, size, onlyObjects) if len(ret) == 0 { panic("no return value specified for QueryGraph") } - var r0 interface{} + var r0 plugindata.Data var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, url.Values) (interface{}, error)); ok { - return rf(ctx, endpoint, queryParams) + if rf, ok := ret.Get(0).(func(context.Context, string, url.Values, int, bool) (plugindata.Data, error)); ok { + return rf(ctx, endpoint, queryParams, size, onlyObjects) } - if rf, ok := ret.Get(0).(func(context.Context, string, url.Values) interface{}); ok { - r0 = rf(ctx, endpoint, queryParams) + if rf, ok := ret.Get(0).(func(context.Context, string, url.Values, int, bool) plugindata.Data); ok { + r0 = rf(ctx, endpoint, queryParams, size, onlyObjects) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) + r0 = ret.Get(0).(plugindata.Data) } } - if rf, ok := ret.Get(1).(func(context.Context, string, url.Values) error); ok { - r1 = rf(ctx, endpoint, queryParams) + if rf, ok := ret.Get(1).(func(context.Context, string, url.Values, int, bool) error); ok { + r1 = rf(ctx, endpoint, queryParams, size, onlyObjects) } else { r1 = ret.Error(1) } @@ -62,23 +64,84 @@ type MicrosoftGraphClient_QueryGraph_Call struct { // - ctx context.Context // - endpoint string // - queryParams url.Values -func (_e *MicrosoftGraphClient_Expecter) QueryGraph(ctx interface{}, endpoint interface{}, queryParams interface{}) *MicrosoftGraphClient_QueryGraph_Call { - return &MicrosoftGraphClient_QueryGraph_Call{Call: _e.mock.On("QueryGraph", ctx, endpoint, queryParams)} +// - size int +// - onlyObjects bool +func (_e *MicrosoftGraphClient_Expecter) QueryGraph(ctx interface{}, endpoint interface{}, queryParams interface{}, size interface{}, onlyObjects interface{}) *MicrosoftGraphClient_QueryGraph_Call { + return &MicrosoftGraphClient_QueryGraph_Call{Call: _e.mock.On("QueryGraph", ctx, endpoint, queryParams, size, onlyObjects)} +} + +func (_c *MicrosoftGraphClient_QueryGraph_Call) Run(run func(ctx context.Context, endpoint string, queryParams url.Values, size int, onlyObjects bool)) *MicrosoftGraphClient_QueryGraph_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(string), args[2].(url.Values), args[3].(int), args[4].(bool)) + }) + return _c +} + +func (_c *MicrosoftGraphClient_QueryGraph_Call) Return(objects plugindata.Data, err error) *MicrosoftGraphClient_QueryGraph_Call { + _c.Call.Return(objects, err) + return _c +} + +func (_c *MicrosoftGraphClient_QueryGraph_Call) RunAndReturn(run func(context.Context, string, url.Values, int, bool) (plugindata.Data, error)) *MicrosoftGraphClient_QueryGraph_Call { + _c.Call.Return(run) + return _c +} + +// QueryGraphObject provides a mock function with given fields: ctx, endpoint +func (_m *MicrosoftGraphClient) QueryGraphObject(ctx context.Context, endpoint string) (plugindata.Data, error) { + ret := _m.Called(ctx, endpoint) + + if len(ret) == 0 { + panic("no return value specified for QueryGraphObject") + } + + var r0 plugindata.Data + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string) (plugindata.Data, error)); ok { + return rf(ctx, endpoint) + } + if rf, ok := ret.Get(0).(func(context.Context, string) plugindata.Data); ok { + r0 = rf(ctx, endpoint) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(plugindata.Data) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, endpoint) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MicrosoftGraphClient_QueryGraphObject_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'QueryGraphObject' +type MicrosoftGraphClient_QueryGraphObject_Call struct { + *mock.Call +} + +// QueryGraphObject is a helper method to define mock.On call +// - ctx context.Context +// - endpoint string +func (_e *MicrosoftGraphClient_Expecter) QueryGraphObject(ctx interface{}, endpoint interface{}) *MicrosoftGraphClient_QueryGraphObject_Call { + return &MicrosoftGraphClient_QueryGraphObject_Call{Call: _e.mock.On("QueryGraphObject", ctx, endpoint)} } -func (_c *MicrosoftGraphClient_QueryGraph_Call) Run(run func(ctx context.Context, endpoint string, queryParams url.Values)) *MicrosoftGraphClient_QueryGraph_Call { +func (_c *MicrosoftGraphClient_QueryGraphObject_Call) Run(run func(ctx context.Context, endpoint string)) *MicrosoftGraphClient_QueryGraphObject_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(string), args[2].(url.Values)) + run(args[0].(context.Context), args[1].(string)) }) return _c } -func (_c *MicrosoftGraphClient_QueryGraph_Call) Return(result interface{}, err error) *MicrosoftGraphClient_QueryGraph_Call { +func (_c *MicrosoftGraphClient_QueryGraphObject_Call) Return(result plugindata.Data, err error) *MicrosoftGraphClient_QueryGraphObject_Call { _c.Call.Return(result, err) return _c } -func (_c *MicrosoftGraphClient_QueryGraph_Call) RunAndReturn(run func(context.Context, string, url.Values) (interface{}, error)) *MicrosoftGraphClient_QueryGraph_Call { +func (_c *MicrosoftGraphClient_QueryGraphObject_Call) RunAndReturn(run func(context.Context, string) (plugindata.Data, error)) *MicrosoftGraphClient_QueryGraphObject_Call { _c.Call.Return(run) return _c } diff --git a/plugin/runner/loader.go b/plugin/runner/loader.go index bc2b7c8c..fc8d93c9 100644 --- a/plugin/runner/loader.go +++ b/plugin/runner/loader.go @@ -167,8 +167,9 @@ func (l *loader) registerPublisher(ctx context.Context, name string, schema *plu } func (l *loader) registerPlugin(ctx context.Context, schema *plugin.Schema, closefn func() error) diagnostics.Diag { - l.logger.DebugContext(ctx, "Registering plugin", "name", schema.Name, "version", schema.Version) + l.logger.DebugContext(ctx, "Registering a plugin", "name", schema.Name, "version", schema.Version) if diags := schema.Validate(); diags.HasErrors() { + l.logger.ErrorContext(ctx, "Validation errors while registering a plugin", "name", schema.Name, "version", schema.Version) return diags } schema = plugin.WithLogging(schema, l.logger)