diff --git a/internal/apiaccess/command.go b/internal/apiaccess/command.go index 8b546b25b..604a135cc 100644 --- a/internal/apiaccess/command.go +++ b/internal/apiaccess/command.go @@ -27,6 +27,7 @@ var cmdKey = &cobra.Command{ Short: "Fetch a single key by ID and type.\n\n---\n**NR Internal** | [#help-unified-api](https://newrelic.slack.com/archives/CBHJRSPSA) | visibility(customer)\n\n", Long: "", Example: "newrelic apiAccess apiAccessGetKey --id --keyType", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { resp, err := client.NRClient.APIAccess.GetAPIAccessKeyWithContext(utils.SignalCtx, apiAccessGetKeyid, apiaccess.APIAccessKeyType(apiAccessGetKeykeyType)) utils.LogIfFatal(err) @@ -41,6 +42,7 @@ var cmdAPIAccessCreateKeys = &cobra.Command{ Short: "Create keys. You can create keys for multiple accounts at once. You can read more about managing keys on [this documentation page](https://docs.newrelic.com/docs/apis/nerdgraph/examples/use-nerdgraph-manage-license-keys-personal-api-keys).", Long: "", Example: "newrelic apiAccess apiAccessCreateKeys --keys", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var keys apiaccess.APIAccessCreateInput @@ -60,6 +62,7 @@ var cmdAPIAccessUpdateKeys = &cobra.Command{ Short: "Update keys. You can update keys for multiple accounts at once. You can read more about managing keys on [this documentation page](https://docs.newrelic.com/docs/apis/nerdgraph/examples/use-nerdgraph-manage-license-keys-personal-api-keys).", Long: "", Example: "newrelic apiAccess apiAccessUpdateKeys --keys", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var keys apiaccess.APIAccessUpdateInput @@ -79,6 +82,7 @@ var cmdAPIAccessDeleteKeys = &cobra.Command{ Short: "A mutation to delete keys.", Long: "", Example: "newrelic apiAccess apiAccessDeleteKeys --keys", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var keys apiaccess.APIAccessDeleteInput diff --git a/internal/apm/command_application.go b/internal/apm/command_application.go index 47699f538..82cd6a011 100644 --- a/internal/apm/command_application.go +++ b/internal/apm/command_application.go @@ -36,6 +36,7 @@ var cmdAppSearch = &cobra.Command{ The search command performs a query for an APM application name and/or account ID. `, Example: "newrelic apm application search --name ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if apmAccountID != 0 { @@ -100,6 +101,7 @@ var cmdAppGet = &cobra.Command{ The get command performs a query for an APM application by GUID. `, Example: "newrelic apm application get --guid ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var results *entities.EntityInterface var err error diff --git a/internal/apm/command_deployment.go b/internal/apm/command_deployment.go index 4f6a74b47..5d7c7baf9 100644 --- a/internal/apm/command_deployment.go +++ b/internal/apm/command_deployment.go @@ -36,6 +36,7 @@ var cmdDeploymentList = &cobra.Command{ The list command returns deployments for a New Relic APM application. `, Example: "newrelic apm deployment list --applicationId ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if apmAppID == 0 { utils.LogIfError(cmd.Help()) @@ -58,6 +59,7 @@ The create command creates a new deployment marker for a New Relic APM application. `, Example: "newrelic apm deployment create --applicationId --revision ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if apmAppID == 0 { utils.LogIfError(cmd.Help()) @@ -79,6 +81,7 @@ var cmdDeploymentDelete = &cobra.Command{ The delete command performs a delete operation for an APM deployment. `, Example: "newrelic apm deployment delete --applicationId --deploymentID ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if apmAppID == 0 { utils.LogIfError(cmd.Help()) diff --git a/internal/client/client.go b/internal/client/client.go index b7a7cd824..5f2fb00fd 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -6,6 +6,9 @@ import ( "github.com/newrelic/newrelic-cli/internal/configuration" "github.com/newrelic/newrelic-client-go/newrelic" + "github.com/spf13/cobra" + + log "github.com/sirupsen/logrus" ) var ( @@ -43,3 +46,9 @@ func NewClient(profileName string) (*newrelic.NewRelic, error) { return nrClient, nil } + +func RequireClient(cmd *cobra.Command, args []string) { + if NRClient == nil { + log.Fatalf("could not initialize New Relic client, make sure your profile is configured with `newrelic profile configure`") + } +} diff --git a/internal/diagnose/command_validate.go b/internal/diagnose/command_validate.go index 6f7bee320..9b838f0a0 100644 --- a/internal/diagnose/command_validate.go +++ b/internal/diagnose/command_validate.go @@ -16,6 +16,7 @@ var cmdValidate = &cobra.Command{ Checks the configuration in the default or specified configuation profile by sending data to the New Relic platform and verifying that it has been received.`, Example: "\tnewrelic diagnose validate", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { v := NewConfigValidator(client.NRClient) diff --git a/internal/edge/command_trace_observer.go b/internal/edge/command_trace_observer.go index 847553d70..88c1c2ef4 100644 --- a/internal/edge/command_trace_observer.go +++ b/internal/edge/command_trace_observer.go @@ -41,6 +41,7 @@ var cmdList = &cobra.Command{ The list command retrieves the trace observers for the given account ID. `, Example: `newrelic edge trace-observer list --accountId 12345678`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { traceObservers, err := client.NRClient.Edge.ListTraceObserversWithContext(utils.SignalCtx, accountID) utils.LogIfFatal(err) @@ -68,6 +69,7 @@ The create command requires an account ID, observer name, and provider region. Valid provider regions are AWS_US_EAST_1 and AWS_US_EAST_2. `, Example: `newrelic edge trace-observer create --name 'My Observer' --accountId 12345678 --providerRegion AWS_US_EAST_1`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if ok := isValidProviderRegion(providerRegion); !ok { log.Fatalf("%s is not a valid provider region, valid values are %s", providerRegion, validProviderRegions) @@ -89,6 +91,7 @@ var cmdDelete = &cobra.Command{ The delete command accepts a trace observer's ID. `, Example: `newrelic edge trace-observer delete --accountId 12345678 --id 1234`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { _, err := client.NRClient.Edge.DeleteTraceObserver(accountID, id) utils.LogIfFatal(err) diff --git a/internal/entities/command_search.go b/internal/entities/command_search.go index 374cf2680..bd03052ef 100644 --- a/internal/entities/command_search.go +++ b/internal/entities/command_search.go @@ -20,6 +20,7 @@ var cmdEntitySearch = &cobra.Command{ The search command performs a search for New Relic entities. `, Example: "newrelic entity search --name ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { params := entities.EntitySearchQueryBuilder{} diff --git a/internal/entities/command_tags.go b/internal/entities/command_tags.go index c283f0d1d..a30c1fa84 100644 --- a/internal/entities/command_tags.go +++ b/internal/entities/command_tags.go @@ -38,6 +38,7 @@ var cmdTagsGet = &cobra.Command{ The get command returns JSON output of the tags for the requested entity. `, Example: "newrelic entity tags get --guid ", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { // Temporary until bulk actions can be build into newrelic-client-go if value, ok := pipe.Get("guid"); ok { @@ -61,6 +62,7 @@ The delete command deletes all tags on the given entity that match the specified keys. `, Example: "newrelic entity tags delete --guid --tag tag1 --tag tag2 --tag tag3,tag4", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { _, err := client.NRClient.Entities.TaggingDeleteTagFromEntityWithContext(utils.SignalCtx, entities.EntityGUID(entityGUID), entityTags) utils.LogIfFatal(err) @@ -77,6 +79,7 @@ var cmdTagsDeleteValues = &cobra.Command{ The delete-values command deletes the specified tag:value pairs on a given entity. `, Example: "newrelic entity tags delete-values --guid --tag tag1:value1", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { tagValues, err := assembleTagValuesInput(entityValues) utils.LogIfFatal(err) @@ -96,6 +99,7 @@ var cmdTagsCreate = &cobra.Command{ The create command adds tag:value pairs to the given entity. `, Example: "newrelic entity tags create --guid --tag tag1:value1", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { tags, err := assembleTagsInput(entityTags) utils.LogIfFatal(err) @@ -116,6 +120,7 @@ The replace command replaces any existing tag:value pairs with those provided for the given entity. `, Example: "newrelic entity tags replace --guid --tag tag1:value1", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { tags, err := assembleTagsInput(entityTags) utils.LogIfFatal(err) @@ -154,23 +159,6 @@ func assembleTagsInput(tags []string) ([]entities.TaggingTagInput, error) { return t, nil } -func assembleTagValues(values []string) ([]entities.EntitySearchQueryBuilderTag, error) { - var tagValues []entities.EntitySearchQueryBuilderTag - - for _, x := range values { - key, value, err := assembleTagValue(x) - - if err != nil { - return []entities.EntitySearchQueryBuilderTag{}, err - } - - tagValues = append(tagValues, entities.EntitySearchQueryBuilderTag{Key: key, Value: value}) - } - - return tagValues, nil -} - -// assembleTagValuesInput is the same as assembleTagValues func assembleTagValuesInput(values []string) ([]entities.TaggingTagValueInput, error) { var tagValues []entities.TaggingTagValueInput diff --git a/internal/events/command_post.go b/internal/events/command_post.go index 073f526d1..a94545229 100644 --- a/internal/events/command_post.go +++ b/internal/events/command_post.go @@ -28,6 +28,7 @@ The accepted payload requires the use of an ` + "`eventType`" + `field that represents the custom event's type. `, Example: `newrelic events post --accountId 12345 --event '{ "eventType": "Payment", "amount": 123.45 }'`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if configuration.GetActiveProfileString(configuration.InsightsInsertKey) == "" { log.Fatal("an Insights insert key is required, set one in your default profile or use the NEW_RELIC_INSIGHTS_INSERT_KEY environment variable") diff --git a/internal/install/command.go b/internal/install/command.go index 1a3c45a31..d0e05661e 100644 --- a/internal/install/command.go +++ b/internal/install/command.go @@ -27,8 +27,9 @@ var ( // Command represents the install command. var Command = &cobra.Command{ - Use: "install", - Short: "Install New Relic.", + Use: "install", + Short: "Install New Relic.", + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { ic := types.InstallerContext{ AssumeYes: assumeYes, diff --git a/internal/nerdgraph/command_query.go b/internal/nerdgraph/command_query.go index 979e6a41d..315fe5a0b 100644 --- a/internal/nerdgraph/command_query.go +++ b/internal/nerdgraph/command_query.go @@ -41,6 +41,7 @@ keys are the variables to be referenced in the GraphQL query. return nil }, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var variablesParsed map[string]interface{} diff --git a/internal/nerdstorage/command_collection.go b/internal/nerdstorage/command_collection.go index 2e46f0b7e..613481f71 100644 --- a/internal/nerdstorage/command_collection.go +++ b/internal/nerdstorage/command_collection.go @@ -38,6 +38,7 @@ GUID. A valid Nerdpack package ID is required. # User scope newrelic nerdstorage collection get --scope USER --packageId b0dee5a1-e809-4d6f-bd3c-0682cd079612 --collection myCol `, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var resp []interface{} var err error @@ -85,6 +86,7 @@ GUID. A valid Nerdpack package ID is required. # User scope newrelic nerdstorage collection delete --scope USER --packageId b0dee5a1-e809-4d6f-bd3c-0682cd079612 --collection myCol `, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var err error diff --git a/internal/nerdstorage/command_document.go b/internal/nerdstorage/command_document.go index 20dfb72fb..25ac865d2 100644 --- a/internal/nerdstorage/command_document.go +++ b/internal/nerdstorage/command_document.go @@ -39,6 +39,7 @@ GUID. A valid Nerdpack package ID is required. # User scope newrelic nerdstorage document get --scope USER --packageId b0dee5a1-e809-4d6f-bd3c-0682cd079612 --collection myCol --documentId myDoc `, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var document interface{} var err error @@ -87,6 +88,7 @@ GUID. A valid Nerdpack package ID is required. # User scope newrelic nerdstorage document write --scope USER --packageId b0dee5a1-e809-4d6f-bd3c-0682cd079612 --collection myCol --documentId myDoc --document '{"field": "myValue"}' `, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var unmarshaled map[string]interface{} err := json.Unmarshal([]byte(document), &unmarshaled) @@ -138,6 +140,7 @@ GUID. A valid Nerdpack package ID is required. # User scope newrelic nerdstorage document delete --scope USER --packageId b0dee5a1-e809-4d6f-bd3c-0682cd079612 --collection myCol --documentId myDoc `, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { var err error diff --git a/internal/nrql/command_query.go b/internal/nrql/command_query.go index b7ca45d10..6d22bf1c1 100644 --- a/internal/nrql/command_query.go +++ b/internal/nrql/command_query.go @@ -26,6 +26,7 @@ This command requires the --accountId flag, which specifies the account to issue the query against. `, Example: `newrelic nrql query --accountId 12345678 --query 'SELECT count(*) FROM Transaction TIMESERIES'`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { result, err := client.NRClient.Nrdb.QueryWithContext(utils.SignalCtx, accountID, nrdb.NRQL(query)) if err != nil { @@ -44,6 +45,7 @@ var cmdHistory = &cobra.Command{ The history command will fetch a list of the most recent NRQL queries you executed. `, Example: `newrelic nrql query history`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { result, err := client.NRClient.Nrdb.QueryHistory() if err != nil { diff --git a/internal/reporting/command_junit.go b/internal/reporting/command_junit.go index e3b15ff08..39e5c587b 100644 --- a/internal/reporting/command_junit.go +++ b/internal/reporting/command_junit.go @@ -30,6 +30,7 @@ var cmdJUnit = &cobra.Command{ `, Example: `newrelic reporting junit --accountId 12345678 --path unit.xml`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { if configuration.GetActiveProfileString(configuration.InsightsInsertKey) == "" { log.Fatal("an Insights insert key is required, set one in your default profile or use the NEW_RELIC_INSIGHTS_INSERT_KEY environment variable") diff --git a/internal/workload/command_workload.go b/internal/workload/command_workload.go index d5af7bb28..91728163d 100644 --- a/internal/workload/command_workload.go +++ b/internal/workload/command_workload.go @@ -30,6 +30,7 @@ var cmdGet = &cobra.Command{ The get command retrieves a specific workload by its workload GUID. `, Example: `newrelic workload get --accountId 12345678 --guid MjUyMDUyOHxOUjF8V09SS0xPQUR8MTI4Myt`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { workload, err := client.NRClient.Entities.GetEntitiesWithContext(utils.SignalCtx, []entities.EntityGUID{entities.EntityGUID(guid)}) utils.LogIfFatal(err) @@ -46,6 +47,7 @@ var cmdList = &cobra.Command{ The list command retrieves the workloads for the given account ID. `, Example: `newrelic workload list --accountId 12345678`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { builder := entities.EntitySearchQueryBuilder{ Type: entities.EntitySearchQueryBuilderTypeTypes.WORKLOAD, @@ -76,6 +78,7 @@ IDs can optionally be provided to include entities from different sub-accounts t you also have access to. `, Example: `newrelic workload create --name 'Example workload' --accountId 12345678 --entitySearchQuery "name like 'Example application'"`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { createInput := workloads.WorkloadCreateInput{ Name: name, @@ -120,6 +123,7 @@ together with an OR. Multiple account scope IDs can optionally be provided to i entities from different sub-accounts that you also have access to. `, Example: `newrelic workload update --guid 'MjUyMDUyOHxBOE28QVBQTElDQVRDT058MjE1MDM3Nzk1' --name 'Updated workflow'`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { updateInput := workloads.WorkloadUpdateInput{ Name: name, @@ -162,6 +166,7 @@ If the name isn't specified, the name + ' copy' of the source workload is used t compose the new name. `, Example: `newrelic workload duplicate --guid 'MjUyMDUyOHxBOE28QVBQTElDQVRDT058MjE1MDM3Nzk1' --accountId 12345678 --name 'New Workload'`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { duplicateInput := workloads.WorkloadDuplicateInput{ Name: name, @@ -183,6 +188,7 @@ var cmdDelete = &cobra.Command{ The delete command accepts a workload's entity GUID. `, Example: `newrelic workload delete --guid 'MjUyMDUyOHxBOE28QVBQTElDQVRDT058MjE1MDM3Nzk1'`, + PreRun: client.RequireClient, Run: func(cmd *cobra.Command, args []string) { _, err := client.NRClient.Workloads.WorkloadDeleteWithContext(utils.SignalCtx, entities.EntityGUID(guid)) utils.LogIfFatal(err)