github.com/newrelic/newrelic-client-go@v1.1.0/pkg/nerdstorage/nerdstorage.go (about)

     1  package nerdstorage
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	"github.com/imdario/mergo"
     9  
    10  	"github.com/newrelic/newrelic-client-go/internal/http"
    11  	"github.com/newrelic/newrelic-client-go/pkg/config"
    12  	"github.com/newrelic/newrelic-client-go/pkg/logging"
    13  )
    14  
    15  const (
    16  	accountScope = "ACCOUNT"
    17  	actorScope   = "ACTOR"
    18  	entityScope  = "ENTITY"
    19  )
    20  
    21  // GetDocumentInput represents the input data required for retrieving a NerdStorage document.
    22  type GetDocumentInput struct {
    23  	Collection string
    24  	DocumentID string
    25  	PackageID  string
    26  }
    27  
    28  // GetDocumentWithAccountScope retrieves a NerdStorage document with account scope.
    29  func (e *NerdStorage) GetDocumentWithAccountScope(accountID int, input GetDocumentInput) (interface{}, error) {
    30  	return e.GetDocumentWithAccountScopeWithContext(context.Background(), accountID, input)
    31  }
    32  
    33  // GetDocumentWithAccountScopeWithContext retrieves a NerdStorage document with account scope.
    34  func (e *NerdStorage) GetDocumentWithAccountScopeWithContext(ctx context.Context, accountID int, input GetDocumentInput) (interface{}, error) {
    35  	if accountID == 0 {
    36  		return nil, fmt.Errorf("account ID is required when using account scope")
    37  	}
    38  
    39  	scopeID := strconv.Itoa(accountID)
    40  	vars := map[string]interface{}{"accountId": accountID}
    41  
    42  	resp, err := e.getDocumentWithScope(ctx, accountScope, scopeID, getDocumentWithAccountScopeQuery, vars, input)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  
    47  	return resp.Actor.Account.NerdStorage.Document, nil
    48  }
    49  
    50  // GetDocumentWithUserScope retrieves a NerdStorage document with user scope.
    51  func (e *NerdStorage) GetDocumentWithUserScope(input GetDocumentInput) (interface{}, error) {
    52  	return e.GetDocumentWithUserScopeWithContext(context.Background(), input)
    53  }
    54  
    55  // GetDocumentWithUserScopeWithContext retrieves a NerdStorage document with user scope.
    56  func (e *NerdStorage) GetDocumentWithUserScopeWithContext(ctx context.Context, input GetDocumentInput) (interface{}, error) {
    57  	userID, err := e.getUserID(ctx)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  
    62  	scopeID := strconv.Itoa(userID)
    63  
    64  	resp, err := e.getDocumentWithScope(ctx, actorScope, scopeID, getDocumentWithUserScopeQuery, nil, input)
    65  	if err != nil {
    66  		return nil, err
    67  	}
    68  
    69  	return resp.Actor.NerdStorage.Document, nil
    70  }
    71  
    72  // GetDocumentWithEntityScope retrieves a NerdStorage document with entity scope.
    73  func (e *NerdStorage) GetDocumentWithEntityScope(entityGUID string, input GetDocumentInput) (interface{}, error) {
    74  	return e.GetDocumentWithEntityScopeWithContext(context.Background(), entityGUID, input)
    75  }
    76  
    77  // GetDocumentWithEntityScopeWithContext retrieves a NerdStorage document with entity scope.
    78  func (e *NerdStorage) GetDocumentWithEntityScopeWithContext(ctx context.Context, entityGUID string, input GetDocumentInput) (interface{}, error) {
    79  	if entityGUID == "" {
    80  		return nil, fmt.Errorf("entity GUID is required when using entity scope")
    81  	}
    82  
    83  	vars := map[string]interface{}{"entityGuid": entityGUID}
    84  	resp, err := e.getDocumentWithScope(ctx, entityScope, entityGUID, getDocumentWithEntityScopeQuery, vars, input)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	return resp.Actor.Entity.NerdStorage.Document, nil
    90  }
    91  
    92  // GetCollectionInput represents the input data required for retrieving a NerdStorage collection.
    93  type GetCollectionInput struct {
    94  	Collection string
    95  	PackageID  string
    96  }
    97  
    98  // GetCollectionWithAccountScope retrieves a NerdStorage collection with account scope.
    99  func (e *NerdStorage) GetCollectionWithAccountScope(accountID int, input GetCollectionInput) ([]interface{}, error) {
   100  	return e.GetCollectionWithAccountScopeWithContext(context.Background(), accountID, input)
   101  }
   102  
   103  // GetCollectionWithAccountScopeWithContext retrieves a NerdStorage collection with account scope.
   104  func (e *NerdStorage) GetCollectionWithAccountScopeWithContext(ctx context.Context, accountID int, input GetCollectionInput) ([]interface{}, error) {
   105  	if accountID == 0 {
   106  		return nil, fmt.Errorf("account ID is required when using account scope")
   107  	}
   108  
   109  	scopeID := strconv.Itoa(accountID)
   110  	vars := map[string]interface{}{"accountId": accountID}
   111  
   112  	resp, err := e.getCollectionWithScope(ctx, accountScope, scopeID, getCollectionWithAccountScopeQuery, vars, input)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  
   117  	return resp.Actor.Account.NerdStorage.Collection, nil
   118  }
   119  
   120  // GetCollectionWithUserScope retrieves a NerdStorage collection with user scope.
   121  func (e *NerdStorage) GetCollectionWithUserScope(input GetCollectionInput) ([]interface{}, error) {
   122  	return e.GetCollectionWithUserScopeWithContext(context.Background(), input)
   123  }
   124  
   125  // GetCollectionWithUserScopeWithContext retrieves a NerdStorage collection with user scope.
   126  func (e *NerdStorage) GetCollectionWithUserScopeWithContext(ctx context.Context, input GetCollectionInput) ([]interface{}, error) {
   127  	userID, err := e.getUserID(ctx)
   128  	if err != nil {
   129  		return nil, err
   130  	}
   131  
   132  	scopeID := strconv.Itoa(userID)
   133  	resp, err := e.getCollectionWithScope(ctx, actorScope, scopeID, getCollectionWithUserScopeQuery, nil, input)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	return resp.Actor.NerdStorage.Collection, nil
   139  }
   140  
   141  // GetCollectionWithEntityScope wretrieves a NerdStorage collection with entity scope.
   142  func (e *NerdStorage) GetCollectionWithEntityScope(entityGUID string, input GetCollectionInput) ([]interface{}, error) {
   143  	return e.GetCollectionWithEntityScopeWithContext(context.Background(), entityGUID, input)
   144  }
   145  
   146  // GetCollectionWithEntityScopeWithContext wretrieves a NerdStorage collection with entity scope.
   147  func (e *NerdStorage) GetCollectionWithEntityScopeWithContext(ctx context.Context, entityGUID string, input GetCollectionInput) ([]interface{}, error) {
   148  	if entityGUID == "" {
   149  		return nil, fmt.Errorf("entity GUID is required when using entity scope")
   150  	}
   151  
   152  	vars := map[string]interface{}{"entityGuid": entityGUID}
   153  	resp, err := e.getCollectionWithScope(ctx, entityScope, entityGUID, getCollectionWithEntityScopeQuery, vars, input)
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	return resp.Actor.Entity.NerdStorage.Collection, nil
   159  }
   160  
   161  // WriteDocumentInput represents the input data required for the WriteDocument mutation.
   162  type WriteDocumentInput struct {
   163  	Collection string
   164  	Document   interface{}
   165  	DocumentID string
   166  	PackageID  string
   167  }
   168  
   169  // WriteDocumentWithAccountScope writes a NerdStorage document with account scope.
   170  func (e *NerdStorage) WriteDocumentWithAccountScope(accountID int, input WriteDocumentInput) (interface{}, error) {
   171  	return e.WriteDocumentWithAccountScopeWithContext(context.Background(), accountID, input)
   172  }
   173  
   174  // WriteDocumentWithAccountScopeWithContext writes a NerdStorage document with account scope.
   175  func (e *NerdStorage) WriteDocumentWithAccountScopeWithContext(ctx context.Context, accountID int, input WriteDocumentInput) (interface{}, error) {
   176  	if accountID == 0 {
   177  		return nil, fmt.Errorf("account ID is required when using account scope")
   178  	}
   179  
   180  	scopeID := strconv.Itoa(accountID)
   181  
   182  	return e.writeDocumentWithScope(ctx, accountScope, scopeID, input)
   183  }
   184  
   185  // WriteDocumentWithUserScope writes a NerdStorage document with user scope.
   186  func (e *NerdStorage) WriteDocumentWithUserScope(input WriteDocumentInput) (interface{}, error) {
   187  	return e.WriteDocumentWithUserScopeWithContext(context.Background(), input)
   188  }
   189  
   190  // WriteDocumentWithUserScopeWithContext writes a NerdStorage document with user scope.
   191  func (e *NerdStorage) WriteDocumentWithUserScopeWithContext(ctx context.Context, input WriteDocumentInput) (interface{}, error) {
   192  	userID, err := e.getUserID(ctx)
   193  	if err != nil {
   194  		return nil, err
   195  	}
   196  
   197  	scopeID := strconv.Itoa(userID)
   198  	return e.writeDocumentWithScope(ctx, actorScope, scopeID, input)
   199  }
   200  
   201  // WriteDocumentWithEntityScope writes a NerdStorage document with entity scope.
   202  func (e *NerdStorage) WriteDocumentWithEntityScope(entityGUID string, input WriteDocumentInput) (interface{}, error) {
   203  	return e.WriteDocumentWithEntityScopeWithContext(context.Background(), entityGUID, input)
   204  }
   205  
   206  // WriteDocumentWithEntityScopeWithContext writes a NerdStorage document with entity scope.
   207  func (e *NerdStorage) WriteDocumentWithEntityScopeWithContext(ctx context.Context, entityGUID string, input WriteDocumentInput) (interface{}, error) {
   208  	if entityGUID == "" {
   209  		return nil, fmt.Errorf("entity GUID is required when using entity scope")
   210  	}
   211  
   212  	return e.writeDocumentWithScope(ctx, entityScope, entityGUID, input)
   213  }
   214  
   215  // DeleteDocumentInput represents the input data required for the DeleteDocument mutation.
   216  type DeleteDocumentInput struct {
   217  	Collection string
   218  	DocumentID string
   219  	PackageID  string
   220  }
   221  
   222  // DeleteDocumentWithAccountScope deletes a NerdStorage document with account scope.
   223  func (e *NerdStorage) DeleteDocumentWithAccountScope(accountID int, input DeleteDocumentInput) (bool, error) {
   224  	return e.DeleteDocumentWithAccountScopeWithContext(context.Background(), accountID, input)
   225  }
   226  
   227  // DeleteDocumentWithAccountScopeWithContext deletes a NerdStorage document with account scope.
   228  func (e *NerdStorage) DeleteDocumentWithAccountScopeWithContext(ctx context.Context, accountID int, input DeleteDocumentInput) (bool, error) {
   229  	if accountID == 0 {
   230  		return false, fmt.Errorf("account ID is required when using account scope")
   231  	}
   232  
   233  	scopeID := strconv.Itoa(accountID)
   234  
   235  	return e.deleteDocumentWithScope(ctx, accountScope, scopeID, input)
   236  }
   237  
   238  // DeleteDocumentWithUserScope deletes a NerdStorage document with user scope.
   239  func (e *NerdStorage) DeleteDocumentWithUserScope(input DeleteDocumentInput) (bool, error) {
   240  	return e.DeleteDocumentWithUserScopeWithContext(context.Background(), input)
   241  }
   242  
   243  // DeleteDocumentWithUserScopeWithContext deletes a NerdStorage document with user scope.
   244  func (e *NerdStorage) DeleteDocumentWithUserScopeWithContext(ctx context.Context, input DeleteDocumentInput) (bool, error) {
   245  	userID, err := e.getUserID(ctx)
   246  	if err != nil {
   247  		return false, err
   248  	}
   249  
   250  	scopeID := strconv.Itoa(userID)
   251  	return e.deleteDocumentWithScope(ctx, actorScope, scopeID, input)
   252  }
   253  
   254  // DeleteDocumentWithEntityScope deletes a NerdStorage document with entity scope.
   255  func (e *NerdStorage) DeleteDocumentWithEntityScope(entityGUID string, input DeleteDocumentInput) (bool, error) {
   256  	return e.DeleteDocumentWithEntityScopeWithContext(context.Background(), entityGUID, input)
   257  }
   258  
   259  // DeleteDocumentWithEntityScopeWithContext deletes a NerdStorage document with entity scope.
   260  func (e *NerdStorage) DeleteDocumentWithEntityScopeWithContext(ctx context.Context, entityGUID string, input DeleteDocumentInput) (bool, error) {
   261  	if entityGUID == "" {
   262  		return false, fmt.Errorf("entity GUID is required when using entity scope")
   263  	}
   264  
   265  	return e.deleteDocumentWithScope(ctx, entityScope, entityGUID, input)
   266  }
   267  
   268  // DeleteCollectionInput represents the input data required for the DeleteCollection mutation.
   269  type DeleteCollectionInput struct {
   270  	Collection string
   271  	PackageID  string
   272  }
   273  
   274  // DeleteCollectionWithAccountScope deletes a NerdStorage collection with account scope.
   275  func (e *NerdStorage) DeleteCollectionWithAccountScope(accountID int, input DeleteCollectionInput) (bool, error) {
   276  	return e.DeleteCollectionWithAccountScopeWithContext(context.Background(), accountID, input)
   277  }
   278  
   279  // DeleteCollectionWithAccountScopeWithContext deletes a NerdStorage collection with account scope.
   280  func (e *NerdStorage) DeleteCollectionWithAccountScopeWithContext(ctx context.Context, accountID int, input DeleteCollectionInput) (bool, error) {
   281  	if accountID == 0 {
   282  		return false, fmt.Errorf("account ID is required when using account scope")
   283  	}
   284  
   285  	scopeID := strconv.Itoa(accountID)
   286  
   287  	return e.deleteCollectionWithScope(ctx, accountScope, scopeID, input)
   288  }
   289  
   290  // DeleteCollectionWithUserScope deletes a NerdStorage collection with user scope.
   291  func (e *NerdStorage) DeleteCollectionWithUserScope(input DeleteCollectionInput) (bool, error) {
   292  	return e.DeleteCollectionWithUserScopeWithContext(context.Background(), input)
   293  }
   294  
   295  // DeleteCollectionWithUserScopeWithContext deletes a NerdStorage collection with user scope.
   296  func (e *NerdStorage) DeleteCollectionWithUserScopeWithContext(ctx context.Context, input DeleteCollectionInput) (bool, error) {
   297  	userID, err := e.getUserID(ctx)
   298  	if err != nil {
   299  		return false, err
   300  	}
   301  
   302  	scopeID := strconv.Itoa(userID)
   303  
   304  	return e.deleteCollectionWithScope(ctx, actorScope, scopeID, input)
   305  }
   306  
   307  // DeleteCollectionWithEntityScope deletes a NerdStorage collection with entity scope.
   308  func (e *NerdStorage) DeleteCollectionWithEntityScope(entityGUID string, input DeleteCollectionInput) (bool, error) {
   309  	return e.DeleteCollectionWithEntityScopeWithContext(context.Background(), entityGUID, input)
   310  }
   311  
   312  // DeleteCollectionWithEntityScopeWithContext deletes a NerdStorage collection with entity scope.
   313  func (e *NerdStorage) DeleteCollectionWithEntityScopeWithContext(ctx context.Context, entityGUID string, input DeleteCollectionInput) (bool, error) {
   314  	if entityGUID == "" {
   315  		return false, fmt.Errorf("entity GUID is required when using entity scope")
   316  	}
   317  
   318  	return e.deleteCollectionWithScope(ctx, entityScope, entityGUID, input)
   319  }
   320  
   321  func (e *NerdStorage) getDocumentWithScope(ctx context.Context, scope string, scopeID string, query string, vars map[string]interface{}, input GetDocumentInput) (*getResponse, error) {
   322  	var resp getResponse
   323  
   324  	v := map[string]interface{}{
   325  		"collection": input.Collection,
   326  		"documentId": input.DocumentID,
   327  		"scope": scopeInput{
   328  			Name: scope,
   329  			ID:   scopeID,
   330  		},
   331  	}
   332  
   333  	err := mergo.Merge(&v, vars)
   334  	if err != nil {
   335  		return nil, err
   336  	}
   337  
   338  	req, err := e.client.NewNerdGraphRequest(query, v, &resp)
   339  	if err != nil {
   340  		return nil, err
   341  	}
   342  
   343  	req.WithContext(ctx)
   344  	req.SetHeader("NewRelic-Package-ID", input.PackageID)
   345  
   346  	_, err = e.client.Do(req)
   347  	if err != nil {
   348  		return nil, err
   349  	}
   350  
   351  	return &resp, nil
   352  }
   353  
   354  func (e *NerdStorage) getCollectionWithScope(ctx context.Context, scope string, scopeID string, query string, vars map[string]interface{}, input GetCollectionInput) (*getResponse, error) {
   355  	var resp getResponse
   356  
   357  	v := map[string]interface{}{
   358  		"collection": input.Collection,
   359  		"scope": scopeInput{
   360  			Name: scope,
   361  			ID:   scopeID,
   362  		},
   363  	}
   364  
   365  	err := mergo.Merge(&v, vars)
   366  	if err != nil {
   367  		return nil, err
   368  	}
   369  
   370  	req, err := e.client.NewNerdGraphRequest(query, v, &resp)
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  
   375  	req.WithContext(ctx)
   376  	req.SetHeader("NewRelic-Package-ID", input.PackageID)
   377  
   378  	_, err = e.client.Do(req)
   379  	if err != nil {
   380  		return nil, err
   381  	}
   382  
   383  	return &resp, nil
   384  }
   385  
   386  func (e *NerdStorage) writeDocumentWithScope(ctx context.Context, scope string, scopeID string, input WriteDocumentInput) (interface{}, error) {
   387  	var resp writeDocumentResponse
   388  
   389  	vars := map[string]interface{}{
   390  		"collection": input.Collection,
   391  		"document":   input.Document,
   392  		"documentId": input.DocumentID,
   393  		"scope": scopeInput{
   394  			Name: scope,
   395  			ID:   scopeID,
   396  		},
   397  	}
   398  
   399  	req, err := e.client.NewNerdGraphRequest(writeDocumentMutation, vars, &resp)
   400  	if err != nil {
   401  		return "", err
   402  	}
   403  
   404  	req.WithContext(ctx)
   405  	req.SetHeader("NewRelic-Package-ID", input.PackageID)
   406  
   407  	_, err = e.client.Do(req)
   408  	if err != nil {
   409  		return "", err
   410  	}
   411  
   412  	return resp.NerdStorageWriteDocument, nil
   413  }
   414  
   415  func (e *NerdStorage) deleteDocumentWithScope(ctx context.Context, scope string, scopeID string, input DeleteDocumentInput) (bool, error) {
   416  	var resp deleteDocumentResponse
   417  
   418  	vars := map[string]interface{}{
   419  		"collection": input.Collection,
   420  		"documentId": input.DocumentID,
   421  		"scope": scopeInput{
   422  			Name: scope,
   423  			ID:   scopeID,
   424  		},
   425  	}
   426  
   427  	req, err := e.client.NewNerdGraphRequest(deleteDocumentMutation, vars, &resp)
   428  	if err != nil {
   429  		return false, err
   430  	}
   431  
   432  	req.WithContext(ctx)
   433  	req.SetHeader("NewRelic-Package-ID", input.PackageID)
   434  
   435  	_, err = e.client.Do(req)
   436  	if err != nil {
   437  		return false, err
   438  	}
   439  
   440  	return resp.NerdStorageDeleteDocument.Deleted != 0, nil
   441  }
   442  
   443  func (e *NerdStorage) deleteCollectionWithScope(ctx context.Context, scope string, scopeID string, input DeleteCollectionInput) (bool, error) {
   444  	var resp deleteCollectionResponse
   445  
   446  	vars := map[string]interface{}{
   447  		"collection": input.Collection,
   448  		"scope": scopeInput{
   449  			Name: scope,
   450  			ID:   scopeID,
   451  		},
   452  	}
   453  
   454  	req, err := e.client.NewNerdGraphRequest(deleteCollectionMutation, vars, &resp)
   455  	if err != nil {
   456  		return false, err
   457  	}
   458  
   459  	req.WithContext(ctx)
   460  	req.SetHeader("NewRelic-Package-ID", input.PackageID)
   461  
   462  	_, err = e.client.Do(req)
   463  	if err != nil {
   464  		return false, err
   465  	}
   466  
   467  	return resp.NerdStorageDeleteCollection.Deleted != 0, nil
   468  }
   469  
   470  func (e *NerdStorage) getUserID(ctx context.Context) (int, error) {
   471  	var resp userIDResponse
   472  
   473  	err := e.client.NerdGraphQueryWithContext(ctx, getUserIDQuery, nil, &resp)
   474  	if err != nil {
   475  		return 0, err
   476  	}
   477  
   478  	return resp.Actor.User.ID, nil
   479  }
   480  
   481  const (
   482  	getDocumentWithAccountScopeQuery = `
   483  		query($accountId: Int!, $documentId: String!, $collection: String!) {
   484  			actor {
   485  				account(id: $accountId) {
   486  					nerdStorage {
   487  						document(collection: $collection, documentId: $documentId)
   488  					}
   489  				}
   490  			}
   491  		}`
   492  
   493  	getDocumentWithEntityScopeQuery = `
   494  		query($entityGuid: EntityGuid!, $documentId: String!, $collection: String!) {
   495  			actor {
   496  				entity(guid: $entityGuid) {
   497  					nerdStorage {
   498  						document(collection: $collection, documentId: $documentId)
   499  					}
   500  				}
   501  			}
   502  		}`
   503  
   504  	getDocumentWithUserScopeQuery = `
   505  		query($documentId: String!, $collection: String!) {
   506  			actor {
   507  				nerdStorage {
   508  					document(collection: $collection, documentId: $documentId)
   509  				}
   510  			}
   511  		}`
   512  
   513  	getCollectionWithAccountScopeQuery = `
   514  		query($accountId: Int!, $collection: String!) {
   515  			actor {
   516  				account(id: $accountId) {
   517  					nerdStorage {
   518  						collection(collection: $collection) {
   519  							document
   520  							id
   521  						}
   522  					}
   523  				}
   524  			}
   525  		}`
   526  
   527  	getCollectionWithEntityScopeQuery = `
   528  		query($entityGuid: EntityGuid!, $collection: String!) {
   529  			actor {
   530  				entity(guid: $entityGuid) {
   531  					nerdStorage {
   532  						collection(collection: $collection) {
   533  							document
   534  							id
   535  						}
   536  					}
   537  				}
   538  			}
   539  		}`
   540  
   541  	getCollectionWithUserScopeQuery = `
   542  		query($collection: String!) {
   543  			actor {
   544  				nerdStorage {
   545  					collection(collection: $collection) {
   546  							document
   547  							id
   548  						}
   549  				}
   550  			}
   551  		}`
   552  
   553  	getUserIDQuery = `
   554  		query {
   555  			actor {
   556  				user {
   557  					id
   558  				}
   559  			}
   560  		}`
   561  
   562  	writeDocumentMutation = `
   563  		mutation($collection: String!, $document: NerdStorageDocument!, $documentId: String!, $scope: NerdStorageScopeInput!) {
   564  			nerdStorageWriteDocument(collection: $collection, document: $document, documentId: $documentId, scope: $scope)
   565  		}`
   566  
   567  	deleteDocumentMutation = `
   568  		mutation($collection: String!, $documentId: String!, $scope: NerdStorageScopeInput!) {
   569  			nerdStorageDeleteDocument(collection: $collection, documentId: $documentId, scope: $scope) {
   570  				deleted
   571  			}
   572  		}`
   573  
   574  	deleteCollectionMutation = `
   575  		mutation($collection: String!, $scope: NerdStorageScopeInput!) {
   576  			nerdStorageDeleteCollection(collection: $collection, scope: $scope) {
   577  				deleted
   578  			}
   579  		}`
   580  )
   581  
   582  type scopeInput struct {
   583  	Name string
   584  	ID   string
   585  }
   586  
   587  type getResponse struct {
   588  	Actor struct {
   589  		Account struct {
   590  			NerdStorage struct {
   591  				Document   interface{}
   592  				Collection []interface{}
   593  			}
   594  		}
   595  		Entity struct {
   596  			NerdStorage struct {
   597  				Document   interface{}
   598  				Collection []interface{}
   599  			}
   600  		}
   601  		NerdStorage struct {
   602  			Document   interface{}
   603  			Collection []interface{}
   604  		}
   605  	}
   606  }
   607  
   608  type userIDResponse struct {
   609  	Actor struct {
   610  		User struct {
   611  			ID int
   612  		}
   613  	}
   614  }
   615  
   616  type writeDocumentResponse struct {
   617  	NerdStorageWriteDocument interface{}
   618  }
   619  
   620  type deleteDocumentResponse struct {
   621  	NerdStorageDeleteDocument struct {
   622  		Deleted int
   623  	}
   624  }
   625  
   626  type deleteCollectionResponse struct {
   627  	NerdStorageDeleteCollection struct {
   628  		Deleted int
   629  	}
   630  }
   631  
   632  // NerdStorage is used to communicate with the New Relic Workloads product.
   633  type NerdStorage struct {
   634  	client http.Client
   635  	logger logging.Logger
   636  }
   637  
   638  // New returns a new client for interacting with the New Relic One NerdStorage
   639  // document store.
   640  func New(config config.Config) NerdStorage {
   641  	return NerdStorage{
   642  		client: http.NewClient(config),
   643  		logger: config.GetLogger(),
   644  	}
   645  }