diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..bbe97d4
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,34 @@
+language: go
+
+go:
+- 1.9
+
+branches:
+ only:
+ - master
+ - /^v.*$/
+
+install:
+- go get -u github.com/golang/dep/cmd/dep
+
+script:
+- make deps
+- make test
+- make build
+
+
+before_deploy:
+- make release
+
+deploy:
+ provider: releases
+ api_key:
+ secure: 4jDPdpCqfV+sPgnw2/8tGASDtaomfSyjCEtGKB8rFHwjkZ2K/FJSyjIA0OrO0QmG/WidQVf8hyEmBBwk3uKHgMbASxYSP4AquUhzUkdtN9gmEQC0D8S1cZBGoWh0ymAts17TpWG4ledRSABGVrpJJ+8VL8mFj8HUxUEqDfqIh2KFqukjYDxL9NvPpbgcK3zJw9g91YCdVyrBZcFihYjE2+visQVRxmOHkNRhdxQ+LgUHJKNWwxJi1Y2GrCu2xJ/92GoT7VbNZw7xPYvLR6TKDMYKbsv4Lr0UNCFh3Adm68h005/kLKSVFuLnl+8s5KRIB5WvR6r/+u0BtkNsLxIKQIqJz82SDvW6/MF7RNtC7jquSS4kYebefwev7XDbUlzAX8VN3/rWi4z//6uMjRRKNuVvX6Tu6kXd5fGeU25mLGVQpSOLtZkckqXaBN7WrC62EMyTOBkccHLaMCZl+TdFGI9wz6gRZ3k0wzk4InvsUMpVK03LNWvHt4RGQwD+MKO1i7PglAMVb83ZWJ4a3PPGjQT8DHUmi48Il1verm1Uk5c8NtlfA6QSyiJtjmz3tUpkZ+rlM8rA/pWaypPHRs2bd8Z92MY+SR1Bxi3J0cD3r63YeK9uIwd7K6N6I5WZmwMOUCNaDhDT6bn96QXnG3nFQ+sKKfWCrOErhY+mNkDR01E=
+ file_glob: true
+ file: dist/*
+ skip_cleanup: true
+ on:
+ tags: true
+
+notifications:
+ email: false
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..420e6f2
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1 @@
+# Change Log
diff --git a/Gopkg.lock b/Gopkg.lock
new file mode 100644
index 0000000..ff96307
--- /dev/null
+++ b/Gopkg.lock
@@ -0,0 +1,162 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ name = "github.com/fsnotify/fsnotify"
+ packages = ["."]
+ revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
+ version = "v1.4.7"
+
+[[projects]]
+ name = "github.com/ghodss/yaml"
+ packages = ["."]
+ revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
+ version = "v1.0.0"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/google/go-querystring"
+ packages = ["query"]
+ revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/hashicorp/hcl"
+ packages = [
+ ".",
+ "hcl/ast",
+ "hcl/parser",
+ "hcl/printer",
+ "hcl/scanner",
+ "hcl/strconv",
+ "hcl/token",
+ "json/parser",
+ "json/scanner",
+ "json/token"
+ ]
+ revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
+
+[[projects]]
+ name = "github.com/inconshreveable/mousetrap"
+ packages = ["."]
+ revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
+ version = "v1.0"
+
+[[projects]]
+ name = "github.com/magiconair/properties"
+ packages = ["."]
+ revision = "c2353362d570a7bfa228149c62842019201cfb71"
+ version = "v1.8.0"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/mitchellh/go-homedir"
+ packages = ["."]
+ revision = "58046073cbffe2f25d425fe1331102f55cf719de"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/mitchellh/mapstructure"
+ packages = ["."]
+ revision = "f15292f7a699fcc1a38a80977f80a046874ba8ac"
+
+[[projects]]
+ name = "github.com/pelletier/go-toml"
+ packages = ["."]
+ revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
+ version = "v1.2.0"
+
+[[projects]]
+ name = "github.com/spf13/afero"
+ packages = [
+ ".",
+ "mem"
+ ]
+ revision = "787d034dfe70e44075ccc060d346146ef53270ad"
+ version = "v1.1.1"
+
+[[projects]]
+ name = "github.com/spf13/cast"
+ packages = ["."]
+ revision = "8965335b8c7107321228e3e3702cab9832751bac"
+ version = "v1.2.0"
+
+[[projects]]
+ name = "github.com/spf13/cobra"
+ packages = ["."]
+ revision = "ef82de70bb3f60c65fb8eebacbb2d122ef517385"
+ version = "v0.0.3"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/spf13/jwalterweatherman"
+ packages = ["."]
+ revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
+
+[[projects]]
+ name = "github.com/spf13/pflag"
+ packages = ["."]
+ revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
+ version = "v1.0.2"
+
+[[projects]]
+ name = "github.com/spf13/viper"
+ packages = ["."]
+ revision = "907c19d40d9a6c9bb55f040ff4ae45271a4754b9"
+ version = "v1.1.0"
+
+[[projects]]
+ name = "github.com/tidwall/gjson"
+ packages = ["."]
+ revision = "1e3f6aeaa5bad08d777ea7807b279a07885dd8b2"
+ version = "v1.1.3"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/tidwall/match"
+ packages = ["."]
+ revision = "1731857f09b1f38450e2c12409748407822dc6be"
+
+[[projects]]
+ branch = "master"
+ name = "github.com/tidwall/pretty"
+ packages = ["."]
+ revision = "65a9db5fad5105a89e17f38adcc9878685be6d78"
+
+[[projects]]
+ name = "github.com/tidwall/sjson"
+ packages = ["."]
+ revision = "6a22caf2fd45d5e2119bfc3717e984f15a7eb7ee"
+ version = "v1.0.0"
+
+[[projects]]
+ branch = "master"
+ name = "golang.org/x/sys"
+ packages = ["unix"]
+ revision = "98c5dad5d1a0e8a73845ecc8897d0bd56586511d"
+
+[[projects]]
+ name = "golang.org/x/text"
+ packages = [
+ "internal/gen",
+ "internal/triegen",
+ "internal/ucd",
+ "transform",
+ "unicode/cldr",
+ "unicode/norm"
+ ]
+ revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
+ version = "v0.3.0"
+
+[[projects]]
+ name = "gopkg.in/yaml.v2"
+ packages = ["."]
+ revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
+ version = "v2.2.1"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ inputs-digest = "6bb72eff73b811f9bc4aba2afecb0a2f5a2e48c875c417b2d9f7ef6118440412"
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
new file mode 100644
index 0000000..feaa078
--- /dev/null
+++ b/Gopkg.toml
@@ -0,0 +1,46 @@
+# Gopkg.toml example
+#
+# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
+# for detailed Gopkg.toml documentation.
+#
+# required = ["github.com/user/thing/cmd/thing"]
+# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
+#
+# [[constraint]]
+# name = "github.com/user/project"
+# version = "1.0.0"
+#
+# [[constraint]]
+# name = "github.com/user/project2"
+# branch = "dev"
+# source = "github.com/myfork/project2"
+#
+# [[override]]
+# name = "github.com/x/y"
+# version = "2.4.0"
+#
+# [prune]
+# non-go = false
+# go-tests = true
+# unused-packages = true
+
+
+[[constraint]]
+ name = "github.com/ghodss/yaml"
+ version = "1.0.0"
+
+[[constraint]]
+ branch = "master"
+ name = "github.com/mitchellh/go-homedir"
+
+[[constraint]]
+ name = "github.com/spf13/cobra"
+ version = "0.0.3"
+
+[[constraint]]
+ name = "github.com/spf13/viper"
+ version = "1.1.0"
+
+[prune]
+ go-tests = true
+ unused-packages = true
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..bd527a5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,41 @@
+VERSION := $(shell grep "version = " cmd/version.go | awk '{print $$4}' | sed 's/"//g')
+
+PLATFORMS := linux/amd64 darwin/amd64 windows/amd64
+temp = $(subst /, ,$@)
+os = $(word 1, $(temp))
+arch = $(word 2, $(temp))
+
+COMMONENVVAR = GOOS=$(shell uname -s | tr A-Z a-z) GOARCH=$(subst x86_64,amd64,$(patsubst i%86,386,$(shell uname -m)))
+BUILDENVVAR = CGO_ENABLED=0
+
+all: build
+
+deps:
+ git config --global url."git@github.com:".insteadOf "https://github.com/"
+ dep ensure
+
+test:
+ $(COMMONENVVAR) $(BUILDENVVAR) go test ./... -v
+
+build:
+ $(COMMONENVVAR) $(BUILDENVVAR) go vet ./...
+ $(COMMONENVVAR) $(BUILDENVVAR) go build -o nr *.go
+
+tag: # used in client side to trigger a travis deployment job
+ifndef VERSION
+ $(error VERSION is undefined - run using make tag VERSION=vX.Y.Z)
+endif
+ git tag $(VERSION)
+
+ # Check to make sure the tag isn't "-dirty".
+ if git describe --tags --dirty | grep dirty; \
+ then echo current git working tree is "dirty". Make sure you do not have any uncommitted changes ;false; fi
+
+ git push --tags
+
+$(PLATFORMS):
+ GOOS=$(os) GOARCH=$(arch) $(BUILDENVVAR) go build -o dist/nr-$(os)-$(arch) *.go
+
+release: $(PLATFORMS)
+
+.PHONY: all deps test build tag release $(PLATFORMS)
diff --git a/README.md b/README.md
index 45c77b5..4d003e1 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,253 @@
# newrelic-cli
+
New Relic CLI is a command line tool which is used to operate New Relic objects(Synthetic monitors, alert policies, conditions, account users etc). You can use it easily to list/get/create/delete these objects. It can be used to backup your New Relic configuration data and restore in the future. It is easy to be used other than calling different REST API endpoints.
+
+## Command
+
+Command | Subcommand | Resource | arguments | flag
+-- | -- | -- | -- | --
+nr | get | users | - |
+nr | get | user | <id> |
+nr | get | monitors | - |
+nr | get | monitor | <id> |
+nr | get | labels | - |
+nr | get | labelsmonitors | <category:label> |
+nr | get | alertspolicies | - |
+nr | get | alertsconditions | - |
+nr | get | alertschannels | - |
+nr | get | dashboards | - |
+nr | get | dashboard | <id> |
+nr | create | monitor | - | -f <monitor_sample.json>
+nr | create | alertspolicies | - | -f <alertspolicies_sample.json>
+nr | create | alertsconditions | - | -f <alertsconditions_sample.json>
+nr | create | alertschannels | - | -f <alertschannels_sample.json>
+nr | add | alertschannels | <id> <category:label> |
+nr | update | monitor | - | -f <monitor_sample.json>
+nr | update | alertspolicies | - | -f <alertspolicies_sample.json>
+nr | update | alertsconditions | - | -f <alertsconditions_sample.json>
+nr | update | alertschannels | - | -f <alertschannels_sample.json>
+nr | patch | monitor | - | -f <monitor_sample.json>
+nr | delete | monitor | <id> |
+nr | delete | alertspolicies | <id> |
+nr | delete | alertsconditions | <id> |
+nr | delete | alertschannels | <id> |
+nr | delete | labelsmonitors | <id> <category:label> |
+nr | insert | customevents | - | -f <custom_events.json>
-i <New Relic insert key>
-a <New Relic account ID>
+nr | backup | monitors | - | -d <backup_folder>
-r <result_file.log>
+nr | backup | alertsconditions | - | -d <backup_folder>
-r <result_file.log>
+nr | backup | dashboards | - | -d <backup_folder>
-r <result_file.log>
+nr | restore | monitors | - | -d <monitors_folder>
-f <monitor_filenames>
-F <file_contains_names>
-m [skip\\|override\\|clean]
-r <result_file.log>
+nr | restore | alertsconditions | - | -d <alertsconditions_folder>
-f <alertscondition_filenames>
-F <file_contains_names>
-m [skip\\|override\\|clean]
-r <result_file.log>
+nr | restore | dashboards | - | -d <dashboards_folder>
-f <dashboard_filenames>
-F <file_contains_names>
-m [skip\\|override\\|clean]
-r <result_file.log>
+
+## To start using nr CLI
+
+### Getting Started with the nr CLI (A quick sample to get all users in New Relic account)
+
+* __Set environment variable__ `NEW_RELIC_APIKEY`
+
+Define New Relic admin API key in environment by `export` cmd on Linux OS like this:
+
+`export NEW_RELIC_APIKEY=xxxx-xxxxxxx-xxxxx-xxxxxx`
+
+`xxxx-xxxxxxx-xxxxx-xxxxxx` is the New Relic admin API key. How to find the admin API key in your New Relic account, reference this doc, __Activate Admin user's API key__: [REST API keys](https://docs.newrelic.com/docs/apis/getting-started/intro-apis/access-rest-api-keys)
+
+
+
+* __Get all users info in current New Relic account__
+
+Use __nr get users__ command like this:
+```
+$ nr get users
+ID FirstName LastName Email Role
+2071178 Chris Ratcliffe chrisr@ca.ibm.com admin
+2000900 Jack Guan jguan@ca.ibm.com admin
+801314 Paul van Run pvanrun@ca.ibm.com admin
+770658 Thomas Schaeck schaeck@de.ibm.com owner
+2102902 Wei Huang wei.huang1@ibm.com admin
+```
+
+
+
Define the output format as JSON using `-o json` argument
+```
+$ nr get users -o json
+{
+ "users": [
+ {
+ "id": 2071178,
+ "first_name": "Chris",
+ "last_name": "Ratcliffe",
+ "email": "chrisr@ca.ibm.com",
+ "role": "admin"
+ },
+......
+```
+
+
+
Define the output format as JSON using `-o YAML` argument
+```
+$ nr get users -o yaml
+users:
+- email: chrisr@ca.ibm.com
+ first_name: Chris
+ id: 2071178
+ last_name: Ratcliffe
+ role: admin
+......
+```
+
+* __Use proxy__
+
+Can configure proxy if the target machine can not directly connect to newrelic.com
+
+`export NEW_RELIC_PROXY=http://:@:`
+
+Like:
+`export NEW_RELIC_PROXY=http://user1:password1@9.42.95.127:3128`
+
+
+* __Return codes__
+
+The nr CLI uses exit codes, which help with scripting and confirming that a command has run successfully. For example, after you run a nr CLI command, you can retrieve its return code by running echo $? (on Windows, echo %ERRORLEVEL%). If the return code is 0, the command was successful.
+
+__A sample to use `return code` in shell scripts for CI/CD pipeline__
+To restore monitors, we check if successful by the `return code`, if failed, it would output the monitor file names to the log file `fail-restore-monitors.log`(the file name you can customize by `-r` argument), we continue to retry to restore all monitors that failed, the monitor names were stored in `fail-restore-monitors.log` and we use `-F` argument to tell `nr` what monitors we want to retry, we also add a counter, if retry times exceed 3, it would end.
+
+__shell scripts to restore monitors with retry:__
+```
+#!/bin/bash
+
+noNRKey="No NEW_RELIC_APIKEY detected."
+noNRKey=${noNRKey}"\n\n"
+noNRKey=${noNRKey}"Please export New Relic API key."
+noNRKey=${noNRKey}"\n\n"
+noNRKey=${noNRKey}"Example:\n"
+noNRKey=${noNRKey}" export NEW_RELIC_APIKEY=xxx-xxxxx-xx"
+noNRKey=${noNRKey}"\n"
+if [ $NEW_RELIC_APIKEY"" == "" ];then
+ echo -e "${noNRKey}"
+ exit 1
+fi
+
+
+basepath=$(cd `dirname $0`; pwd)
+
+${basepath}/nr restore monitors -d ${basepath}/backup_monitors_folder -r fail-restore-monitors.log
+exitCode=$?""
+
+if [ $exitCode == "0" ];then
+ echo ""
+ echo "Success, restore end."
+ exit 0
+else
+ echo ""
+ echo "Some monitors to restore failed, begin to retry..."
+fi
+
+counter=0
+while [ $exitCode != "0" ]
+do
+ counter=`expr $counter + 1`
+
+ ${basepath}/nr restore monitors -F ${basepath}/fail-restore-monitors.log -r fail-restore-monitors.log
+ exitCode=$?""
+
+ if [ $exitCode != "0" ];then
+ echo ""
+ echo "Some monitors to restore failed in this retry: "$counter"."
+ if [ $counter -ge 3 ];then
+ echo ""
+ echo "Retry 3 times, restore end."
+ exit 1
+ fi
+ else
+ echo ""
+ echo "After retry, no failed, restore end."
+ exit 0
+ fi
+done
+```
+
+
+* __nr help command__
+
+The nr help command lists the nr CLI commands and a brief description of each. Passing the -h flag to any command lists detailed help, including any aliases. For example, to see detailed help for `nr get`, run:
+
+```
+$ nr get -h
+Display one or many NewRelic resources.
+
+Usage:
+ nr get [command]
+
+Available Commands:
+ alertschannels Display all alerts_channels.
+ alertsconditions Display alert conditions by alert id.
+ alertspolicies Display all alerts_policies.
+ labels Display all labels.
+ labelsmonitors Display monitros by label.
+ monitor Display a single monitor by id.
+ monitors Display all synthetics monitors.
+ user Display a single user by id.
+ users Display all users.
+
+Flags:
+ -h, --help help for get
+ -o, --output string Output format. table/json/yaml are supported (default "table")
+ -t, --type-condition string Alert condition type. Only used for 'alertsconditions' command. all|conditions|sythentics|ext|plugin|nrql are supported (default "all")
+```
+
+
for `nr get users`, run:
+
+```
+$ nr get users -h
+Display all users.
+
+Usage:
+ nr get users [flags]
+
+Examples:
+* nr get users
+* nr get users -o json
+* nr get users -o yaml
+* nr get users -i 2102902
+* nr get users -i 2102902,+801314
+* nr get users -e wei.huang1@ibm.com
+* nr get users -e ibm.com
+* nr get users -i 2102902 -e ibm.com
+
+Flags:
+ -e, --email string email to filter returned result. can't specify emails
+ -h, --help help for users
+ -i, --id string user id(s) to filter returned result. use ',+' to separate ids
+
+Global Flags:
+ -o, --output string Output format. table/json/yaml are supported (default "table")
+ -t, --type-condition string Alert condition type. Only used for 'alertsconditions' command. all|conditions|sythentics|ext|plugin|nrql are supported (default "all")
+```
+
+
+## To start developing nr CLI
+
+### Prerequisite
+
+* Golang 1.9 or 1.9+
+
+* Golang `dep`
+
Install `dep`:
+`go get -u github.com/golang/dep/cmd/dep`
+
+
+### Build newrelic-cli project
+
+* git clone `newrelic-cli`
+* Enter project root folder
+* Run `make deps`
+* Run `make build`
+
+
+### Cross compilation by using gox
+
+* Install `gox`
+* Enter project root folder
+* Run `gox -os "windows linux darwin" -arch "amd64"`
\ No newline at end of file
diff --git a/cmd/add/add.go b/cmd/add/add.go
new file mode 100644
index 0000000..81bff7a
--- /dev/null
+++ b/cmd/add/add.go
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package add
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// CreateCmd represents the create command
+var AddCmd = &cobra.Command{
+ Use: "add",
+ Short: "Add a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // CreateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/add/add_labelsmonitor.go b/cmd/add/add_labelsmonitor.go
new file mode 100644
index 0000000..8197b8f
--- /dev/null
+++ b/cmd/add/add_labelsmonitor.go
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package add
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strings"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var labelsmonitorsCmd = &cobra.Command{
+ Use: "labelsmonitors",
+ Short: "Add one lable to a specific monitor by monitor id.",
+ Aliases: []string{"m"},
+ Example: `nr add labelsmonitors
+ * nr add labelsmonitors xxx-xxxx-xxx Env:Staging`,
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 2 {
+ return fmt.Errorf("length of [flags] should be 2 instead of %d", len(args))
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+
+ monitorId := string(args[0])
+ label := string(args[1])
+ var monitorLabel *newrelic.MonitorLabel
+ monitorLabel = &newrelic.MonitorLabel{}
+ arr := strings.Split(label, ":")
+ monitorLabel.Category = &arr[0]
+ monitorLabel.Label = &arr[1]
+ err, returnValue := AddLabelToMonitor(monitorId, monitorLabel)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ os.Exit(1)
+ return
+ }
+
+ os.Exit(0)
+ },
+}
+
+func AddLabelToMonitor(monitorId string, monitorLabel *newrelic.MonitorLabel) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("labelSynthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_ADD_LABEL_MONITOR, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ resp, err := client.LabelsSynthetics.AddLabelToMonitor(context.Background(), monitorId, monitorLabel)
+ var label = *monitorLabel.Category + ":" + *monitorLabel.Label
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_ADD_LABEL_MONITOR, err, tracker.ERR_REST_CALL, "label: "+", monitor id: ")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.LabelsSynthetics, tracker.OPERATION_NAME_ADD_LABEL_MONITOR, resp.StatusCode, "label: "+", monitor id: ")
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Adding label '%s' to monitor '%s'\n", statusCode, label, monitorId)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_ADD_LABEL_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_ADD_LABEL_MONITOR, nil, nil, "")
+ return nil, ret
+}
+
+func init() {
+ AddCmd.AddCommand(labelsmonitorsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/backup/backup.go b/cmd/backup/backup.go
new file mode 100644
index 0000000..bab2c18
--- /dev/null
+++ b/cmd/backup/backup.go
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package backup
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// BackupCmd represents the update command
+var BackupCmd = &cobra.Command{
+ Use: "backup",
+ Short: "Backup a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // BackupCmd.PersistentFlags().String("foo", "", "A help for foo")
+ BackupCmd.PersistentFlags().StringP("dir", "d", "", "Folder name to backup.")
+ BackupCmd.MarkPersistentFlagRequired("dir")
+
+ BackupCmd.PersistentFlags().StringP("result-file-name", "r", "", "Result file name")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // UpdateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/backup/backup_alertsconditions.go b/cmd/backup/backup_alertsconditions.go
new file mode 100644
index 0000000..2e73551
--- /dev/null
+++ b/cmd/backup/backup_alertsconditions.go
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package backup
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/spf13/cobra"
+)
+
+type AlertPolicySet struct {
+ AlertsPolicy *newrelic.AlertsPolicy `json:"policy,omitempty"`
+ AlertsConditionList *newrelic.AlertsConditionList `json:"alerts_conditions,omitempty"`
+ AlertsChannels []*newrelic.AlertsChannel `json:"alerts_channels,omitempty"`
+}
+
+type AlertDependencies struct {
+ MonitorMap map[string]*newrelic.Monitor `json:"dependent_monitors,omitempty"`
+}
+
+type AlertBackup struct {
+ AlertPolicySetList []AlertPolicySet `json:"policies,omitempty"`
+ AlertDependencies *AlertDependencies `json:"dependencies,omitempty"`
+}
+
+type OneAlertBackup struct {
+ AlertPolicySet AlertPolicySet `json:"policy,omitempty"`
+ AlertDependencies *AlertDependencies `json:"dependencies,omitempty"`
+}
+
+var alertsconditionsCmd = &cobra.Command{
+ Use: "alertsconditions",
+ Short: "Backup alertsconditions to a directory.",
+ Example: "nr backup alertsconditions -d <",
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var backupFolder string
+ var err error
+ flags := cmd.Flags()
+ if flags.Lookup("dir") != nil {
+ backupFolder, err = cmd.Flags().GetString("dir")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if backupFolder == "" {
+ fmt.Println("Please give backup folder.")
+ os.Exit(1)
+ return
+ }
+ fileInfo, err := os.Stat(backupFolder)
+ if err != nil {
+ fmt.Println("The folder did not exist.")
+ os.Exit(1)
+ return
+ }
+ if fileInfo.IsDir() == false {
+ fmt.Println(backupFolder + "is not folder.")
+ os.Exit(1)
+ return
+ }
+ fmt.Printf("Start to backup all alertsconditions to '%s' folder\n", backupFolder)
+ } else {
+ os.Exit(1)
+ return
+ }
+
+ var resultFileName string = ""
+ if flags.Lookup("result-file-name") != nil {
+ resultFileName, err = cmd.Flags().GetString("result-file-name")
+ }
+ if resultFileName == "" {
+ resultFileName = "fail-backup-alert-conditions-file-list.log"
+ }
+
+ var backupPolicyMetaList tracker.BackupPolicyMetaList = tracker.BackupPolicyMetaList{}
+ var allBackupPolicyMeta []tracker.BackupPolicyMeta
+
+ var alertBackup AlertBackup = AlertBackup{}
+ var allAlertPolicySet []AlertPolicySet
+
+ alertBackup.AlertDependencies = &AlertDependencies{}
+ alertBackup.AlertDependencies.MonitorMap = map[string]*newrelic.Monitor{}
+
+ allChannelList, err, returnValue := get.GetAllAlertsChannels()
+ if returnValue.IsContinue == false {
+ exitBackupAlertConditionsWithError(returnValue, resultFileName)
+ return
+ }
+
+ allPolicyList, err, returnValue := get.GetAllAlertPolicies()
+ if returnValue.IsContinue == false {
+ exitBackupAlertConditionsWithError(returnValue, resultFileName)
+ return
+ }
+
+ for _, alertsPolicy := range allPolicyList.AlertsPolicies {
+ var backupPolicyMeta tracker.BackupPolicyMeta = tracker.BackupPolicyMeta{}
+
+ var alertPolicySet AlertPolicySet = AlertPolicySet{}
+
+ alertPolicySet.AlertsPolicy = alertsPolicy
+
+ var policyName = *alertsPolicy.Name
+ var ID = *alertsPolicy.ID
+ var fileNamePrefix = policyName + "-" + strconv.FormatInt(ID, 10)
+ var fileName = backupFolder + "/" + fileNamePrefix + ".alert-conditions.bak"
+ backupPolicyMeta.FileName = fileName
+ backupPolicyMeta.OperationStatus = "fail"
+ // backupPolicyMeta.PolicyName = policyName
+
+ var alertPolicyID = alertsPolicy.ID
+ conditionList, _, returnValue := get.GetAllConditionsByAlertPolicyID(*alertPolicyID)
+ if returnValue.IsContinue == false {
+ backupPolicyMeta.OperationStatus = "fail"
+ allBackupPolicyMeta = append(allBackupPolicyMeta, backupPolicyMeta)
+ continue
+ }
+ syntheticsArray := conditionList.AlertsSyntheticsConditions
+
+ // alertPolicySet.MonitorList := []*newrelic.Monitor
+ for _, monitor := range syntheticsArray {
+ if monitor.MonitorID != nil {
+ m, err, ret := get.GetMonitorByID(*monitor.MonitorID)
+ if err != nil {
+ fmt.Println(err)
+ }
+ if ret.IsContinue == false {
+ //ignore err
+ }
+ alertBackup.AlertDependencies.MonitorMap[*monitor.MonitorID] = m
+ }
+ }
+ alertPolicySet.AlertsConditionList = conditionList
+
+ //process channels
+ for _, channel := range allChannelList.AlertsChannels {
+ for _, policyID := range channel.Links.PolicyIDs {
+ if *policyID == *alertPolicyID {
+ alertPolicySet.AlertsChannels = append(alertPolicySet.AlertsChannels, channel)
+ }
+ }
+ }
+ ////
+
+ allAlertPolicySet = append(allAlertPolicySet, alertPolicySet)
+
+ backupPolicyMeta.OperationStatus = "success"
+ allBackupPolicyMeta = append(allBackupPolicyMeta, backupPolicyMeta)
+
+ }
+
+ alertBackup.AlertPolicySetList = allAlertPolicySet
+
+ backupPolicyMetaList.AllBackupPolicyMeta = allBackupPolicyMeta
+
+ fmt.Println()
+
+ for _, policy := range alertBackup.AlertPolicySetList {
+ var onePolicy OneAlertBackup = OneAlertBackup{}
+
+ var name = *policy.AlertsPolicy.Name
+ var ID = *policy.AlertsPolicy.ID
+ var fileNamePrefix = name + "-" + strconv.FormatInt(ID, 10)
+
+ onePolicy.AlertPolicySet = policy
+ onePolicy.AlertDependencies = alertBackup.AlertDependencies
+
+ fileContent, err := json.MarshalIndent(onePolicy, "", " ")
+ if err != nil {
+ fmt.Println(err)
+ }
+ var fileName = backupFolder + "/" + fileNamePrefix + ".alert-conditions.bak"
+ err = ioutil.WriteFile(fileName, fileContent, 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+ }
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+ tracker.PrintStatisticsInfo(backupPolicyMetaList)
+ fmt.Println()
+ writeFailBackupConditionsFileList(resultFileName, allBackupPolicyMeta)
+ fmt.Println()
+
+ os.Exit(0)
+ },
+}
+
+func writeFailBackupConditionsFileList(resultFileName string, backupPolicyMetaArray []tracker.BackupPolicyMeta) {
+ var totalCount = len(backupPolicyMetaArray)
+ var successCount int = 0
+ var failCount int = 0
+ var failInfoContent string = ""
+ for _, meta := range backupPolicyMetaArray {
+ if meta.OperationStatus == "fail" {
+ failCount++
+ failInfoContent = failInfoContent + meta.FileName + "\r\n"
+ } else {
+ successCount++
+ }
+ }
+ if failCount == 0 {
+ failInfoContent = "No failed"
+ }
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(failInfoContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Println()
+ fmt.Printf("Backup alert conditions, total: " + strconv.Itoa(totalCount) + ", success: " + strconv.Itoa(successCount) + ", fail: " + strconv.Itoa(failCount))
+}
+
+func exitBackupAlertConditionsWithError(returnValue tracker.ReturnValue, resultFileName string) {
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ fmt.Println(returnValue.Description)
+ fmt.Println()
+
+ fmt.Println("Failed to backup alert conditions, exit.")
+
+ var fileContent = "Backup failed."
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(fileContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ os.Exit(1)
+}
+
+func init() {
+ BackupCmd.AddCommand(alertsconditionsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+
+}
diff --git a/cmd/backup/backup_dashboards.go b/cmd/backup/backup_dashboards.go
new file mode 100644
index 0000000..ca5bbfa
--- /dev/null
+++ b/cmd/backup/backup_dashboards.go
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package backup
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/pretty"
+)
+
+var dashboardsCmd = &cobra.Command{
+ Use: "dashboards",
+ Short: "Backup dashboards to a directory.",
+ Example: "nr backup dashboards -d ",
+ Run: func(cmd *cobra.Command, args []string) {
+ var backupFolder string
+ var err error
+ flags := cmd.Flags()
+ if flags.Lookup("dir") != nil {
+ backupFolder, err = cmd.Flags().GetString("dir")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if backupFolder == "" {
+ fmt.Println("Please give backup folder.")
+ os.Exit(1)
+ return
+ }
+ fileInfo, err := os.Stat(backupFolder)
+ if err != nil {
+ fmt.Println("The folder did not exist.")
+ os.Exit(1)
+ return
+ }
+ if fileInfo.IsDir() == false {
+ fmt.Println(backupFolder + "is not folder.")
+ os.Exit(1)
+ return
+ }
+
+ fmt.Printf("Start to backup all dashboards to '%s' folder\n", backupFolder)
+ } else {
+ fmt.Println("Please give backup folder.")
+ os.Exit(1)
+ return
+ }
+
+ var resultFileName string = ""
+ if flags.Lookup("result-file-name") != nil {
+ resultFileName, err = cmd.Flags().GetString("result-file-name")
+ }
+ if resultFileName == "" {
+ resultFileName = "backup-dashboards-file-list.log"
+ }
+
+ var backupDashboardMetaList tracker.BackupDashboardMetaList = tracker.BackupDashboardMetaList{}
+ var allBackupDashboardMeta []tracker.BackupDashboardMeta
+
+ resultStr, err, returnValue := get.GetAllDashboards()
+ if err != nil {
+ fmt.Println(err)
+ exitBackupDashboardWithError(returnValue, resultFileName)
+ os.Exit(1)
+ return
+ }
+
+ if returnValue.IsContinue == false {
+ fmt.Println(returnValue.OriginalError)
+ exitBackupDashboardWithError(returnValue, resultFileName)
+ os.Exit(1)
+ return
+ }
+
+ dashboardArr := gjson.Parse(resultStr).Get("dashboards").Array()
+ for _, dashboard := range dashboardArr {
+ var backupDashboardMeta tracker.BackupDashboardMeta = tracker.BackupDashboardMeta{}
+
+ id := gjson.Parse(dashboard.String()).Get("id")
+ title := gjson.Parse(dashboard.String()).Get("title")
+ name := title.String()
+ var fileName = backupFolder + "/" + name + "-" + id.String() + ".dashboard.bak"
+
+ backupDashboardMeta.FileName = fileName
+ backupDashboardMeta.OperationStatus = "fail"
+
+ strDashboard, err, ret := get.GetDashboardByID(id.Int())
+ if err != nil {
+ fmt.Println(err)
+ continue
+ } else {
+ if ret.IsContinue == false {
+ fmt.Println(ret.OriginalError)
+ continue
+ }
+ jsonDashboard := pretty.Pretty([]byte(strDashboard))
+ // fmt.Printf("%s\n", string(jsonDashboard))
+
+ err = ioutil.WriteFile(fileName, jsonDashboard, 0666)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ backupDashboardMeta.OperationStatus = "success"
+ }
+ }
+ allBackupDashboardMeta = append(allBackupDashboardMeta, backupDashboardMeta)
+ }
+
+ backupDashboardMetaList.AllBackupDashboardMeta = allBackupDashboardMeta
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+ tracker.PrintStatisticsInfo(backupDashboardMetaList)
+ fmt.Println()
+ writeFailDashboardConditionsFileList(resultFileName, allBackupDashboardMeta)
+
+ os.Exit(0)
+ },
+}
+
+func writeFailDashboardConditionsFileList(resultFileName string, backupDashboardMetaArray []tracker.BackupDashboardMeta) {
+ var totalCount = len(backupDashboardMetaArray)
+ var successCount int = 0
+ var failCount int = 0
+ var failInfoContent string = ""
+ for _, meta := range backupDashboardMetaArray {
+ if meta.OperationStatus == "fail" {
+ failCount++
+ failInfoContent = failInfoContent + meta.FileName + "\r\n"
+ } else {
+ successCount++
+ }
+ }
+ if failCount == 0 {
+ failInfoContent = "No failed"
+ }
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(failInfoContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Println()
+ fmt.Printf("Backup dashboards, total: " + strconv.Itoa(totalCount) + ", success: " + strconv.Itoa(successCount) + ", fail: " + strconv.Itoa(failCount))
+}
+
+func exitBackupDashboardWithError(returnValue tracker.ReturnValue, resultFileName string) {
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ fmt.Println(returnValue.Description)
+ fmt.Println()
+
+ fmt.Println("Failed to backup dashboards, exit.")
+
+ var fileContent = "Backup failed."
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(fileContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ os.Exit(1)
+}
+
+func init() {
+ BackupCmd.AddCommand(dashboardsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+
+}
diff --git a/cmd/backup/backup_monitors.go b/cmd/backup/backup_monitors.go
new file mode 100644
index 0000000..1084c09
--- /dev/null
+++ b/cmd/backup/backup_monitors.go
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package backup
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/spf13/cobra"
+)
+
+var monitorsCmd = &cobra.Command{
+ Use: "monitors",
+ Short: "Backup monitors to a directory.",
+ Example: "nr backup monitors -d ",
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var backupFolder string
+ var err error
+ flags := cmd.Flags()
+ if flags.Lookup("dir") != nil {
+ backupFolder, err = cmd.Flags().GetString("dir")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if backupFolder == "" {
+ fmt.Println("Please give backup folder.")
+ os.Exit(1)
+ return
+ }
+ fileInfo, err := os.Stat(backupFolder)
+ if err != nil {
+ fmt.Println("The folder did not exist.")
+ os.Exit(1)
+ return
+ }
+ if fileInfo.IsDir() == false {
+ fmt.Println(backupFolder + "is not folder.")
+ os.Exit(1)
+ return
+ }
+
+ fmt.Printf("Start to backup all monitors to '%s' folder\n", backupFolder)
+ } else {
+ fmt.Println("Please give backup folder.")
+ os.Exit(1)
+ return
+ }
+
+ var resultFileName string = ""
+ if flags.Lookup("result-file-name") != nil {
+ resultFileName, err = cmd.Flags().GetString("result-file-name")
+ }
+ if resultFileName == "" {
+ resultFileName = "backup-monitors-file-list.log"
+ }
+
+ //
+ //get all monitors
+ monitorArray, err, returnValue := get.GetMonitors()
+ // if err != nil {
+ // fmt.Println(err)
+ // os.Exit(1)
+ // return
+ // }
+ if returnValue.IsContinue == false {
+ exitBackupMonitorWithError(returnValue, resultFileName)
+ return
+ }
+
+ //get all labels
+ lablesArray, err, returnValue := get.GetLabels()
+ if returnValue.IsContinue == false {
+ exitBackupMonitorWithError(returnValue, resultFileName)
+ return
+ }
+
+ for index, _ := range lablesArray.Labels {
+ l := lablesArray.Labels[index]
+ key := fmt.Sprintf("%v:%v", *l.Category, *l.Name)
+
+ labelSynthetics, err, returnValue := get.GetMonitorsByLabel(key)
+ if err != nil {
+ fmt.Println(err)
+ exitBackupMonitorWithError(returnValue, resultFileName)
+ return
+ }
+ if returnValue.IsContinue == false {
+ exitBackupMonitorWithError(returnValue, resultFileName)
+ return
+ }
+
+ monitorRefList := labelSynthetics.MonitorRefs
+ var refListLen = len(monitorRefList)
+
+ if refListLen > 0 {
+ //the label was added to monitors
+ for _, ref := range monitorRefList {
+ //get monitor id
+ monitorId := *ref.ID
+ for _, monitor := range monitorArray {
+ if monitorId == (*monitor.ID) {
+ labLen := len(monitor.Labels)
+ var newLabelList = make([]*string, (labLen + 1))
+ for i := 0; i < labLen; i++ {
+ newLabelList[i] = monitor.Labels[i]
+ }
+ newLabelList[labLen] = &key
+ monitor.Labels = newLabelList
+ }
+ }
+ }
+ }
+ }
+
+ // var backupFileNameStr string = ""
+
+ for _, monitor := range monitorArray {
+ var name = *monitor.Name
+ fileContent, err := json.MarshalIndent(monitor, "", " ")
+ if err != nil {
+ fmt.Println(err)
+ }
+ var fileName = backupFolder + "/" + name + ".monitor.bak"
+ err = ioutil.WriteFile(fileName, fileContent, 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+ // else {
+ // backupFileNameStr = backupFileNameStr + fileName + "\r\n"
+ // }
+
+ }
+
+ var fileContent = "No failed."
+ var fileLogName = resultFileName
+ err = ioutil.WriteFile(fileLogName, []byte(fileContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+ //print statistics monitor list
+ tracker.PrintBackupMonitorInfo(monitorArray)
+
+ fmt.Println()
+
+ fmt.Printf("Backup monitors done. folder: %v\n", backupFolder)
+ fmt.Println()
+ fmt.Printf("Backup monitor file names of failure status listed in this file: " + fileLogName)
+ fmt.Println()
+
+ os.Exit(0)
+ },
+}
+
+func exitBackupMonitorWithError(returnValue tracker.ReturnValue, resultFileName string) {
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ fmt.Println(returnValue.Description)
+ fmt.Println()
+
+ fmt.Println("Failed to backup monitors, exit.")
+
+ var fileContent = "Backup failed."
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(fileContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ os.Exit(1)
+}
+
+func init() {
+ BackupCmd.AddCommand(monitorsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+
+}
diff --git a/cmd/create/create.go b/cmd/create/create.go
new file mode 100644
index 0000000..19d03f8
--- /dev/null
+++ b/cmd/create/create.go
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package create
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// CreateCmd represents the create command
+var CreateCmd = &cobra.Command{
+ Use: "create",
+ Short: "Create a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands
+ CreateCmd.PersistentFlags().StringP("file", "f", "", "Filename to create resource with, yaml/json format is supported.")
+ CreateCmd.MarkPersistentFlagRequired("file")
+
+ CreateCmd.PersistentFlags().StringP("type-condition", "t", "default", "Alert condition type. Only used for 'alertsconditions' command. default|sythentics|ext|plugin|nrql are supported")
+
+ CreateCmd.PersistentFlags().StringP("output", "o", "json", "Output format. json/yaml are supported")
+
+ CreateCmd.PersistentFlags().StringP("script-file", "s", "", "Synthetics monitor javascript file name. Only used for 'monitor' command.")
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // CreateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/create/create_alertschannels.go b/cmd/create/create_alertschannels.go
new file mode 100644
index 0000000..cceab1a
--- /dev/null
+++ b/cmd/create/create_alertschannels.go
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package create
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+// alertschannelsCmd represents the alertschannels command
+var alertschannelsCmd = &cobra.Command{
+ Use: "alertschannels",
+ Short: "Create alerts_channels from a file.",
+ Aliases: []string{"ac", "alertchannel", "alertschannel"},
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var c = new(newrelic.AlertsChannelEntity)
+ err = decorder.Decode(c)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsChannelEntity), c) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ // start to create
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ _, resp, err := client.AlertsChannels.Create(context.Background(), c)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ } else {
+ fmt.Println(resp.Status)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ }
+ }
+ os.Exit(0)
+ },
+}
+
+func init() {
+ CreateCmd.AddCommand(alertschannelsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertschannelsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertschannelsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/create/create_alertsconditions.go b/cmd/create/create_alertsconditions.go
new file mode 100644
index 0000000..ee6a852
--- /dev/null
+++ b/cmd/create/create_alertsconditions.go
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package create
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var alertsconditionsCmd = &cobra.Command{
+ Use: "alertsconditions",
+ Short: "Create alerts_conditions from a file.",
+ Aliases: []string{"ac", "alertcondition", "alertscondition"},
+ Example: "nr create alertsconditions -f ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Printf("%v\n", err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ var err = fmt.Errorf("%q looks like a non-number.\n", args[0])
+ fmt.Printf("%v\n", err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+
+ alertPolicyID, _ := strconv.ParseInt(args[0], 10, 64)
+
+ flags := cmd.Flags()
+ var conditionType string
+ var errConditionType error
+ if flags.Lookup("type-condition") != nil {
+ conditionType, errConditionType = cmd.Flags().GetString("type-condition")
+ if errConditionType != nil {
+ fmt.Printf("error accessing flag %s for command %s: %v\n", "type-condition", cmd.Name(), errConditionType)
+ os.Exit(1)
+ return
+ }
+
+ var cat newrelic.ConditionCategory
+ var ac = new(newrelic.AlertsConditionEntity)
+
+ if conditionType == "plugins" {
+ cat = newrelic.ConditionPlugins
+ var ace = new(newrelic.AlertsPluginsConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for plugins type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsPluginsConditionEntity), ace) {
+ fmt.Printf("Error validating for plugins type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ ac.AlertsPluginsConditionEntity = ace
+
+ cat = newrelic.ConditionPlugins
+ } else if conditionType == "synthetics" {
+ var ace = new(newrelic.AlertsSyntheticsConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for synthetics type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsSyntheticsConditionEntity), ace) {
+ fmt.Printf("Error validating for synthetics type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ ac.AlertsSyntheticsConditionEntity = ace
+
+ cat = newrelic.ConditionSynthetics
+ } else if conditionType == "ext" {
+ var ace = new(newrelic.AlertsExternalServiceConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for ext type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsExternalServiceConditionEntity), ace) {
+ fmt.Printf("Error validating for ext type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ ac.AlertsExternalServiceConditionEntity = ace
+
+ cat = newrelic.ConditionExternalService
+ } else if conditionType == "nrql" {
+ var ace = new(newrelic.AlertsNRQLConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for nrql type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsNRQLConditionEntity), ace) {
+ fmt.Printf("Error validating for nrql type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ ac.AlertsNRQLConditionEntity = ace
+
+ cat = newrelic.ConditionNRQL
+ } else {
+ var ace = new(newrelic.AlertsDefaultConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for default type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsDefaultConditionEntity), ace) {
+ fmt.Printf("Error validating for default type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ ac.AlertsDefaultConditionEntity = ace
+
+ cat = newrelic.ConditionDefault
+ }
+ // start to create
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ _, resp, err := client.AlertsConditions.Create(context.Background(), cat, ac, alertPolicyID)
+ if err != nil {
+ fmt.Printf("Failed to create condition, %v\n", err)
+ } else {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Create alert conditions, alert policy id: '%d'\n", statusCode, alertPolicyID)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ }
+ }
+
+ }
+
+ os.Exit(0)
+ },
+}
+
+func CreateCondition(cat newrelic.ConditionCategory, ac *newrelic.AlertsConditionEntity, alertPolicyID int64) (*newrelic.AlertsConditionEntity, error, tracker.ReturnValue) {
+ // start to create
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_ALERT_CONDITIION, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ alertsConditionEntity, resp, err := client.AlertsConditions.Create(context.Background(), cat, ac, alertPolicyID)
+ if err != nil {
+ fmt.Printf("Failed to create alert condition, %v\n", err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_ALERT_CONDITIION, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.AlertsConditions, tracker.OPERATION_NAME_CREATE_ALERT_CONDITIION, resp.StatusCode, "")
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Create alert conditions, alert policy id: '%d'\n", statusCode, alertPolicyID)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_ALERT_CONDITIION, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CREATE_ALERT_CONDITIION, nil, nil, "")
+ return alertsConditionEntity, err, ret
+}
+
+func init() {
+ CreateCmd.AddCommand(alertsconditionsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertsconditionsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertsconditionsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/create/create_alertspolicies.go b/cmd/create/create_alertspolicies.go
new file mode 100644
index 0000000..d90be48
--- /dev/null
+++ b/cmd/create/create_alertspolicies.go
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package create
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var alertspoliciesCmd = &cobra.Command{
+ Use: "alertspolicies",
+ Short: "Create alerts_policies from a file.",
+ Aliases: []string{"ap", "alertpolicy", "alertspolicy"},
+ Example: "nr create alertspolicies -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var p = new(newrelic.AlertsPolicyEntity)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsPolicyEntity), p) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ // start to create
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ alertsPolicy, resp, err := client.AlertsPolicies.Create(context.Background(), p)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ } else {
+ fmt.Println(resp.Status)
+ }
+
+ printer, err := utils.NewPriter(cmd)
+
+ if err != nil {
+ fmt.Println(err)
+ return
+ }
+ printer.Print(alertsPolicy, os.Stdout)
+
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ }
+
+ os.Exit(0)
+ },
+}
+
+func CreateAlertsPolicyEntity(alertsPolcyEntity *newrelic.AlertsPolicyEntity) (*newrelic.AlertsPolicy, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_ALERT_POLICY, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ alertsPolicy, resp, err := client.AlertsPolicies.Create(context.Background(), alertsPolcyEntity)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.AlertsPolicies, tracker.OPERATION_NAME_CREATE_ALERT_POLICY, resp.StatusCode, "alert policy name:"+(*alertsPolcyEntity.AlertsPolicy.Name))
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Create alert policy '%s', alert policy id: '%d'\n", statusCode, *alertsPolicy.AlertsPolicy.Name, *alertsPolicy.AlertsPolicy.ID)
+ if resp.StatusCode >= 400 {
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_ALERT_POLICY, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CREATE_ALERT_POLICY, nil, nil, "")
+ return alertsPolicy.AlertsPolicy, err, ret
+}
+
+func CreateAlertsPolicy(alertsPolcy *newrelic.AlertsPolicy) (*newrelic.AlertsPolicy, error, tracker.ReturnValue) {
+ var alertsPolcyEntity *newrelic.AlertsPolicyEntity = &newrelic.AlertsPolicyEntity{}
+ alertsPolcyEntity.AlertsPolicy = alertsPolcy
+ return CreateAlertsPolicyEntity(alertsPolcyEntity)
+}
+
+func init() {
+ CreateCmd.AddCommand(alertspoliciesCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/create/create_dashboard.go b/cmd/create/create_dashboard.go
new file mode 100644
index 0000000..c60e622
--- /dev/null
+++ b/cmd/create/create_dashboard.go
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package create
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+)
+
+// dashboardCmd represents the dashboard command
+var dashboardCmd = &cobra.Command{
+ Use: "dashboard",
+ Short: "Create dashboard from a json file.",
+ Run: func(cmd *cobra.Command, args []string) {
+ fileName, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ bytes, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ fmt.Print(err)
+ os.Exit(1)
+ return
+ }
+ fileContent := string(bytes)
+ if !gjson.Valid(fileContent) {
+ fmt.Printf("Incorrect JSON format: %v.\n", errors.New("invalid json"))
+ os.Exit(1)
+ return
+ }
+ // start to create
+ retMsg, err, ret := CreateDashboard(fileContent)
+ fmt.Printf("response message: %s\n", retMsg)
+ if err != nil {
+ fmt.Print(err)
+ os.Exit(1)
+ return
+ }
+ if ret.IsContinue == false {
+ fmt.Print(ret.OriginalError)
+ os.Exit(1)
+ return
+ }
+
+ os.Exit(0)
+ },
+}
+
+func CreateDashboard(dashboard string) (string, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_DASHBOARD, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return "", err, ret
+ }
+ title := gjson.Parse(dashboard).Get("dashboard.title").String()
+
+ resp, bytes, err := client.Dashboards.Create(context.Background(), dashboard)
+
+ var retMsg string
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_DASHBOARD, err, tracker.ERR_REST_CALL, "")
+ return "", err, ret
+ } else {
+ retMsg = string(bytes)
+ tracker.AppendRESTCallResult(client.Dashboards, tracker.OPERATION_NAME_CREATE_DASHBOARD, resp.StatusCode, "dashboard title:"+title)
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Create dashboard '%s''\n", statusCode, title)
+ if resp.StatusCode >= 400 {
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_DASHBOARD, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, retMsg)
+ return retMsg, err, ret
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CREATE_DASHBOARD, nil, nil, "")
+ return retMsg, err, ret
+}
+
+func init() {
+ CreateCmd.AddCommand(dashboardCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertschannelsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertschannelsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/create/create_monitor.go b/cmd/create/create_monitor.go
new file mode 100644
index 0000000..cff1426
--- /dev/null
+++ b/cmd/create/create_monitor.go
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package create
+
+import (
+ "context"
+ "encoding/base64"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strings"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/cmd/add"
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var monitorCmd = &cobra.Command{
+ Use: "monitor",
+ Short: "Create monitor from a file.",
+ Example: "nr create monitor -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var p = new(newrelic.Monitor)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.Monitor), p) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ // start to create
+
+ var scriptTextEncoded *newrelic.Script
+ scriptTextEncoded = &newrelic.Script{}
+
+ if *p.Type == "SCRIPT_BROWSER" || *p.Type == "SCRIPT_API" {
+
+ flags := cmd.Flags()
+ if flags.Lookup("script-file") != nil {
+ scriptFileName, err := cmd.Flags().GetString("script-file")
+ if err != nil {
+ fmt.Printf("error accessing flag %s for command %s: %v\n", "script-file", cmd.Name(), err)
+ os.Exit(1)
+ return
+ }
+
+ if scriptFileName != "" {
+ sf, err := os.Open(scriptFileName)
+ defer sf.Close()
+ if err != nil {
+ fmt.Printf("Unable to open monitor script file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ byteArr, err := ioutil.ReadAll(sf)
+ sfContentEncoded := base64.StdEncoding.EncodeToString(byteArr)
+ scriptTextEncoded.ScriptText = &sfContentEncoded
+ } else {
+ scriptTextEncoded = p.Script
+ }
+ } else {
+ scriptTextEncoded = p.Script
+ }
+ }
+
+ _, err, returnValue := CreateMonitor(p, scriptTextEncoded)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ os.Exit(1)
+ return
+ }
+
+ os.Exit(0)
+ },
+}
+
+func CreateMonitor(p *newrelic.Monitor, scriptTextEncoded *newrelic.Script) (string, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_MONITOR, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return "", err, ret
+ }
+
+ p.ID = nil
+
+ createdMonitor, resp, err := client.SyntheticsMonitors.Create(context.Background(), p)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_MONITOR, err, tracker.ERR_REST_CALL, "")
+ return "", err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_CREATE_MONITOR, resp.StatusCode, "monitor name :"+(*p.Name))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Creating monitor '%s'\n", statusCode, *createdMonitor.Name)
+ var ret tracker.ReturnValue
+ if resp.StatusCode == 400 {
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_CREATE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_400, "")
+ } else {
+ ret = tracker.ToReturnValue(false, tracker.OPERATION_NAME_CREATE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ }
+
+ return "", err, ret
+ }
+
+ }
+
+ if *p.Type == "SCRIPT_BROWSER" || *p.Type == "SCRIPT_API" {
+ if scriptTextEncoded != nil && scriptTextEncoded.ScriptText != nil {
+ id := *createdMonitor.ID
+ resp, err := client.SyntheticsScript.UpdateByID(context.Background(), scriptTextEncoded, id)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR_SCRIPT, err, tracker.ERR_REST_CALL, "")
+ return id, err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_UPDATE_MONITOR_SCRIPT, resp.StatusCode, "monitor name :"+(*p.Name))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update script to monitor '%s', monitor id: '%s'\n", statusCode, *createdMonitor.Name, id)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR_SCRIPT, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return "", err, ret
+ }
+ }
+ }
+ }
+
+ //add labels
+ var labelsLen = len(p.Labels)
+ if labelsLen > 0 {
+ for _, label := range p.Labels {
+ id := createdMonitor.ID
+ var monitorLabel *newrelic.MonitorLabel
+ monitorLabel = &newrelic.MonitorLabel{}
+ arr := strings.Split(*label, ":")
+ monitorLabel.Category = &arr[0]
+ monitorLabel.Label = &arr[1]
+ err, returnValue := add.AddLabelToMonitor(*id, monitorLabel)
+ // if err != nil {
+ // fmt.Println(err)
+ // return *id, "failed to add labels to monitor", err
+ // }
+ if returnValue.IsContinue == false {
+ return "", err, returnValue
+ }
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CREATE_MONITOR, nil, nil, "")
+
+ return *createdMonitor.ID, err, ret
+}
+
+func init() {
+ CreateCmd.AddCommand(monitorCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete.go b/cmd/delete/delete.go
new file mode 100644
index 0000000..45ae503
--- /dev/null
+++ b/cmd/delete/delete.go
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// DeleteCmd represents the delete/delete command
+var DeleteCmd = &cobra.Command{
+ Use: "delete",
+ Short: "Delete a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ DeleteCmd.PersistentFlags().StringP("type-condition", "t", "default", "Alert condition type. Only used for 'alertsconditions' command. default|sythentics|ext|plugin|nrql are supported")
+
+ DeleteCmd.PersistentFlags().StringP("output", "o", "json", "Output format. json/yaml are supported")
+ // DeleteCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // DeleteCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete_alertschannels.go b/cmd/delete/delete_alertschannels.go
new file mode 100644
index 0000000..726fb0c
--- /dev/null
+++ b/cmd/delete/delete_alertschannels.go
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var alertschannelsCmd = &cobra.Command{
+ Use: "alertschannels",
+ Short: "Delete alerts_channel by id.",
+ Aliases: []string{"ac", "alertchannel", "alertschannel"},
+ Example: "nr delete alertschannels ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ var err = fmt.Errorf("%q looks like a non-number.\n", args[0])
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ id, _ := strconv.ParseInt(args[0], 10, 64)
+ resp, err := client.AlertsChannels.DeleteByID(context.Background(), id)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.Status)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func init() {
+ DeleteCmd.AddCommand(alertschannelsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertschannelsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertschannelsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete_alertsconditions.go b/cmd/delete/delete_alertsconditions.go
new file mode 100644
index 0000000..6e73378
--- /dev/null
+++ b/cmd/delete/delete_alertsconditions.go
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var alertsconditionsCmd = &cobra.Command{
+ Use: "alertsconditions",
+ Short: "Delete alerts_conditions by id.",
+ Aliases: []string{"ac", "alertcondition", "alertscondition"},
+ Example: "nr delete alertsconditions ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ var err = fmt.Errorf("%q looks like a non-number.\n", args[0])
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+
+ conditionPolicyID, _ := strconv.ParseInt(args[0], 10, 64)
+
+ flags := cmd.Flags()
+ var conditionType string
+ var errConditionType error
+ if flags.Lookup("type-condition") != nil {
+ conditionType, errConditionType = cmd.Flags().GetString("type-condition")
+ if errConditionType != nil {
+ fmt.Printf("error accessing flag %s for command %s: %v\n", "type-condition", cmd.Name(), errConditionType)
+ os.Exit(1)
+ return
+ }
+
+ var cat newrelic.ConditionCategory
+ if conditionType == "plugins" {
+ cat = newrelic.ConditionPlugins
+ } else if conditionType == "synthetics" {
+ cat = newrelic.ConditionSynthetics
+ } else if conditionType == "ext" {
+ cat = newrelic.ConditionExternalService
+ } else if conditionType == "nrql" {
+ cat = newrelic.ConditionNRQL
+ } else {
+ cat = newrelic.ConditionDefault
+ }
+ // start to delete
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ resp, err := client.AlertsConditions.DeleteByID(context.Background(), cat, conditionPolicyID)
+ if err != nil {
+ fmt.Printf("Failed to delete condition, %v\n", err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.Status)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+ } else {
+ fmt.Println("Can not find type-condition argument.")
+ os.Exit(1)
+ return
+ }
+
+ os.Exit(0)
+ },
+}
+
+func DeleteCondition(cat newrelic.ConditionCategory, conditionPolicyID int64) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_ALERT_CONDITION, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ resp, err := client.AlertsConditions.DeleteByID(context.Background(), cat, conditionPolicyID)
+ if err != nil {
+ fmt.Printf("Failed to delete condition, %v\n", err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_ALERT_CONDITION, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.AlertsConditions, tracker.OPERATION_NAME_DELETE_ALERT_CONDITION, resp.StatusCode, "monitor id: "+strconv.FormatInt(conditionPolicyID, 10))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Remove alert condition id '%d'\n", statusCode, conditionPolicyID)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_ALERT_CONDITION, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_DELETE_ALERT_CONDITION, nil, nil, "")
+ return nil, ret
+}
+
+func init() {
+ DeleteCmd.AddCommand(alertsconditionsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertsconditionsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertsconditionsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete_alertspolicies.go b/cmd/delete/delete_alertspolicies.go
new file mode 100644
index 0000000..40fc5de
--- /dev/null
+++ b/cmd/delete/delete_alertspolicies.go
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var alertspoliciesCmd = &cobra.Command{
+ Use: "alertspolicies",
+ Short: "Delete alerts_policy by id.",
+ Aliases: []string{"ap", "alertpolicy", "alertspolicy"},
+ Example: "nr delete alertspolicies ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ return fmt.Errorf("%q looks like a non-number.\n", args[0])
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ id, _ := strconv.ParseInt(args[0], 10, 64)
+ resp, err := client.AlertsPolicies.DeleteByID(context.Background(), id)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.Status)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func DeletePolicyByID(alertPolicyID int64) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_ALERT_POLICY_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ resp, err := client.AlertsPolicies.DeleteByID(context.Background(), alertPolicyID)
+
+ if err != nil {
+ fmt.Printf("Failed to delete alert policy, %v\n", err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_ALERT_POLICY_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.AlertsConditions, tracker.OPERATION_NAME_DELETE_ALERT_POLICY_BY_ID, resp.StatusCode, "alert policy id:"+strconv.FormatInt(alertPolicyID, 10))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("response status code: %d. Remove alert condition id '%d'\n", statusCode, alertPolicyID)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_ALERT_POLICY_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_DELETE_ALERT_POLICY_BY_ID, nil, nil, "")
+ return nil, ret
+}
+
+func DeletePolicyByName(alertPolicyName string) (error, tracker.ReturnValue) {
+ list, err, ret := get.GetAllAlertPolicies()
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ for _, policy := range list.AlertsPolicies {
+ if *policy.Name == alertPolicyName {
+ err, ret := DeletePolicyByID(*policy.ID)
+ if err != nil {
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ }
+ }
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_DELETE_ALERT_POLICY_BY_NAME, nil, nil, "")
+ return nil, ret
+}
+
+func init() {
+ DeleteCmd.AddCommand(alertspoliciesCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete_dashboard.go b/cmd/delete/delete_dashboard.go
new file mode 100644
index 0000000..8475598
--- /dev/null
+++ b/cmd/delete/delete_dashboard.go
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+)
+
+var dashboardCmd = &cobra.Command{
+ Use: "dashboard",
+ Short: "Delete one dashboard by id.",
+ Aliases: []string{"m"},
+ Example: "nr delete dashboard ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ id, _ := strconv.ParseInt(args[0], 10, 64)
+ resp, _, err := client.Dashboards.DeleteByID(context.Background(), id)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.StatusCode)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func DeleteDashboardByID(id int64) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_DASHBOARD_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ resp, bytes, err := client.Dashboards.DeleteByID(context.Background(), id)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_DASHBOARD_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ retMsg := string(bytes)
+ tracker.AppendRESTCallResult(client.Dashboards, tracker.OPERATION_NAME_DELETE_DASHBOARD_BY_ID, resp.StatusCode, "dashboard id: "+strconv.FormatInt(id, 10))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Remove dashboard id '%d'\n", statusCode, id)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_DASHBOARD_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, retMsg)
+ return err, ret
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_DELETE_DASHBOARD_BY_ID, nil, nil, "")
+ return nil, ret
+}
+
+func DeleteByDashboardTitle(title string) (error, tracker.ReturnValue) {
+ resultStr, err, ret := get.GetAllDashboards()
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ } else {
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ dashboardArr := gjson.Parse(resultStr).Get("dashboards").Array()
+ for _, existDashboard := range dashboardArr {
+ t := gjson.Parse(existDashboard.String()).Get("title").String()
+ if t == title {
+ id := gjson.Parse(existDashboard.String()).Get("id")
+ dashboardId, _ := strconv.ParseInt(id.String(), 10, 64)
+ err, ret := DeleteDashboardByID(dashboardId)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ } else {
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ return err, ret
+ }
+ }
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_DASHBOARD_BY_NAME, nil, nil, "")
+ return err, ret
+}
+
+func init() {
+ DeleteCmd.AddCommand(dashboardCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete_labelsmonitor.go b/cmd/delete/delete_labelsmonitor.go
new file mode 100644
index 0000000..5ff5cc5
--- /dev/null
+++ b/cmd/delete/delete_labelsmonitor.go
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var labelsmonitorsCmd = &cobra.Command{
+ Use: "labelsmonitors",
+ Short: "Delete one label from a specific monitor by monitor id.",
+ Aliases: []string{"m"},
+ Example: `nr delete labelsmonitors
+ * nr delete labelsmonitors xxx-xxxx-xxx Category:Label
+ * nr delete labelsmonitors xxx-xxxx-xxx Env:Staging`,
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 2 {
+ var err = fmt.Errorf("length of [flags] should be 2 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ monitorId := string(args[0])
+ label := string(args[1])
+ err, returnValue := DeleteLabelFromMonitor(monitorId, label)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ os.Exit(1)
+ return
+ }
+
+ os.Exit(0)
+ },
+}
+
+func DeleteLabelFromMonitor(monitorId string, label string) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("labelSynthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_LABEL_FROM_MONITOR, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ resp, err := client.LabelsSynthetics.DeleteLabelFromMonitor(context.Background(), monitorId, label)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_LABEL_FROM_MONITOR, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_DELETE_LABEL_FROM_MONITOR, resp.StatusCode, "label:"+label+",monitor id:"+monitorId)
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Remove label '%s' to monitor '%s'\n", statusCode, label, monitorId)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_LABEL_FROM_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_DELETE_LABEL_FROM_MONITOR, nil, nil, "")
+ return nil, ret
+}
+
+func init() {
+ DeleteCmd.AddCommand(labelsmonitorsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/delete/delete_monitor.go b/cmd/delete/delete_monitor.go
new file mode 100644
index 0000000..955b056
--- /dev/null
+++ b/cmd/delete/delete_monitor.go
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package delete
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var monitorCmd = &cobra.Command{
+ Use: "monitor",
+ Short: "Delete one synthetics monitor by id.",
+ Aliases: []string{"m"},
+ Example: "nr delete monitor ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ id := string(args[0])
+ resp, err := client.SyntheticsMonitors.DeleteByID(context.Background(), &id)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.StatusCode)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func DeleteMonitorByID(id string) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_MONITOR, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ resp, err := client.SyntheticsMonitors.DeleteByID(context.Background(), &id)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_MONITOR, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_DELETE_MONITOR, resp.StatusCode, "monitor id: "+id)
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Remove monitor id '%s'\n", statusCode, id)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_DELETE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_DELETE_MONITOR, nil, nil, "")
+ return nil, ret
+}
+
+func init() {
+ DeleteCmd.AddCommand(monitorCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/get/get.go b/cmd/get/get.go
new file mode 100644
index 0000000..20c6221
--- /dev/null
+++ b/cmd/get/get.go
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// GetCmd represents the get command
+var GetCmd = &cobra.Command{
+ Use: "get",
+ Short: "Display one or many NewRelic resources.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // GetCmd.PersistentFlags().String("foo", "", "A help for foo")
+ GetCmd.PersistentFlags().StringP("output", "o", "table", "Output format. table/json/yaml are supported")
+
+ GetCmd.PersistentFlags().StringP("type-condition", "t", "all", "Alert condition type. Only used for 'alertsconditions' command. all|conditions|sythentics|ext|plugin|nrql are supported")
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // GetCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/get/get_alertschannels.go b/cmd/get/get_alertschannels.go
new file mode 100644
index 0000000..00e4cff
--- /dev/null
+++ b/cmd/get/get_alertschannels.go
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var alertschannelsCmd = &cobra.Command{
+ Use: "alertschannels",
+ Short: "Display all alerts_channels.",
+ Aliases: []string{"ac", "alertchannel", "alertschannel"},
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ alertsChannelList, resp, err := client.AlertsChannels.ListAll(context.Background(), nil)
+ if err != nil || resp.StatusCode >= 400 {
+ fmt.Printf("%v:%v", resp.Status, err)
+ os.Exit(1)
+ return
+ }
+ printer, err := utils.NewPriter(cmd)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(alertsChannelList, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetAllAlertsChannels() (*newrelic.AlertsChannelList, error, tracker.ReturnValue) {
+ var opt *newrelic.AlertsChannelListOptions = &newrelic.AlertsChannelListOptions{}
+
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_ALERT_CHANNELS, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+
+ var allChannelList *newrelic.AlertsChannelList = &newrelic.AlertsChannelList{}
+
+ var pageCount = 1
+ for {
+ opt.Page = pageCount
+ alertsChannelList, resp, err := client.AlertsChannels.ListAll(context.Background(), opt)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_ALERT_CHANNELS, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.AlertsChannels, tracker.OPERATION_NAME_GET_ALERT_CHANNELS, resp.StatusCode, "pageCount:"+strconv.Itoa(pageCount))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get alert channels, pageCount '%d'\n", statusCode, pageCount)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_ALERT_CHANNELS, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+
+ var channelListLen = len(alertsChannelList.AlertsChannels)
+ if channelListLen == 0 {
+ break
+ } else {
+ allChannelList.AlertsChannels = utils.MergeAlertChannelList(allChannelList.AlertsChannels, alertsChannelList.AlertsChannels)
+ pageCount++
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_ALERT_CHANNELS, nil, nil, "")
+
+ return allChannelList, err, ret
+}
+
+func IsChannelNameExists(channelName string) (bool, *newrelic.AlertsChannel, error, tracker.ReturnValue) {
+ list, err, returnValue := GetAllAlertsChannels()
+ if returnValue.IsContinue == false {
+ return false, nil, err, returnValue
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CHECK_ALERT_CHANNEL_NAME_EXISTS, nil, nil, "")
+ for _, channel := range list.AlertsChannels {
+ if *channel.Name == channelName {
+ return true, channel, nil, ret
+ }
+ }
+ return false, nil, err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(alertschannelsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertschannelsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertschannelsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/get/get_alertsconditions.go b/cmd/get/get_alertsconditions.go
new file mode 100644
index 0000000..050c7a9
--- /dev/null
+++ b/cmd/get/get_alertsconditions.go
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var alertsconditionsCmd = &cobra.Command{
+ Use: "alertsconditions",
+ Short: "Display alert conditions by alert id.",
+ Aliases: []string{"ac", "alertcondition", "alertscondition"},
+ Example: "nr get alertsconditions -o json",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ var err = fmt.Errorf("%q looks like a non-number.\n", args[0])
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ id, _ := strconv.ParseInt(args[0], 10, 64)
+ var conditionsOptions *newrelic.AlertsConditionsOptions
+ conditionsOptions = new(newrelic.AlertsConditionsOptions)
+ conditionsOptions.PolicyIDOptions = strconv.FormatInt(id, 10)
+
+ var alertsConditionList *newrelic.AlertsConditionList
+
+ flags := cmd.Flags()
+
+ var conditionType string
+ var errConditionType error
+ if flags.Lookup("type-condition") != nil {
+ conditionType, errConditionType = cmd.Flags().GetString("type-condition")
+ if errConditionType != nil {
+ fmt.Printf("error accessing flag %s for command %s: %v\n", "type-condition", cmd.Name(), errConditionType)
+ os.Exit(1)
+ return
+ }
+ if conditionType == "plugins" || conditionType == "synthetics" || conditionType == "ext" || conditionType == "nrql" || conditionType == "conditions" {
+ var cat newrelic.ConditionCategory
+ switch conditionType {
+ case "plugins":
+ cat = newrelic.ConditionPlugins
+ case "synthetics":
+ cat = newrelic.ConditionSynthetics
+ case "ext":
+ cat = newrelic.ConditionExternalService
+ case "nrql":
+ cat = newrelic.ConditionNRQL
+ default:
+ cat = newrelic.ConditionDefault
+ }
+ list, resp, err := client.AlertsConditions.List(context.Background(), conditionsOptions, cat)
+ if err != nil || resp.StatusCode >= 400 {
+ fmt.Printf("%v\n", err)
+ os.Exit(1)
+ return
+ }
+ alertsConditionList = list
+ } else {
+ list, err := client.AlertsConditions.ListAll(context.Background(), conditionsOptions)
+ if err != nil {
+ fmt.Printf("%v\n", err)
+ os.Exit(1)
+ return
+ }
+ alertsConditionList = list
+ }
+ } else {
+ list, err := client.AlertsConditions.ListAll(context.Background(), conditionsOptions)
+ if err != nil {
+ fmt.Printf("%v", err)
+ os.Exit(1)
+ return
+ }
+ alertsConditionList = list
+ }
+
+ if err != nil {
+ fmt.Printf("%v\n", err)
+ os.Exit(1)
+ return
+ }
+ printer, err := utils.NewPriter(cmd)
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(alertsConditionList, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetAllConditionsByAlertPolicyID(id int64) (*newrelic.AlertsConditionList, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+
+ var allList *newrelic.AlertsConditionList = &newrelic.AlertsConditionList{}
+ allList.AlertsDefaultConditionList = &newrelic.AlertsDefaultConditionList{}
+ allList.AlertsExternalServiceConditionList = &newrelic.AlertsExternalServiceConditionList{}
+ allList.AlertsNRQLConditionList = &newrelic.AlertsNRQLConditionList{}
+ allList.AlertsPluginsConditionList = &newrelic.AlertsPluginsConditionList{}
+ allList.AlertsSyntheticsConditionList = &newrelic.AlertsSyntheticsConditionList{}
+
+ var conditionsOptions *newrelic.AlertsConditionsOptions
+ conditionsOptions = new(newrelic.AlertsConditionsOptions)
+ conditionsOptions.PolicyIDOptions = strconv.FormatInt(id, 10)
+
+ var pageCount = 1
+
+ for {
+ conditionsOptions.Page = pageCount
+
+ list, err := client.AlertsConditions.ListAll(context.Background(), conditionsOptions)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ var defaultConditionsLen = len(list.AlertsDefaultConditions)
+ var externalServiceConditionsLen = len(list.AlertsExternalServiceConditions)
+ var nrqlConditionsLen = len(list.AlertsNRQLConditions)
+ var pluginsConditionsLen = len(list.AlertsPluginsConditions)
+ var syntheticsConditionsLen = len(list.AlertsSyntheticsConditions)
+
+ if defaultConditionsLen == 0 && externalServiceConditionsLen == 0 && nrqlConditionsLen == 0 && pluginsConditionsLen == 0 && syntheticsConditionsLen == 0 {
+ break
+ } else {
+ //merge conditions list
+ allList = utils.MergeAlertConditionList(allList, list)
+ pageCount++
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, nil, nil, "")
+
+ return allList, err, ret
+}
+
+func GetConditionsByAlertPolicyIDAndConditionType(id int64, cat newrelic.ConditionCategory) (*newrelic.AlertsConditionList, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ var alertsConditionList *newrelic.AlertsConditionList = &newrelic.AlertsConditionList{}
+ alertsConditionList.AlertsDefaultConditionList = &newrelic.AlertsDefaultConditionList{}
+ alertsConditionList.AlertsExternalServiceConditionList = &newrelic.AlertsExternalServiceConditionList{}
+ alertsConditionList.AlertsNRQLConditionList = &newrelic.AlertsNRQLConditionList{}
+ alertsConditionList.AlertsPluginsConditionList = &newrelic.AlertsPluginsConditionList{}
+ alertsConditionList.AlertsSyntheticsConditionList = &newrelic.AlertsSyntheticsConditionList{}
+
+ var conditionsOptions *newrelic.AlertsConditionsOptions
+ conditionsOptions = new(newrelic.AlertsConditionsOptions)
+ conditionsOptions.PolicyIDOptions = strconv.FormatInt(id, 10)
+
+ var pageCount = 1
+
+ for {
+ conditionsOptions.Page = pageCount
+
+ list, resp, err := client.AlertsConditions.List(context.Background(), conditionsOptions, cat)
+ if err != nil {
+ fmt.Printf("%v\n", err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.AlertsConditions, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, resp.StatusCode, "pageCount:"+strconv.Itoa(pageCount))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get alert conditions, pageCount '%d'\n", statusCode, pageCount)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+
+ var size = 0
+ if cat == newrelic.ConditionDefault {
+ size = len(list.AlertsDefaultConditions)
+ } else if cat == newrelic.ConditionExternalService {
+ size = len(list.AlertsExternalServiceConditions)
+ } else if cat == newrelic.ConditionNRQL {
+ size = len(list.AlertsNRQLConditions)
+ } else if cat == newrelic.ConditionPlugins {
+ size = len(list.AlertsPluginsConditions)
+ } else if cat == newrelic.ConditionSynthetics {
+ size = len(list.AlertsSyntheticsConditions)
+ }
+
+ if size == 0 {
+ break
+ } else {
+ //merge conditions list
+ alertsConditionList = utils.MergeAlertConditionList(alertsConditionList, list)
+ pageCount++
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID, nil, nil, "")
+
+ return alertsConditionList, err, ret
+}
+
+func IsConditionNameExists(alertPolicyID int64, condtionName string, cat newrelic.ConditionCategory) (bool, int64, error, tracker.ReturnValue) {
+ list, err, ret := GetConditionsByAlertPolicyIDAndConditionType(alertPolicyID, cat)
+ if ret.IsContinue == false {
+ return false, -1, err, ret
+ }
+
+ if cat == newrelic.ConditionDefault {
+ for _, condition := range list.AlertsDefaultConditions {
+ if *condition.Name == condtionName {
+ return true, *condition.ID, err, ret
+ }
+ }
+ } else if cat == newrelic.ConditionExternalService {
+ for _, condition := range list.AlertsExternalServiceConditions {
+ if *condition.Name == condtionName {
+ return true, *condition.ID, err, ret
+ }
+ }
+ } else if cat == newrelic.ConditionNRQL {
+ for _, condition := range list.AlertsNRQLConditions {
+ if *condition.Name == condtionName {
+ return true, *condition.ID, err, ret
+ }
+ }
+ } else if cat == newrelic.ConditionPlugins {
+ for _, condition := range list.AlertsPluginsConditions {
+ if *condition.Name == condtionName {
+ return true, *condition.ID, err, ret
+ }
+ }
+ } else if cat == newrelic.ConditionSynthetics {
+ for _, condition := range list.AlertsSyntheticsConditions {
+ if *condition.Name == condtionName {
+ return true, *condition.ID, err, ret
+ }
+ }
+ }
+
+ return false, -1, err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(alertsconditionsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertsconditionsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+}
diff --git a/cmd/get/get_alertspolicies.go b/cmd/get/get_alertspolicies.go
new file mode 100644
index 0000000..7612db1
--- /dev/null
+++ b/cmd/get/get_alertspolicies.go
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+// alertspoliciesCmd represents the alertspolicies command
+var alertspoliciesCmd = &cobra.Command{
+ Use: "alertspolicies",
+ Short: "Display all alerts_policies.",
+ Aliases: []string{"ap", "alertpolicy", "alertspolicy"},
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ var opt *newrelic.AlertsPolicyListOptions
+ if filter, err := utils.GetArg(cmd, "policy"); err == nil {
+ opt = &newrelic.AlertsPolicyListOptions{
+ NameOptions: filter,
+ }
+ }
+ alertsPolicyList, resp, err := client.AlertsPolicies.ListAll(context.Background(), opt)
+ if err != nil || resp.StatusCode >= 400 {
+ fmt.Printf("%v:%v\n", resp.Status, err)
+ os.Exit(1)
+ return
+ }
+ printer, err := utils.NewPriter(cmd)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(alertsPolicyList, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetAllAlertPolicies() (*newrelic.AlertsPolicyList, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_ALERT_POLICIES, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+
+ var allAlertList *newrelic.AlertsPolicyList = &newrelic.AlertsPolicyList{}
+
+ var opt *newrelic.AlertsPolicyListOptions
+ opt = &newrelic.AlertsPolicyListOptions{}
+
+ var pageCount = 1
+ for {
+ opt.Page = pageCount
+ alertsPolicyList, resp, err := client.AlertsPolicies.ListAll(context.Background(), opt)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_ALERT_POLICIES, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.AlertsPolicies, tracker.OPERATION_NAME_GET_ALERT_POLICIES, resp.StatusCode, "pageCount:"+strconv.Itoa(pageCount))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one page alert policies, pageCount '%d'\n", statusCode, pageCount)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_ALERT_POLICIES, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ var policiesListLen = len(alertsPolicyList.AlertsPolicies)
+
+ if policiesListLen == 0 {
+ break
+ } else {
+ allAlertList.AlertsPolicies = utils.MergeAlertPolicyList(allAlertList.AlertsPolicies, alertsPolicyList.AlertsPolicies)
+
+ pageCount++
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_ALERT_POLICIES, nil, nil, "")
+ return allAlertList, err, ret
+}
+
+func IsPolicyNameExists(policyName string) (bool, *newrelic.AlertsPolicy, error, tracker.ReturnValue) {
+ allPolicyList, err, returnValue := GetAllAlertPolicies()
+ if returnValue.IsContinue == false {
+ return false, nil, err, returnValue
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CHECK_ALERT_POLICY_NAME_EXISTS, nil, nil, "")
+
+ for _, policy := range allPolicyList.AlertsPolicies {
+ if *policy.Name == policyName {
+ return true, policy, nil, ret
+ }
+ }
+
+ return false, nil, err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(alertspoliciesCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+ alertspoliciesCmd.Flags().StringP("policy", "p", "", "policy name to filter returned result")
+}
diff --git a/cmd/get/get_dashboard.go b/cmd/get/get_dashboard.go
new file mode 100644
index 0000000..fa27952
--- /dev/null
+++ b/cmd/get/get_dashboard.go
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/pretty"
+)
+
+// dashboardsCmd represents the dashboards command
+var dashboardCmd = &cobra.Command{
+ Use: "dashboard",
+ Short: "Display one single dashboard by id.",
+ Example: `* nr get dashboard `,
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ var err = fmt.Errorf("%q looks like a non-number.\n", args[0])
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+
+ id, _ := strconv.ParseInt(args[0], 10, 64)
+
+ result, err, ret := GetDashboardByID(id)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if ret.IsContinue == false {
+ fmt.Println(ret.OriginalError)
+ os.Exit(1)
+ return
+ }
+
+ jsonStr := pretty.Pretty([]byte(result))
+ fmt.Printf("%s\n", string(jsonStr))
+
+ os.Exit(0)
+ },
+}
+
+func GetDashboardByID(id int64) (string, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_DASHBOARD_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return "", err, ret
+ }
+
+ resp, bytes, err := client.Dashboards.GetByID(context.Background(), id)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_DASHBOARD_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return "", err, ret
+ }
+ tracker.AppendRESTCallResult(client.Labels, tracker.OPERATION_NAME_GET_DASHBOARD_BY_ID, resp.StatusCode, "id:"+strconv.FormatInt(id, 10))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one specific dashboard, id '%d'\n", statusCode, id)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_DASHBOARD_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return "", err, ret
+ }
+
+ strContent := string(bytes)
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_DASHBOARD_BY_ID, nil, nil, "")
+
+ return strContent, nil, ret
+}
+
+func IsDashboardTitleExists(dashboardTitle string) (bool, string, error, tracker.ReturnValue) {
+ resultStr, err, returnValue := GetAllDashboards()
+ if returnValue.IsContinue == false {
+ return false, "", err, returnValue
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CHECK_DASHBOARD_TITLE_EXISTS, nil, nil, "")
+
+ dashboardArr := gjson.Parse(resultStr).Get("dashboards").Array()
+ for _, dashboard := range dashboardArr {
+
+ titleResult := gjson.Parse(dashboard.String()).Get("title")
+ title := titleResult.String()
+ if dashboardTitle == title {
+ return true, dashboard.String(), err, ret
+ }
+ }
+
+ return false, "", err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(dashboardCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // dashboardsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+}
diff --git a/cmd/get/get_dashboards.go b/cmd/get/get_dashboards.go
new file mode 100644
index 0000000..e0e9044
--- /dev/null
+++ b/cmd/get/get_dashboards.go
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/pretty"
+ "github.com/tidwall/sjson"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+// dashboardsCmd represents the dashboards command
+var dashboardsCmd = &cobra.Command{
+ Use: "dashboards",
+ Short: "Display all dashboards.",
+ Example: `* nr get dashboards`,
+ Run: func(cmd *cobra.Command, args []string) {
+
+ resultStr, err, ret := GetAllDashboards()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if ret.IsContinue == false {
+ fmt.Println(ret.OriginalError)
+ os.Exit(1)
+ return
+ }
+
+ result := pretty.Pretty([]byte(resultStr))
+ fmt.Printf("%s\n", string(result))
+
+ os.Exit(0)
+ },
+}
+
+func GetAllDashboards() (string, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_DASHBOARDS, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return "", err, ret
+ }
+
+ var dashboardJson = `{"dashboards":[]}`
+
+ var pageCount = 1
+ var opt *newrelic.DashboardListOptions = &newrelic.DashboardListOptions{}
+
+ for {
+ opt.Page = pageCount
+
+ resp, bytes, err := client.Dashboards.ListAll(context.Background(), opt)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_DASHBOARDS, err, tracker.ERR_REST_CALL, "")
+ return "", err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.Labels, tracker.OPERATION_NAME_GET_DASHBOARDS, resp.StatusCode, "pageCount:"+strconv.Itoa(pageCount))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one page dashboards, pageCount '%d'\n", statusCode, pageCount)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_DASHBOARDS, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return "", err, ret
+ }
+
+ strContent := string(bytes)
+ dashboardArr := gjson.Parse(strContent).Get("dashboards").Array()
+ var lenDashboards = len(dashboardArr)
+
+ if lenDashboards == 0 {
+ break
+ } else {
+ for _, dashboard := range dashboardArr {
+ if dashboard.String() != "" {
+ dashboardJson, _ = sjson.Set(dashboardJson, "dashboards.-1", dashboard.String())
+ }
+ }
+ }
+ pageCount++
+ }
+
+ var resultStr = ""
+ var dashboardListSize = 0
+ dashboardArr := gjson.Parse(dashboardJson).Get("dashboards").Array()
+ var lenArr = len(dashboardArr)
+
+ resultStr = resultStr + `{"dashboards":[`
+ for index, dashboard := range dashboardArr {
+ if index < (lenArr - 1) {
+ resultStr = resultStr + dashboard.String() + ","
+ } else {
+ resultStr = resultStr + dashboard.String()
+ }
+
+ // fmt.Println(dashboard.String())
+ // fmt.Println()
+ // id := gjson.Parse(dashboard.String()).Get("id")
+ // title := gjson.Parse(dashboard.String()).Get("title")
+ // fmt.Println(id)
+ // fmt.Println(title)
+ // fmt.Println()
+ // fmt.Println()
+
+ dashboardListSize++
+ }
+ resultStr = resultStr + `]}`
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_DASHBOARDS, nil, nil, "")
+
+ return resultStr, nil, ret
+}
+
+func init() {
+ GetCmd.AddCommand(dashboardsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // dashboardsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+}
diff --git a/cmd/get/get_labels.go b/cmd/get/get_labels.go
new file mode 100644
index 0000000..ce73277
--- /dev/null
+++ b/cmd/get/get_labels.go
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+// labelsCmd represents the monitors command
+var labelsCmd = &cobra.Command{
+ Use: "labels",
+ Short: "Display all labels.",
+ Example: `* nr get labels
+* nr get labels -o json
+* nr get labels -o yaml`,
+ Run: func(cmd *cobra.Command, args []string) {
+
+ labelArray, err, _ := GetLabels()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ var printer utils.Printer
+
+ printer = &utils.JSONPrinter{}
+
+ var output string
+ flags := cmd.Flags()
+ if flags.Lookup("output") != nil {
+ output, err = cmd.Flags().GetString("output")
+ if output == "yaml" {
+ printer = &utils.YAMLPrinter{}
+ }
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(labelArray, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetLabels() (*newrelic.LabelList, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_LABELS, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+
+ var opt *newrelic.LabelListOptions
+ opt = &newrelic.LabelListOptions{}
+
+ var allLabelList *newrelic.LabelList = &newrelic.LabelList{}
+
+ var pageCount = 1
+ for {
+ opt.Page = pageCount
+ labelList, resp, err := client.Labels.ListAll(context.Background(), opt)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_LABELS, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.Labels, tracker.OPERATION_NAME_GET_LABELS, resp.StatusCode, "pageCount:"+strconv.Itoa(pageCount))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one page labels, pageCount '%d'\n", statusCode, pageCount)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_LABELS, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ var labelListLen = len(labelList.Labels)
+
+ if labelListLen == 0 {
+ break
+ } else {
+ allLabelList.Labels = utils.MergeLabelList(allLabelList.Labels, labelList.Labels)
+
+ pageCount++
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_LABELS, nil, nil, "")
+
+ return allLabelList, err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(labelsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // usersCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:s
+}
diff --git a/cmd/get/get_labelsmonitors.go b/cmd/get/get_labelsmonitors.go
new file mode 100644
index 0000000..33194dd
--- /dev/null
+++ b/cmd/get/get_labelsmonitors.go
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+// labelsmonitorsCmd represents the monitors command
+var labelsmonitorsCmd = &cobra.Command{
+ Use: "labelsmonitors",
+ Short: "Display monitros by label.",
+ Example: `* nr get labelsmonitors
+* nr get labelsmonitors Category:Label -o json
+* nr get labelsmonitors Category:Label -o yaml
+* nr get labelsmonitors Env:Staging -o json`,
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ label := args[0]
+
+ monitorRefList, err, ret := GetMonitorsByLabel(label)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if ret.IsContinue == false {
+ os.Exit(1)
+ return
+ }
+
+ var printer utils.Printer
+
+ printer = &utils.JSONPrinter{}
+
+ var output string
+ flags := cmd.Flags()
+ if flags.Lookup("output") != nil {
+ output, err = cmd.Flags().GetString("output")
+ if output == "yaml" {
+ printer = &utils.YAMLPrinter{}
+ }
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(monitorRefList, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetMonitorsByLabel(label string) (*newrelic.MonitorRefList, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("labelSynthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS_BY_LABEL, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ var opt *newrelic.PageLimitOptions
+ opt = &newrelic.PageLimitOptions{}
+ var pageSize int = 20
+ var pageOffset int = 0
+ var allMonitorRefList *newrelic.MonitorRefList = &newrelic.MonitorRefList{}
+ for {
+ opt.Limit = pageSize
+ opt.Offset = pageOffset
+ labelSynthetics, resp, err := client.LabelsSynthetics.GetMonitorsByLabel(context.Background(), opt, label)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS_BY_LABEL, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+ tracker.AppendRESTCallResult(client.LabelsSynthetics, tracker.OPERATION_NAME_GET_MONITORS_BY_LABEL, resp.StatusCode, "pageSize:"+strconv.Itoa(pageSize)+",pageOffset:"+strconv.Itoa(pageOffset))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get monitors by specific label, pageSize '%d', pageOffset '%d'\n", statusCode, pageSize, pageOffset)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS_BY_LABEL, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+
+ var refsLen = len(labelSynthetics.PagedData.MonitorRefs)
+ if refsLen == 0 {
+ break
+ } else {
+ allMonitorRefList.MonitorRefs = utils.MergeMonitorReflList(allMonitorRefList.MonitorRefs, labelSynthetics.PagedData.MonitorRefs)
+
+ pageOffset = pageOffset + pageSize
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_MONITORS_BY_LABEL, nil, nil, "")
+ return allMonitorRefList, err, ret
+}
+
+func GetLabelsByMonitorID(monitorId string) ([]*string, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_LABELS_BY_MONITOR_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ monitor, _, err := client.SyntheticsMonitors.GetByID(context.Background(), monitorId)
+
+ var labels []*string
+
+ //get all labels
+ lablesArray, err, returnValue := GetLabels()
+ if returnValue.IsContinue == false {
+ return nil, err, returnValue
+ }
+
+ for index, _ := range lablesArray.Labels {
+ l := lablesArray.Labels[index]
+ key := fmt.Sprintf("%v:%v", *l.Category, *l.Name)
+
+ labelSynthetics, err, returnValue := GetMonitorsByLabel(key)
+ if returnValue.IsContinue == false {
+ return nil, err, returnValue
+ }
+
+ // if err != nil {
+ // fmt.Println(err)
+ // return nil, err, returnValue
+ // }
+
+ monitorRefList := labelSynthetics.MonitorRefs
+ var refListLen = len(monitorRefList)
+ // fmt.Println(refListLen)
+
+ if refListLen > 0 {
+ //the label was added to monitors
+ for _, ref := range monitorRefList {
+ //get monitor id
+ mId := *ref.ID
+ if mId == (*monitor.ID) {
+ labLen := len(monitor.Labels)
+ var newLabelList = make([]*string, (labLen + 1))
+ for i := 0; i < labLen; i++ {
+ newLabelList[i] = monitor.Labels[i]
+ }
+ newLabelList[labLen] = &key
+ labels = utils.MergeStringList(labels, newLabelList)
+ }
+ }
+ } else {
+ //the label was not used by any monitors, skip
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_LABELS_BY_MONITOR_ID, nil, nil, "")
+
+ return labels, err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(labelsmonitorsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // usersCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:s
+}
diff --git a/cmd/get/get_monitor.go b/cmd/get/get_monitor.go
new file mode 100644
index 0000000..710a133
--- /dev/null
+++ b/cmd/get/get_monitor.go
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var monitorCmd = &cobra.Command{
+ Use: "monitor",
+ Short: "Display a single monitor by id.",
+ Example: "nr get monitor ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+
+ id := args[0]
+
+ monitor, err, _ := GetMonitorByID(id)
+
+ var printer utils.Printer
+
+ printer = &utils.JSONPrinter{}
+
+ var output string
+ flags := cmd.Flags()
+ if flags.Lookup("output") != nil {
+ output, err = cmd.Flags().GetString("output")
+ if output == "yaml" {
+ printer = &utils.YAMLPrinter{}
+ }
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(monitor, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetMonitorByID(id string) (*newrelic.Monitor, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITOR_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+
+ monitor, resp, err := client.SyntheticsMonitors.GetByID(context.Background(), id)
+
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITOR_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_GET_MONITOR_BY_ID, resp.StatusCode, "monitor id: "+id+", monitor name: "+(*monitor.Name))
+
+ // if err != nil || resp.StatusCode >= 400 {
+ // fmt.Printf("%v:%v\n", resp.Status, err)
+ // return nil, err
+ // }
+ monitor.Labels = make([]*string, 0)
+
+ //get all labels
+ lablesArray, err, _ := GetLabels()
+
+ for index, _ := range lablesArray.Labels {
+ l := lablesArray.Labels[index]
+ key := fmt.Sprintf("%v:%v", *l.Category, *l.Name)
+
+ labelSynthetics, err, returnValue := GetMonitorsByLabel(key)
+ if returnValue.IsContinue == false {
+ return nil, err, returnValue
+ }
+ // if err != nil {
+ // fmt.Println(err)
+ // return nil, err
+ // }
+
+ monitorRefList := labelSynthetics.MonitorRefs
+ var refListLen = len(monitorRefList)
+
+ if refListLen > 0 {
+ //the label was added to monitors
+ for _, ref := range monitorRefList {
+ //get monitor id
+ monitorId := *ref.ID
+ if monitorId == (*monitor.ID) {
+ labLen := len(monitor.Labels)
+ var newLabelList = make([]*string, (labLen + 1))
+ for i := 0; i < labLen; i++ {
+ newLabelList[i] = monitor.Labels[i]
+ }
+ newLabelList[labLen] = &key
+ monitor.Labels = newLabelList
+ }
+ }
+ } else {
+ //the label was not used by any monitors, skip
+ }
+ }
+
+ if *monitor.Type == "SCRIPT_BROWSER" || *monitor.Type == "SCRIPT_API" {
+ monitorID := monitor.ID
+ var id string = ""
+ id = *monitorID
+ scriptText, _, err := client.SyntheticsScript.GetByID(context.Background(), id)
+
+ tracker.AppendRESTCallResult(client.SyntheticsScript, tracker.OPERATION_NAME_GET_MONITOR_SCRIPT, resp.StatusCode, "monitor id: "+id+", monitor name: "+(*monitor.Name))
+
+ if err != nil {
+ fmt.Println(err)
+ // var st *newrelic.Script
+ // st = &newrelic.Script{}
+ // scriptText = st
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITOR_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one monitor script, monitor id '%s', monitor name '%s'\n", statusCode, id, *monitor.Name)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITOR_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "monitor id: "+id+", monitor name: "+(*monitor.Name))
+ return nil, err, ret
+ }
+ monitor.Script = scriptText
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_MONITOR_BY_ID, nil, nil, "")
+ return monitor, err, ret
+}
+
+var isAllMonitorsFetched bool = false
+var allMonitors []*newrelic.Monitor
+
+func IsMonitorNameExists(monitorName string) (bool, *newrelic.Monitor, error, tracker.ReturnValue) {
+ // var allMonitorList []*newrelic.Monitor
+ if isAllMonitorsFetched == false {
+ allMonitorList, err, returnValue := GetMonitors()
+ if returnValue.IsContinue == false {
+ return false, nil, err, returnValue
+ }
+ allMonitors = allMonitorList
+ isAllMonitorsFetched = true
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CHECK_MONITOR_NAME_EXISTS, nil, nil, "")
+ for _, monitor := range allMonitors {
+ if *monitor.Name == monitorName {
+ return true, monitor, nil, ret
+ }
+ }
+
+ return false, nil, nil, ret
+}
+
+func GetMonitorByName(monitorName string) (*newrelic.Monitor, error, tracker.ReturnValue) {
+
+ isExist, monitor, err, ret := IsMonitorNameExists(monitorName)
+ if ret.IsContinue == false {
+ return nil, err, ret
+ }
+
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_MONITOR_BY_NAME, nil, nil, "")
+ if isExist == true {
+ return monitor, err, ret
+ } else {
+ return nil, err, ret
+ }
+}
+
+func init() {
+ GetCmd.AddCommand(monitorCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // userCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+}
diff --git a/cmd/get/get_monitors.go b/cmd/get/get_monitors.go
new file mode 100644
index 0000000..b0d11ef
--- /dev/null
+++ b/cmd/get/get_monitors.go
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+// monitorsCmd represents the monitors command
+var monitorsCmd = &cobra.Command{
+ Use: "monitors",
+ Short: "Display all synthetics monitors.",
+ Example: `* nr get monitors
+* nr get monitors -o json
+* nr get monitors -o yaml`,
+ Run: func(cmd *cobra.Command, args []string) {
+
+ monitorArray, err, ret := GetMonitors()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if ret.IsContinue == false {
+ os.Exit(1)
+ return
+ }
+
+ //get all labels
+ lablesArray, err, ret := GetLabels()
+ if ret.IsContinue == false {
+ os.Exit(1)
+ return
+ }
+
+ for index, _ := range lablesArray.Labels {
+ l := lablesArray.Labels[index]
+ key := fmt.Sprintf("%v:%v", *l.Category, *l.Name)
+
+ labelSynthetics, err, returnValue := GetMonitorsByLabel(key)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ os.Exit(1)
+ return
+ }
+ // if err != nil {
+ // fmt.Println(err)
+ // return
+ // }
+
+ monitorRefList := labelSynthetics.MonitorRefs
+ var refListLen = len(monitorRefList)
+
+ if refListLen > 0 {
+ //the label was added to monitors
+ for _, ref := range monitorRefList {
+ //get monitor id
+ monitorId := *ref.ID
+ for _, monitor := range monitorArray {
+ if monitorId == (*monitor.ID) {
+ labLen := len(monitor.Labels)
+ var newLabelList = make([]*string, (labLen + 1))
+ for i := 0; i < labLen; i++ {
+ newLabelList[i] = monitor.Labels[i]
+ }
+ newLabelList[labLen] = &key
+ monitor.Labels = newLabelList
+ }
+ }
+ }
+ } else {
+ //the label was not used by any monitors, skip
+ }
+ }
+
+ var printer utils.Printer
+
+ printer = &utils.JSONPrinter{}
+
+ var output string
+ flags := cmd.Flags()
+ if flags.Lookup("output") != nil {
+ output, err = cmd.Flags().GetString("output")
+ if output == "yaml" {
+ printer = &utils.YAMLPrinter{}
+ }
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(monitorArray, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func GetMonitors() ([]*newrelic.Monitor, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+
+ var opt *newrelic.MonitorListOptions
+ opt = &newrelic.MonitorListOptions{}
+ var pageSize int = 50
+ var pageOffset int = 0
+
+ var mList *newrelic.MonitorList = &newrelic.MonitorList{}
+
+ for {
+ opt.PageLimitOptions.Limit = pageSize
+ opt.PageLimitOptions.Offset = pageOffset
+ monitorList, resp, err := client.SyntheticsMonitors.ListAll(context.Background(), opt)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_GET_MONITORS, resp.StatusCode, "pageSize:"+strconv.Itoa(pageSize)+",pageOffset:"+strconv.Itoa(pageOffset))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one page monitors, pageSize '%d', pageOffset '%d'\n", statusCode, pageSize, pageOffset)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITORS, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ var monitorListLen = len(monitorList.Monitors)
+
+ if monitorListLen == 0 {
+ break
+ } else {
+ mList.Monitors = utils.MergeMonitorList(mList.Monitors, monitorList.Monitors)
+
+ pageOffset = pageOffset + pageSize
+ }
+ }
+
+ var mListLen = len(mList.Monitors)
+ var monitorArray = make([]*newrelic.Monitor, mListLen)
+ for i := 0; i < mListLen; i++ {
+ monitor := mList.Monitors[i]
+ if *monitor.Type == "SCRIPT_BROWSER" || *monitor.Type == "SCRIPT_API" {
+ monitorID := monitor.ID
+ var id string = ""
+ id = *monitorID
+ scriptText, resp, err := client.SyntheticsScript.GetByID(context.Background(), id)
+
+ tracker.AppendRESTCallResult(client.SyntheticsScript, tracker.OPERATION_NAME_GET_MONITOR_SCRIPT, resp.StatusCode, "monitor id: "+id+", monitor name: "+(*monitor.Name))
+
+ if err != nil {
+ fmt.Println(err)
+ // var st *newrelic.Script
+ // st = &newrelic.Script{}
+ // scriptText = st
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITOR_SCRIPT, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ }
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Get one monitor script, monitor id '%s', monitor name '%s'\n", statusCode, id, *monitor.Name)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_GET_MONITOR_SCRIPT, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "monitor id: "+id+", monitor name: "+(*monitor.Name))
+ return nil, err, ret
+ }
+ monitor.Script = scriptText
+ monitorArray[i] = monitor
+
+ } else {
+ monitorArray[i] = monitor
+ }
+
+ }
+
+ for _, m := range monitorArray {
+ m.Labels = make([]*string, 0)
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_GET_MONITORS, nil, nil, "")
+ return monitorArray, err, ret
+}
+
+func init() {
+ GetCmd.AddCommand(monitorsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // usersCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:s
+}
diff --git a/cmd/get/get_user.go b/cmd/get/get_user.go
new file mode 100644
index 0000000..7e37e77
--- /dev/null
+++ b/cmd/get/get_user.go
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var userCmd = &cobra.Command{
+ Use: "user",
+ Short: "Display a single user by id.",
+ Example: "nr get user ",
+ Args: func(cmd *cobra.Command, args []string) error {
+ if len(args) != 1 {
+ var err = fmt.Errorf("length of [flags] should be 1 instead of %d", len(args))
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ if _, err := strconv.ParseInt(args[0], 10, 64); err != nil {
+ var err = fmt.Errorf("%q looks like a non-number.\n", args[0])
+ fmt.Println(err)
+ os.Exit(1)
+ return err
+ }
+ return nil
+ },
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ id, _ := strconv.ParseInt(args[0], 10, 64)
+ user, resp, err := client.Users.GetByID(context.Background(), id)
+ if err != nil || resp.StatusCode >= 400 {
+ fmt.Printf("%v:%v\n", resp.Status, err)
+ os.Exit(1)
+ return
+ }
+ printer, err := utils.NewPriter(cmd)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(user, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func init() {
+ GetCmd.AddCommand(userCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // userCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+}
diff --git a/cmd/get/get_users.go b/cmd/get/get_users.go
new file mode 100644
index 0000000..456ffcd
--- /dev/null
+++ b/cmd/get/get_users.go
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package get
+
+import (
+ "context"
+ "fmt"
+ "os"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+// usersCmd represents the users command
+var usersCmd = &cobra.Command{
+ Use: "users",
+ Short: "Display all users.",
+ Example: `* nr get users
+* nr get users -o json
+* nr get users -o yaml
+* nr get users -i 2102902
+* nr get users -i 2102902,+801314
+* nr get users -e wei.huang1@ibm.com
+* nr get users -e ibm.com
+* nr get users -i 2102902 -e ibm.com`,
+ Run: func(cmd *cobra.Command, args []string) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ var opt *newrelic.UserListOptions
+ if ids, err := utils.GetArg(cmd, "id"); err == nil {
+ opt = &newrelic.UserListOptions{
+ IDOptions: ids,
+ }
+ }
+ if emails, err := utils.GetArg(cmd, "email"); err == nil {
+ if opt == nil {
+ opt = new(newrelic.UserListOptions)
+ }
+ opt.EmailOptions = emails
+ }
+ userList, resp, err := client.Users.ListAll(context.Background(), opt)
+ if err != nil || resp.StatusCode >= 400 {
+ fmt.Printf("%v:%v\n", resp.Status, err)
+ os.Exit(1)
+ return
+ }
+ printer, err := utils.NewPriter(cmd)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ printer.Print(userList, os.Stdout)
+
+ os.Exit(0)
+ },
+}
+
+func init() {
+ GetCmd.AddCommand(usersCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // usersCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ usersCmd.Flags().StringP("id", "i", "", "user id(s) to filter returned result. use ',+' to separate ids")
+ usersCmd.Flags().StringP("email", "e", "", "email to filter returned result. can't specify emails")
+}
diff --git a/cmd/insert/insert.go b/cmd/insert/insert.go
new file mode 100644
index 0000000..fca9b51
--- /dev/null
+++ b/cmd/insert/insert.go
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package insert
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// InsertCmd represents the insert command
+var InsertCmd = &cobra.Command{
+ Use: "insert",
+ Short: "Inster NewRelic custom events using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // InsertCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+
+ InsertCmd.PersistentFlags().StringP("file", "f", "", "File name to store custom events data in JSON.")
+ InsertCmd.MarkPersistentFlagRequired("file")
+
+ InsertCmd.PersistentFlags().StringP("insert-key", "i", "", "New Relic insert key.")
+ InsertCmd.MarkPersistentFlagRequired("insert-key")
+
+ InsertCmd.PersistentFlags().StringP("account-id", "a", "", "New Relic account ID.")
+ InsertCmd.MarkPersistentFlagRequired("account-id")
+}
diff --git a/cmd/insert/insert_customevents.go b/cmd/insert/insert_customevents.go
new file mode 100644
index 0000000..8c5eaf3
--- /dev/null
+++ b/cmd/insert/insert_customevents.go
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package insert
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "os"
+
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var customeventsCmd = &cobra.Command{
+ Use: "customevents",
+ Short: "Insert custom events.",
+ Aliases: []string{"m"},
+ Example: `nr insert customevents`,
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var err error
+
+ flags := cmd.Flags()
+
+ var insertKey = ""
+ if flags.Lookup("insert-key") != nil {
+ insertKey, err = cmd.Flags().GetString("insert-key")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if insertKey == "" {
+ fmt.Println("Please give New Relic insert key.")
+ }
+ }
+
+ var accountID = ""
+ if flags.Lookup("account-id") != nil {
+ accountID, err = cmd.Flags().GetString("account-id")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ if accountID == "" {
+ fmt.Println("Please give New Relic account ID.")
+ }
+ }
+
+ var filePath = ""
+
+ if flags.Lookup("file") != nil {
+ filePath, err = cmd.Flags().GetString("file")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ }
+
+ bytes, err := ioutil.ReadFile(filePath)
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", filePath, err)
+ os.Exit(1)
+ return
+ }
+
+ var fileContent = string(bytes)
+
+ client, err := utils.GetNewRelicClient("insights")
+ if err != nil {
+ fmt.Println(err)
+ tracker.ToReturnValue(false, tracker.OPERATION_NAME_INSERT_CUSTOM_EVENTS, err, tracker.ERR_CREATE_NR_CLINET, "")
+ os.Exit(1)
+ return
+ }
+
+ resp, bytes, err := client.CustomEvents.Insert(context.Background(), insertKey, accountID, fileContent)
+ retMsg := string(bytes)
+
+ if err != nil {
+ tracker.ToReturnValue(false, tracker.OPERATION_NAME_INSERT_CUSTOM_EVENTS, err, tracker.ERR_REST_CALL, "")
+ fmt.Printf("Failed to insert custom events.")
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ fmt.Printf("Response status code: %d.\n", resp.StatusCode)
+
+ tracker.AppendRESTCallResult(client.CustomEvents, tracker.OPERATION_NAME_INSERT_CUSTOM_EVENTS, resp.StatusCode, retMsg)
+
+ var ret tracker.ReturnValue
+ if resp.StatusCode >= 400 {
+ ret = tracker.ToReturnValue(false, tracker.OPERATION_NAME_INSERT_CUSTOM_EVENTS, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, retMsg)
+ fmt.Printf("Failed to insert custom events. status code is not 200, Response status code: %d\n", resp.StatusCode)
+ fmt.Println(retMsg)
+ } else {
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_INSERT_CUSTOM_EVENTS, nil, nil, "")
+ }
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ if ret.IsContinue == false {
+ fmt.Printf("Failed to insert custom events.")
+ os.Exit(1)
+ return
+ }
+
+ fmt.Println("Insert custom events successful.")
+ os.Exit(0)
+ },
+}
+
+func init() {
+ InsertCmd.AddCommand(customeventsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/patch/patch.go b/cmd/patch/patch.go
new file mode 100644
index 0000000..d41b755
--- /dev/null
+++ b/cmd/patch/patch.go
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package patch
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// PatchCmd represents the update command
+var PatchCmd = &cobra.Command{
+ Use: "patch",
+ Short: "Patch a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // PatchCmd.PersistentFlags().String("foo", "", "A help for foo")
+ PatchCmd.PersistentFlags().StringP("file", "f", "", "Filename to patch resource with, yaml/json format is supported.")
+ PatchCmd.MarkPersistentFlagRequired("file")
+
+ PatchCmd.PersistentFlags().StringP("output", "o", "json", "Output format. json/yaml are supported")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // UpdateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/patch/patch_monitor.go b/cmd/patch/patch_monitor.go
new file mode 100644
index 0000000..5de4e41
--- /dev/null
+++ b/cmd/patch/patch_monitor.go
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package patch
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var monitorCmd = &cobra.Command{
+ Use: "monitor",
+ Short: "Patch monitor from a file.",
+ Example: "nr patch monitor -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var p = new(newrelic.Monitor)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.Monitor), p) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ // start to create
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if p.ID == nil {
+ fmt.Printf("Can't find {.id} in %q.\n", file)
+ os.Exit(1)
+ return
+ }
+
+ resp, err := client.SyntheticsMonitors.Patch(context.Background(), p, p.ID)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Patch monitor '%s', monitor id: '%s'\n", statusCode, *p.Name, *p.ID)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func init() {
+ PatchCmd.AddCommand(monitorCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/restore/resotre_alertsconditions.go b/cmd/restore/resotre_alertsconditions.go
new file mode 100644
index 0000000..07375a1
--- /dev/null
+++ b/cmd/restore/resotre_alertsconditions.go
@@ -0,0 +1,774 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package restore
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/IBM/newrelic-cli/cmd/backup"
+ "github.com/IBM/newrelic-cli/cmd/create"
+ "github.com/IBM/newrelic-cli/cmd/delete"
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/cmd/update"
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var alertsconditionsCmd = &cobra.Command{
+ Use: "alertsconditions",
+ Short: "Restore alertsconditions from directory.",
+ Example: "nr restore alertsconditions -d ",
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var restoreFileFolder string
+ var err error
+ flags := cmd.Flags()
+ if flags.Lookup("dir") != nil {
+ restoreFileFolder, err = cmd.Flags().GetString("dir")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ }
+
+ var restoreFileNamesParam string
+ var restoreFileNames []string
+ flags = cmd.Flags()
+ if flags.Lookup("files") != nil {
+ restoreFileNamesParam, err = cmd.Flags().GetString("files")
+
+ if restoreFileNamesParam != "" {
+ restoreFileNames = strings.Split(restoreFileNamesParam, ",")
+ }
+ }
+
+ var restoreLoggingFileName string
+ flags = cmd.Flags()
+ if flags.Lookup("File") != nil {
+ restoreLoggingFileName, err = cmd.Flags().GetString("File")
+ }
+
+ if restoreFileFolder == "" && restoreFileNamesParam == "" && restoreLoggingFileName == "" {
+ fmt.Println("Please give restore folder name, files path or logging file name.")
+ os.Exit(1)
+ return
+ }
+
+ var restoreFileNameList []string
+
+ if restoreFileFolder != "" {
+ f, err := os.Open(restoreFileFolder)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", restoreFileFolder, err)
+ os.Exit(1)
+ return
+ }
+
+ dir, err := ioutil.ReadDir(restoreFileFolder)
+
+ for _, fileInfo := range dir {
+ if fileInfo.IsDir() == false {
+ restoreFileName := fileInfo.Name()
+
+ isBak := strings.HasSuffix(restoreFileName, ".alert-conditions.bak")
+ if isBak == true {
+ var fileName = restoreFileFolder + "/" + restoreFileName
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ }
+ }
+ }
+
+ if restoreLoggingFileName != "" {
+ f, err := os.Open(restoreLoggingFileName)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open retore logging file '%v': %v\n", restoreLoggingFileName, err)
+ os.Exit(1)
+ return
+ }
+
+ buf := bufio.NewReader(f)
+ for {
+ line, err := buf.ReadString('\n')
+ line = strings.TrimSpace(line)
+ var fileName = line
+ isBak := strings.HasSuffix(fileName, ".alert-conditions.bak")
+ if isBak == true {
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ if err != nil {
+ if err != io.EOF {
+ os.Exit(1)
+ return
+ } else {
+ //end of file
+ break
+ }
+ }
+ }
+ }
+
+ if len(restoreFileNames) > 0 {
+ for _, fileName := range restoreFileNames {
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ }
+
+ var filesLen = len(restoreFileNameList)
+
+ if filesLen == 0 {
+ fmt.Printf("No files to restore found!")
+ os.Exit(1)
+ return
+ }
+
+ var resultFileName string = ""
+ if flags.Lookup("result-file-name") != nil {
+ resultFileName, err = cmd.Flags().GetString("result-file-name")
+ }
+ if resultFileName == "" {
+ resultFileName = "fail-restore-alert-conditions-file-list.log"
+ }
+
+ fmt.Printf("Start to restore all alertsconditions.")
+
+ var updateMode string = "skip"
+ if flags.Lookup("update-mode") != nil {
+ updateMode, err = cmd.Flags().GetString("update-mode")
+ }
+ fmt.Printf("Using update mode - %s\n", updateMode)
+
+ var restoreAlertPolicyMetaArray []tracker.RestoreAlertPolicyMeta
+
+ if updateMode == "clean" {
+ var rapmArray []tracker.RestoreAlertPolicyMeta
+ for _, restoreFileName := range restoreFileNameList {
+ var restoreAlertPolicyMeta tracker.RestoreAlertPolicyMeta = tracker.RestoreAlertPolicyMeta{}
+ restoreAlertPolicyMeta.FileName = restoreFileName
+
+ rapmArray = append(rapmArray, restoreAlertPolicyMeta)
+ }
+
+ //delete all alert policies
+
+ allPolicyList, err, returnValue := get.GetAllAlertPolicies()
+ if err != nil {
+ exitRestoreAlertCondtionsWithError(returnValue)
+ writeFailRestoreConditionsFileList(resultFileName, rapmArray)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ exitRestoreAlertCondtionsWithError(returnValue)
+ writeFailRestoreConditionsFileList(resultFileName, rapmArray)
+ os.Exit(1)
+ return
+ }
+
+ for _, alertsPolicy := range allPolicyList.AlertsPolicies {
+ err, returnValue := delete.DeletePolicyByName(*alertsPolicy.Name)
+ if err != nil {
+ exitRestoreAlertCondtionsWithError(returnValue)
+ writeFailRestoreConditionsFileList(resultFileName, rapmArray)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ exitRestoreAlertCondtionsWithError(returnValue)
+ writeFailRestoreConditionsFileList(resultFileName, rapmArray)
+ os.Exit(1)
+ return
+ }
+ }
+ }
+
+ for _, restoreFileName := range restoreFileNameList {
+
+ var restoreAlertPolicyMeta tracker.RestoreAlertPolicyMeta = tracker.RestoreAlertPolicyMeta{}
+ restoreAlertPolicyMeta.FileName = restoreFileName
+ restoreAlertPolicyMeta.OperationStatus = "fail"
+
+ restoreFile, err := os.Open(restoreFileName)
+ defer restoreFile.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", restoreFileName, err)
+ continue
+ }
+
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(restoreFile, 4096)
+ var p = new(backup.OneAlertBackup)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", restoreFileName, err)
+ return
+ }
+ if reflect.DeepEqual(new(backup.OneAlertBackup), p) {
+ fmt.Printf("Error validating %q.\n", restoreFileName)
+ return
+ }
+
+ alertPolicySet := p.AlertPolicySet
+ alertPolicy := alertPolicySet.AlertsPolicy
+ // fmt.Println(*alertPolicy.Name)
+
+ newAlertPolicy, isPolicyCreated, err, ret := RestoreOnePolicy(alertPolicy, updateMode)
+ if err != nil {
+ fmt.Println(err)
+ goto next
+ }
+ if ret.IsContinue == false {
+ goto next
+ } else {
+ if newAlertPolicy == nil {
+ //skip
+ restoreAlertPolicyMeta.OperationStatus = "success"
+ goto next
+ }
+ }
+
+ if alertPolicySet.AlertsConditionList != nil {
+ if alertPolicySet.AlertsConditionList.AlertsDefaultConditionList != nil {
+ var isErr bool = false
+ for _, defaultCondition := range alertPolicySet.AlertsConditionList.AlertsDefaultConditionList.AlertsDefaultConditions {
+ var cat newrelic.ConditionCategory = newrelic.ConditionDefault
+ var ac = new(newrelic.AlertsConditionEntity)
+ ac.AlertsDefaultConditionEntity = &newrelic.AlertsDefaultConditionEntity{}
+ ac.AlertsDefaultConditionEntity.AlertsDefaultCondition = defaultCondition
+ err, ret := RestoreOneCondition(*newAlertPolicy.ID, cat, ac, updateMode, isPolicyCreated)
+ if err != nil || ret.IsContinue == false {
+ isErr = true
+ break
+ }
+ }
+ if isErr == true {
+ goto next
+ }
+ }
+ }
+
+ if alertPolicySet.AlertsConditionList != nil {
+ if alertPolicySet.AlertsConditionList.AlertsExternalServiceConditionList != nil {
+ var isErr bool = false
+ for _, externalServiceCondition := range alertPolicySet.AlertsConditionList.AlertsExternalServiceConditionList.AlertsExternalServiceConditions {
+ var cat newrelic.ConditionCategory = newrelic.ConditionExternalService
+ var ac = new(newrelic.AlertsConditionEntity)
+ ac.AlertsExternalServiceConditionEntity = &newrelic.AlertsExternalServiceConditionEntity{}
+ ac.AlertsExternalServiceConditionEntity.AlertsExternalServiceCondition = externalServiceCondition
+ err, ret := RestoreOneCondition(*newAlertPolicy.ID, cat, ac, updateMode, isPolicyCreated)
+ if err != nil || ret.IsContinue == false {
+ isErr = true
+ break
+ }
+ }
+ if isErr == true {
+ goto next
+ }
+ }
+ }
+
+ if alertPolicySet.AlertsConditionList != nil {
+ if alertPolicySet.AlertsConditionList.AlertsNRQLConditionList != nil {
+ var isErr bool = false
+ for _, nrqlCondition := range alertPolicySet.AlertsConditionList.AlertsNRQLConditionList.AlertsNRQLConditions {
+ var cat newrelic.ConditionCategory = newrelic.ConditionNRQL
+ var ac = new(newrelic.AlertsConditionEntity)
+ ac.AlertsNRQLConditionEntity = &newrelic.AlertsNRQLConditionEntity{}
+ ac.AlertsNRQLConditionEntity.AlertsNRQLCondition = nrqlCondition
+ err, ret := RestoreOneCondition(*newAlertPolicy.ID, cat, ac, updateMode, isPolicyCreated)
+ if err != nil || ret.IsContinue == false {
+ isErr = true
+ break
+ }
+ }
+ if isErr == true {
+ goto next
+ }
+ }
+ }
+
+ if alertPolicySet.AlertsConditionList != nil {
+ if alertPolicySet.AlertsConditionList.AlertsPluginsConditionList != nil {
+ var isErr bool = false
+ for _, pluginsCondition := range alertPolicySet.AlertsConditionList.AlertsPluginsConditionList.AlertsPluginsConditions {
+ var cat newrelic.ConditionCategory = newrelic.ConditionPlugins
+ var ac = new(newrelic.AlertsConditionEntity)
+ ac.AlertsPluginsConditionEntity = &newrelic.AlertsPluginsConditionEntity{}
+ ac.AlertsPluginsConditionEntity.AlertsPluginsCondition = pluginsCondition
+ err, ret := RestoreOneCondition(*newAlertPolicy.ID, cat, ac, updateMode, isPolicyCreated)
+ if err != nil || ret.IsContinue == false {
+ isErr = true
+ break
+ }
+ }
+ if isErr == true {
+ goto next
+ }
+ }
+ }
+
+ if alertPolicySet.AlertsConditionList != nil {
+ if alertPolicySet.AlertsConditionList.AlertsSyntheticsConditionList != nil {
+ var isErr bool = false
+ for _, syntheticsCondition := range alertPolicySet.AlertsConditionList.AlertsSyntheticsConditionList.AlertsSyntheticsConditions {
+ var cat newrelic.ConditionCategory = newrelic.ConditionSynthetics
+ var ac = new(newrelic.AlertsConditionEntity)
+ ac.AlertsSyntheticsConditionEntity = &newrelic.AlertsSyntheticsConditionEntity{}
+ ac.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition = syntheticsCondition
+ err, ret := RestoreOneConditionForSynthetics(*newAlertPolicy.ID, cat, ac, updateMode, p.AlertDependencies.MonitorMap, isPolicyCreated)
+ if err != nil || ret.IsContinue == false {
+ isErr = true
+ break
+ }
+ }
+ if isErr == true {
+ goto next
+ }
+ }
+ }
+
+ //restore policy channels associations
+ err, ret = RestorePolicyChannels(*newAlertPolicy.ID, alertPolicySet.AlertsChannels, updateMode, isPolicyCreated)
+ if ret.IsContinue == false {
+ goto next
+ } else {
+ restoreAlertPolicyMeta.OperationStatus = "success"
+ goto next
+ }
+
+ next:
+ restoreAlertPolicyMetaArray = append(restoreAlertPolicyMetaArray, restoreAlertPolicyMeta)
+ }
+
+ var restoreAlertPolicyMetaList tracker.RestoreAlertPolicyMetaList = tracker.RestoreAlertPolicyMetaList{}
+ restoreAlertPolicyMetaList.AllRestoreAlertPolicyMeta = restoreAlertPolicyMetaArray
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+ tracker.PrintStatisticsInfo(restoreAlertPolicyMetaList)
+
+ writeFailRestoreConditionsFileList(resultFileName, restoreAlertPolicyMetaArray)
+ fmt.Println()
+
+ fmt.Printf("Restore alert conditions done.")
+
+ os.Exit(0)
+ },
+}
+
+func RestoreOnePolicy(alertsPolicy *newrelic.AlertsPolicy, mode string) (*newrelic.AlertsPolicy, bool, error, tracker.ReturnValue) {
+ isExist, policy, err, ret := get.IsPolicyNameExists(*alertsPolicy.Name)
+ if err != nil {
+ fmt.Println(err)
+ return nil, false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return nil, false, err, ret
+ }
+ }
+ var newAlertsPolicy *newrelic.AlertsPolicy
+ if mode == "skip" {
+ if isExist == true {
+ ret.IsContinue = true
+ return nil, false, err, ret
+ } else {
+ //create the policy
+ newAlertsPolicy, err, ret := create.CreateAlertsPolicy(alertsPolicy)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return nil, false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return nil, false, err, ret
+ }
+ return newAlertsPolicy, true, err, ret
+ }
+ }
+ } else if mode == "override" {
+ if isExist == true {
+ //update all by name
+ newAlertsPolicy, err, ret := update.UpdateByPolicyName(policy, *policy.Name)
+ if err != nil {
+ fmt.Println(err)
+ return nil, false, err, ret
+ }
+ if ret.IsContinue == false {
+ return nil, false, err, ret
+ }
+ return newAlertsPolicy, false, err, ret
+ } else {
+ //create the policy
+ newAlertsPolicy, err, ret := create.CreateAlertsPolicy(alertsPolicy)
+ if err != nil {
+ fmt.Println(err)
+ return nil, false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return nil, false, err, ret
+ }
+ return newAlertsPolicy, true, err, ret
+ }
+ }
+ } else if mode == "clean" {
+ if isExist == true {
+ //delete policy by name
+ err, ret := delete.DeletePolicyByName(*alertsPolicy.Name)
+ if err != nil {
+ fmt.Println(err)
+ return nil, false, err, ret
+ }
+ if ret.IsContinue == false {
+ return nil, false, err, ret
+ }
+ }
+ //create the policy
+ newAlertsPolicy, err, ret = create.CreateAlertsPolicy(alertsPolicy)
+ if err != nil {
+ fmt.Println(err)
+ return nil, false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return nil, false, err, ret
+ }
+ return newAlertsPolicy, true, err, ret
+ }
+ }
+ if err != nil {
+ fmt.Println(err)
+ return nil, false, err, ret
+ }
+
+ return nil, false, err, ret
+}
+
+func RestoreOneCondition(alertPolicyID int64, cat newrelic.ConditionCategory, c *newrelic.AlertsConditionEntity, mode string, isPolicyCreated bool) (error, tracker.ReturnValue) {
+ var err error
+ if isPolicyCreated == true {
+ //create conditions directly, because the alert policy was new created.
+ _, err, ret := create.CreateCondition(cat, c, alertPolicyID)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ } else {
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ } else {
+ //first check if condition exists by name, because the alert policy was updated.
+ //if so, update condtion, if not, create condition
+ //
+ var conditionName string = ""
+ switch cat {
+ case newrelic.ConditionDefault:
+ conditionName = *c.AlertsDefaultCondition.Name
+ case newrelic.ConditionExternalService:
+ conditionName = *c.AlertsExternalServiceCondition.Name
+ case newrelic.ConditionNRQL:
+ conditionName = *c.AlertsNRQLCondition.Name
+ case newrelic.ConditionPlugins:
+ conditionName = *c.AlertsPluginsCondition.Name
+ case newrelic.ConditionSynthetics:
+ conditionName = *c.AlertsSyntheticsCondition.Name
+ }
+ isConditionExists, conditionId, err, ret := get.IsConditionNameExists(alertPolicyID, conditionName, cat)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ if isConditionExists == true {
+ if mode == "skip" {
+ //do nothing
+ } else if mode == "override" {
+ //update condtion
+ _, err, ret := update.UpdateCondition(cat, c, conditionId)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ } else if mode == "clean" {
+ //delete current condition
+ err, ret := delete.DeleteCondition(cat, conditionId)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ //create condition
+ create.CreateCondition(cat, c, alertPolicyID)
+ }
+ } else {
+ //create condtion directly
+ create.CreateCondition(cat, c, alertPolicyID)
+ }
+
+ }
+ ret := tracker.ToReturnValue(true, "Restore one condtion", nil, nil, "")
+ return err, ret
+}
+
+func RestoreOneConditionForSynthetics(alertPolicyID int64, cat newrelic.ConditionCategory, c *newrelic.AlertsConditionEntity, mode string, monitorMap map[string]*newrelic.Monitor, isPolicyCreated bool) (error, tracker.ReturnValue) {
+ monitorId := c.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition.MonitorID
+ monitorName := monitorMap[*monitorId].Name
+ //check if monitor exist by monitorId
+ isExists, monitor, err, ret := get.IsMonitorNameExists(*monitorName)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ if isExists == true {
+ c.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition.MonitorID = monitor.ID
+ if mode == "skip" {
+ //do nothing
+ } else {
+ //update monitor by monitor name
+ err, returnValue := update.UpdateMonitorByID(monitor.ID, monitor, monitor.Script)
+ if err != nil {
+ fmt.Println(err)
+ return err, returnValue
+ }
+ if returnValue.IsContinue == false {
+ return err, returnValue
+ }
+ }
+ } else {
+ //create this synthetics monitor
+ monitor := monitorMap[*monitorId]
+
+ newMonitorId, err, returnValue := create.CreateMonitor(monitor, monitor.Script)
+ if err != nil {
+ fmt.Println(err)
+ return err, returnValue
+ }
+ if returnValue.IsContinue == false {
+
+ return returnValue.OriginalError, returnValue
+ } else {
+ c.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition.MonitorID = &newMonitorId
+ }
+ }
+
+ if isPolicyCreated == true {
+ //create conditions directly, because the alert policy was new created.
+ _, err, ret := create.CreateCondition(cat, c, alertPolicyID)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ } else {
+ //first check if condition exists by name, because the alert policy was updated.
+ //if so, update condtion, if not, create condition
+ //
+ isConditionExists, conditionId, err, ret := get.IsConditionNameExists(alertPolicyID, *c.AlertsSyntheticsCondition.Name, cat)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ if isConditionExists == true {
+ if mode == "skip" {
+ //do nothing
+ } else if mode == "override" {
+ //update condtion
+ _, err, ret := update.UpdateCondition(cat, c, conditionId)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ } else if mode == "clean" {
+ //delete current condition
+ err, ret := delete.DeleteCondition(cat, conditionId)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ //create condition
+ _, err, ret = create.CreateCondition(cat, c, alertPolicyID)
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ }
+ } else {
+ //create condtion directly
+ _, err, ret = create.CreateCondition(cat, c, alertPolicyID)
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ }
+
+ }
+
+ ret = tracker.ToReturnValue(true, "Restore one synthetics condtion", nil, nil, "")
+ return nil, ret
+}
+
+func RestorePolicyChannels(policyId int64, channels []*newrelic.AlertsChannel, mode string, isPolicyCreated bool) (error, tracker.ReturnValue) {
+ var channelIds []*int64
+ for _, channel := range channels {
+ isChannelExists, newChannel, err, ret := get.IsChannelNameExists(*channel.Name)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ if isChannelExists == true {
+ channelIds = append(channelIds, newChannel.ID)
+ }
+
+ }
+
+ var size = len(channelIds)
+ if size == 0 {
+ ret := tracker.ToReturnValue(false, "Restore policy channels", tracker.ERR_REST_CHANNEL_NOT_EXIST, tracker.ERR_REST_CHANNEL_NOT_EXIST, "")
+ return nil, ret
+ }
+
+ if isPolicyCreated == true {
+ err, ret := update.UpdatePolicyChannels(policyId, channelIds)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ } else {
+ if mode == "skip" {
+ //do nothing
+ } else if mode == "override" {
+ err, ret := update.UpdatePolicyChannels(policyId, channelIds)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ } else if mode == "clean" {
+ //create associations
+ err, ret := update.UpdatePolicyChannels(policyId, channelIds)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return err, ret
+ }
+ if ret.IsContinue == false {
+ return ret.OriginalError, ret
+ }
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, "Restore policy channels", nil, nil, "")
+ return nil, ret
+}
+
+func writeFailRestoreConditionsFileList(resultFileName string, restoreAlertPolicyMetaArray []tracker.RestoreAlertPolicyMeta) {
+ var totalCount = len(restoreAlertPolicyMetaArray)
+ var successCount int = 0
+ var failCount int = 0
+ var failInfoContent string = ""
+ for _, meta := range restoreAlertPolicyMetaArray {
+ if meta.OperationStatus == "fail" {
+ failCount++
+ failInfoContent = failInfoContent + meta.FileName + "\r\n"
+ } else {
+ successCount++
+ }
+ }
+ if failCount == 0 {
+ failInfoContent = "" //empty string to represent "no failed"
+ }
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(failInfoContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Println()
+ fmt.Printf("Alert conditoins to restore, total: " + strconv.Itoa(totalCount) + ", success: " + strconv.Itoa(successCount) + ", fail: " + strconv.Itoa(failCount))
+
+ if failCount > 0 {
+ os.Exit(1)
+ }
+}
+
+func exitRestoreAlertCondtionsWithError(returnValue tracker.ReturnValue) {
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ fmt.Println(returnValue.Description)
+ fmt.Println()
+
+ fmt.Println("Failed to restore alert conditions, exit.")
+ os.Exit(1)
+}
+
+func init() {
+ RestoreCmd.AddCommand(alertsconditionsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+
+}
diff --git a/cmd/restore/restore.go b/cmd/restore/restore.go
new file mode 100644
index 0000000..bdf8e34
--- /dev/null
+++ b/cmd/restore/restore.go
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package restore
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// RestoreCmd represents the update command
+var RestoreCmd = &cobra.Command{
+ Use: "restore",
+ Short: "Restore a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // RestoreCmd.PersistentFlags().String("foo", "", "A help for foo")
+ RestoreCmd.PersistentFlags().StringP("dir", "d", "", "Folder name where are files in to restore.")
+ // RestoreCmd.MarkPersistentFlagRequired("dir")
+
+ RestoreCmd.PersistentFlags().StringP("update-mode", "m", "skip", "Update mode. skip|override|clean are supported")
+
+ RestoreCmd.PersistentFlags().StringP("files", "f", "", "File names to restore. Multiple files separated by commma.")
+ RestoreCmd.PersistentFlags().StringP("File", "F", "", "Logging file stored failed resources to restore.")
+
+ RestoreCmd.PersistentFlags().StringP("result-file-name", "r", "", "Result file name")
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // UpdateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/restore/restore_dashboards.go b/cmd/restore/restore_dashboards.go
new file mode 100644
index 0000000..e24e510
--- /dev/null
+++ b/cmd/restore/restore_dashboards.go
@@ -0,0 +1,434 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package restore
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "strconv"
+ "strings"
+
+ "github.com/IBM/newrelic-cli/cmd/create"
+ "github.com/IBM/newrelic-cli/cmd/delete"
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/cmd/update"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+)
+
+var dashboardsCmd = &cobra.Command{
+ Use: "dashboards",
+ Short: "Restore dashboards from directory.",
+ Example: "nr restore dashboards -d ",
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var restoreFileFolder string
+ var err error
+ flags := cmd.Flags()
+ if flags.Lookup("dir") != nil {
+ restoreFileFolder, err = cmd.Flags().GetString("dir")
+ } else {
+ fmt.Println("Please give restore folder name.")
+ os.Exit(1)
+ return
+ }
+
+ var restoreFileNamesParam string
+ var restoreFileNames []string
+ flags = cmd.Flags()
+ if flags.Lookup("files") != nil {
+ restoreFileNamesParam, err = cmd.Flags().GetString("files")
+
+ if restoreFileNamesParam != "" {
+ restoreFileNames = strings.Split(restoreFileNamesParam, ",")
+ }
+ }
+
+ var restoreLoggingFileName string
+ flags = cmd.Flags()
+ if flags.Lookup("File") != nil {
+ restoreLoggingFileName, err = cmd.Flags().GetString("File")
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if restoreFileFolder == "" && restoreFileNamesParam == "" && restoreLoggingFileName == "" {
+ fmt.Println("Please give restore folder name, files path or logging file name.")
+ os.Exit(1)
+ return
+ }
+
+ var restoreFileNameList []string
+
+ if restoreFileFolder != "" {
+ f, err := os.Open(restoreFileFolder)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", restoreFileFolder, err)
+ os.Exit(1)
+ return
+ }
+
+ dir, err := ioutil.ReadDir(restoreFileFolder)
+
+ for _, fileInfo := range dir {
+ if fileInfo.IsDir() == false {
+ restoreFileName := fileInfo.Name()
+
+ isBak := strings.HasSuffix(restoreFileName, ".dashboard.bak")
+ if isBak == true {
+ var fileName = restoreFileFolder + "/" + restoreFileName
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ }
+ }
+ }
+
+ if restoreLoggingFileName != "" {
+ f, err := os.Open(restoreLoggingFileName)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open retore logging file '%v': %v\n", restoreLoggingFileName, err)
+ os.Exit(1)
+ return
+ }
+
+ buf := bufio.NewReader(f)
+ for {
+ line, err := buf.ReadString('\n')
+ line = strings.TrimSpace(line)
+ var fileName = line
+ isBak := strings.HasSuffix(fileName, ".dashboard.bak")
+ if isBak == true {
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ if err != nil {
+ if err != io.EOF {
+ os.Exit(1)
+ return
+ } else {
+ //end of file
+ break
+ }
+ }
+ }
+ }
+
+ if len(restoreFileNames) > 0 {
+ for _, fileName := range restoreFileNames {
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ }
+
+ var filesLen = len(restoreFileNameList)
+
+ if filesLen == 0 {
+ fmt.Printf("No files to restore found!")
+ os.Exit(1)
+ return
+ }
+
+ fmt.Println("Start to restore all dashboards")
+ fmt.Println()
+
+ var resultFileName string = ""
+ if flags.Lookup("result-file-name") != nil {
+ resultFileName, err = cmd.Flags().GetString("result-file-name")
+ }
+ if resultFileName == "" {
+ resultFileName = "fail-restore-dashboards-file-list.log"
+ }
+
+ var updateMode string = "skip"
+ if flags.Lookup("update-mode") != nil {
+ updateMode, err = cmd.Flags().GetString("update-mode")
+ }
+ fmt.Printf("Using update mode - %s\n", updateMode)
+
+ if updateMode == "clean" {
+ var ramArray []tracker.RestoreDashboardMeta
+ for _, restoreFileName := range restoreFileNameList {
+ var restoreDashboardMeta tracker.RestoreDashboardMeta = tracker.RestoreDashboardMeta{}
+ restoreDashboardMeta.FileName = restoreFileName
+
+ ramArray = append(ramArray, restoreDashboardMeta)
+ }
+
+ //delete all dashboards
+ resultStr, err, returnValue := get.GetAllDashboards()
+ if err != nil {
+ fmt.Println(err)
+ exitRestoreDashboardsWithError(returnValue)
+ writeFailRestoreDashboardsFileList(resultFileName, ramArray)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(err)
+ exitRestoreDashboardsWithError(returnValue)
+ writeFailRestoreDashboardsFileList(resultFileName, ramArray)
+ os.Exit(1)
+ return
+ }
+ dashboardArr := gjson.Parse(resultStr).Get("dashboards").Array()
+
+ for _, dashboard := range dashboardArr {
+ if dashboard.String() != "" {
+ id := gjson.Parse(dashboard.String()).Get("id")
+ title := gjson.Parse(dashboard.String()).Get("title")
+ fmt.Println(id.String())
+ fmt.Println(title.String())
+
+ dashboardId, _ := strconv.ParseInt(id.String(), 10, 64)
+ err, returnValue := delete.DeleteDashboardByID(dashboardId)
+ if err != nil {
+ fmt.Println(err)
+ exitRestoreDashboardsWithError(returnValue)
+ writeFailRestoreDashboardsFileList(resultFileName, ramArray)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(err)
+ exitRestoreDashboardsWithError(returnValue)
+ writeFailRestoreDashboardsFileList(resultFileName, ramArray)
+ os.Exit(1)
+ return
+ }
+ }
+ }
+
+ fmt.Println("Delete all dashboards completed.")
+ }
+
+ var restoreDashboardMetaArray []tracker.RestoreDashboardMeta
+
+ for _, restoreFileName := range restoreFileNameList {
+
+ var restoreDashboardMeta tracker.RestoreDashboardMeta = tracker.RestoreDashboardMeta{}
+ restoreDashboardMeta.FileName = restoreFileName
+ restoreDashboardMeta.OperationStatus = "fail"
+
+ restoreFile, err := os.Open(restoreFileName)
+ defer restoreFile.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", restoreFileName, err)
+ continue
+ }
+
+ bytes, err := ioutil.ReadFile(restoreFileName)
+ if err != nil {
+ fmt.Print(err)
+ continue
+ }
+ fileContent := string(bytes)
+ if !gjson.Valid(fileContent) {
+ fmt.Printf("Incorrect JSON format: %v.\n", errors.New("invalid json"))
+ continue
+ }
+
+ isRestored, err, ret := RestoreOneDashboard(fileContent, updateMode)
+ if err != nil {
+ fmt.Println(err)
+ goto next
+ }
+ if ret.IsContinue == false {
+ goto next
+ } else {
+ if isRestored == true {
+ restoreDashboardMeta.OperationStatus = "success"
+ }
+ goto next
+ }
+
+ next:
+ restoreDashboardMetaArray = append(restoreDashboardMetaArray, restoreDashboardMeta)
+ }
+
+ var restoreDashboardMetaList tracker.RestoreDashboardMetaList = tracker.RestoreDashboardMetaList{}
+ restoreDashboardMetaList.AllRestoreDashboardMeta = restoreDashboardMetaArray
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+ tracker.PrintStatisticsInfo(restoreDashboardMetaList)
+
+ writeFailRestoreDashboardsFileList(resultFileName, restoreDashboardMetaArray)
+ fmt.Println()
+
+ fmt.Printf("Restore alert dashboards done.")
+
+ os.Exit(0)
+ },
+}
+
+func RestoreOneDashboard(dashboardContent string, mode string) (bool, error, tracker.ReturnValue) {
+
+ title := gjson.Parse(dashboardContent).Get("dashboard.title").String()
+ isExist, _, err, ret := get.IsDashboardTitleExists(title)
+ if err != nil {
+ fmt.Println(err)
+ return false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return false, err, ret
+ }
+ }
+
+ // var newDashboard string
+ if mode == "skip" {
+ if isExist == true {
+ ret.IsContinue = true
+ return true, err, ret
+ } else {
+ //create the dashboard
+ _, err, ret := create.CreateDashboard(dashboardContent)
+ if err != nil {
+ fmt.Println(err)
+ ret.IsContinue = false
+ return false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return false, err, ret
+ }
+ return true, err, ret
+ }
+ }
+ } else if mode == "override" {
+ if isExist == true {
+ //update all by title
+ title := gjson.Parse(dashboardContent).Get("dashboard.title").String()
+ err, ret := update.UpdateByDashboardTitle(dashboardContent, title)
+ if err != nil {
+ fmt.Println(err)
+ return false, err, ret
+ }
+ if ret.IsContinue == false {
+ return false, err, ret
+ }
+ return true, err, ret
+ } else {
+ //create the dashboard
+ _, err, ret := create.CreateDashboard(dashboardContent)
+ if err != nil {
+ fmt.Println(err)
+ return false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return false, err, ret
+ }
+ return true, err, ret
+ }
+ }
+ } else if mode == "clean" {
+ if isExist == true {
+ //delete dashbaord by title
+ title := gjson.Parse(dashboardContent).Get("dashboard.title").String()
+ err, ret := delete.DeleteByDashboardTitle(title)
+ if err != nil {
+ fmt.Println(err)
+ return false, err, ret
+ }
+ if ret.IsContinue == false {
+ return false, err, ret
+ }
+ }
+ //create the dashboard
+ _, err, ret = create.CreateDashboard(dashboardContent)
+ if err != nil {
+ fmt.Println(err)
+ return false, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return false, err, ret
+ }
+ return true, err, ret
+ }
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ return false, err, ret
+ }
+
+ return true, nil, ret
+}
+
+func exitRestoreDashboardsWithError(returnValue tracker.ReturnValue) {
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ fmt.Println(returnValue.Description)
+ fmt.Println()
+
+ fmt.Println("Failed to restore dashboards, exit.")
+ os.Exit(1)
+}
+
+func writeFailRestoreDashboardsFileList(resultFileName string, restoreDashboardMetaArray []tracker.RestoreDashboardMeta) {
+ var totalCount = len(restoreDashboardMetaArray)
+ var successCount int = 0
+ var failCount int = 0
+ var failInfoContent string = ""
+ for _, meta := range restoreDashboardMetaArray {
+ if meta.OperationStatus == "fail" {
+ failCount++
+ failInfoContent = failInfoContent + meta.FileName + "\r\n"
+ } else {
+ successCount++
+ }
+ }
+ if failCount == 0 {
+ failInfoContent = "" //empty string to represent "no failed"
+ }
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(failInfoContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Println()
+ fmt.Printf("Dashboards to restore, total: " + strconv.Itoa(totalCount) + ", success: " + strconv.Itoa(successCount) + ", fail: " + strconv.Itoa(failCount))
+
+ if failCount > 0 {
+ os.Exit(1)
+ }
+}
+
+func init() {
+ RestoreCmd.AddCommand(dashboardsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+
+}
diff --git a/cmd/restore/restore_monitors.go b/cmd/restore/restore_monitors.go
new file mode 100644
index 0000000..543eb97
--- /dev/null
+++ b/cmd/restore/restore_monitors.go
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package restore
+
+import (
+ "bufio"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strconv"
+ "strings"
+
+ "github.com/IBM/newrelic-cli/cmd/create"
+ "github.com/IBM/newrelic-cli/cmd/delete"
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/cmd/update"
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var monitorsCmd = &cobra.Command{
+ Use: "monitors",
+ Short: "Restore monitors from directory.",
+ Example: "nr restore monitors -d ",
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var restoreFileFolder string
+ var err error
+ flags := cmd.Flags()
+ if flags.Lookup("dir") != nil {
+ restoreFileFolder, err = cmd.Flags().GetString("dir")
+ } else {
+ fmt.Println("Please give restore folder name.")
+ os.Exit(1)
+ return
+ }
+
+ var restoreFileNamesParam string
+ var restoreFileNames []string
+ flags = cmd.Flags()
+ if flags.Lookup("files") != nil {
+ restoreFileNamesParam, err = cmd.Flags().GetString("files")
+
+ if restoreFileNamesParam != "" {
+ restoreFileNames = strings.Split(restoreFileNamesParam, ",")
+ }
+ }
+
+ var restoreLoggingFileName string
+ flags = cmd.Flags()
+ if flags.Lookup("File") != nil {
+ restoreLoggingFileName, err = cmd.Flags().GetString("File")
+ }
+
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if restoreFileFolder == "" && restoreFileNamesParam == "" && restoreLoggingFileName == "" {
+ fmt.Println("Please give restore folder name, files path or logging file name.")
+ os.Exit(1)
+ return
+ }
+
+ var restoreFileNameList []string
+
+ if restoreFileFolder != "" {
+ f, err := os.Open(restoreFileFolder)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", restoreFileFolder, err)
+ os.Exit(1)
+ return
+ }
+
+ dir, err := ioutil.ReadDir(restoreFileFolder)
+
+ for _, fileInfo := range dir {
+ if fileInfo.IsDir() == false {
+ restoreFileName := fileInfo.Name()
+
+ isBak := strings.HasSuffix(restoreFileName, ".monitor.bak")
+ if isBak == true {
+ var fileName = restoreFileFolder + "/" + restoreFileName
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ }
+ }
+ }
+
+ if restoreLoggingFileName != "" {
+ f, err := os.Open(restoreLoggingFileName)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open retore logging file '%v': %v\n", restoreLoggingFileName, err)
+ os.Exit(1)
+ return
+ }
+
+ buf := bufio.NewReader(f)
+ for {
+ line, err := buf.ReadString('\n')
+ line = strings.TrimSpace(line)
+ var fileName = line
+ isBak := strings.HasSuffix(fileName, ".monitor.bak")
+ if isBak == true {
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ if err != nil {
+ if err != io.EOF {
+ os.Exit(1)
+ return
+ } else {
+ //end of file
+ break
+ }
+ }
+ }
+ }
+
+ if len(restoreFileNames) > 0 {
+ for _, fileName := range restoreFileNames {
+ restoreFileNameList = append(restoreFileNameList, fileName)
+ }
+ }
+
+ var filesLen = len(restoreFileNameList)
+
+ if filesLen == 0 {
+ fmt.Printf("No files to restore found!")
+ os.Exit(1)
+ return
+ }
+
+ fmt.Println("Start to restore all monitors")
+ fmt.Println()
+
+ var resultFileName string = ""
+ if flags.Lookup("result-file-name") != nil {
+ resultFileName, err = cmd.Flags().GetString("result-file-name")
+ }
+ if resultFileName == "" {
+ resultFileName = "fail-restore-monitors-file-list.log"
+ }
+
+ var updateMode string = "skip"
+ if flags.Lookup("update-mode") != nil {
+ updateMode, err = cmd.Flags().GetString("update-mode")
+ }
+ fmt.Printf("Using update mode - %s\n", updateMode)
+
+ if updateMode == "clean" {
+ var rmmArray []tracker.RestoreMonitorMeta
+ for _, restoreFileName := range restoreFileNameList {
+ var restoreMonitorMeta tracker.RestoreMonitorMeta = tracker.RestoreMonitorMeta{}
+ restoreMonitorMeta.FileName = restoreFileName
+
+ rmmArray = append(rmmArray, restoreMonitorMeta)
+ }
+
+ //delete all monitors
+ monitors, err, returnValue := get.GetMonitors()
+ if err != nil {
+ fmt.Println(err)
+ writeFailRestoreMonitorsFileList(resultFileName, rmmArray)
+ exitRestoreMonitorWithError(returnValue)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(err)
+ writeFailRestoreMonitorsFileList(resultFileName, rmmArray)
+ exitRestoreMonitorWithError(returnValue)
+ os.Exit(1)
+ return
+ }
+ fmt.Println()
+ fmt.Println("Deleting all monitors...")
+ for _, monitor := range monitors {
+ err, returnValue := delete.DeleteMonitorByID(*monitor.ID)
+ if err != nil {
+ fmt.Println(err)
+ writeFailRestoreMonitorsFileList(resultFileName, rmmArray)
+ exitRestoreMonitorWithError(returnValue)
+ os.Exit(1)
+ return
+ }
+ if returnValue.IsContinue == false {
+ fmt.Println(err)
+ writeFailRestoreMonitorsFileList(resultFileName, rmmArray)
+ exitRestoreMonitorWithError(returnValue)
+ os.Exit(1)
+ return
+ }
+ }
+ }
+
+ var restoreMonitorMetaArray []tracker.RestoreMonitorMeta
+
+ for _, restoreFileName := range restoreFileNameList {
+ var restoreMonitorMeta tracker.RestoreMonitorMeta = tracker.RestoreMonitorMeta{}
+ restoreMonitorMeta.FileName = restoreFileName
+
+ fmt.Println("start to restore monitor in file: " + restoreFileName)
+ isBak := strings.HasSuffix(restoreFileName, ".monitor.bak")
+ if isBak == true {
+
+ restoreFile, err := os.Open(restoreFileName)
+ defer restoreFile.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", restoreFileName, err)
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(restoreFile, 4096)
+ var p = new(*newrelic.Monitor)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", restoreFileName, err)
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ }
+ if reflect.DeepEqual(new([]*newrelic.Monitor), p) {
+ fmt.Printf("Error validating %q.\n", restoreFileName)
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ }
+
+ monitor := *p
+
+ // restoreMonitorMeta.Name = *monitor.Name
+ restoreMonitorMeta.Type = *monitor.Type
+ if *monitor.Type == "SCRIPT_BROWSER" || *monitor.Type == "SCRIPT_API" {
+ restoreMonitorMeta.Script = true
+ } else {
+ restoreMonitorMeta.Script = false
+ }
+ var labelLen = len(monitor.Labels)
+ restoreMonitorMeta.LabelCount = labelLen
+ if labelLen > 0 {
+ for _, label := range monitor.Labels {
+ restoreMonitorMeta.Labels = append(restoreMonitorMeta.Labels, *label)
+ }
+ }
+ restoreMonitorMeta.OperationStatus = "fail"
+
+ if updateMode == "clean" {
+ //create all monitors
+ fmt.Println()
+ fmt.Println("Creating one monitor...")
+
+ var scriptTextEncoded *newrelic.Script = nil
+ if *monitor.Type == "SCRIPT_BROWSER" || *monitor.Type == "SCRIPT_API" {
+ scriptTextEncoded = monitor.Script
+ }
+ _, err, returnValue := create.CreateMonitor(monitor, scriptTextEncoded)
+ if err != nil {
+ restoreMonitorMeta.OperationStatus = "fail"
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ } else {
+ if returnValue.IsContinue == false {
+ restoreMonitorMeta.OperationStatus = "fail"
+
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ } else {
+ restoreMonitorMeta.OperationStatus = "success"
+ }
+ }
+ fmt.Println()
+ fmt.Println("Restore monitor done, file name: " + restoreFileName)
+ } else {
+
+ var scriptTextEncoded *newrelic.Script = nil
+ if *monitor.Type == "SCRIPT_BROWSER" || *monitor.Type == "SCRIPT_API" {
+ scriptTextEncoded = monitor.Script
+ }
+ backupMonitorId := monitor.ID
+ //try to create, if response status code is 400, monitor exist, then update
+ // _, err, returnValue := create.CreateMonitor(monitor, scriptTextEncoded)
+ isExists, _, err, returnValue := get.IsMonitorNameExists(*monitor.Name)
+ if err != nil {
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ } else {
+ if returnValue.IsContinue == false {
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ }
+ if isExists == false {
+ _, err, returnValue := create.CreateMonitor(monitor, scriptTextEncoded)
+ if err != nil {
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ } else {
+ if returnValue.IsContinue == false {
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ }
+ restoreMonitorMeta.OperationStatus = "success"
+ }
+ } else {
+ if updateMode == "override" {
+ //update monitor
+ monitor.ID = backupMonitorId
+ err, ret := update.UpdateMonitorByName(monitor, scriptTextEncoded)
+ if err != nil {
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ } else {
+ if ret.IsContinue == false {
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ continue
+ }
+ restoreMonitorMeta.OperationStatus = "success"
+ }
+ } else if updateMode == "skip" {
+ //skip, do nothing
+ fmt.Printf("Monitor '%s' already exists, skip.\n", *monitor.Name)
+ restoreMonitorMeta.OperationStatus = "success"
+ // restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ }
+ fmt.Println("Restore monitor done, file name: " + restoreFileName)
+ }
+ }
+ }
+
+ restoreMonitorMetaArray = append(restoreMonitorMetaArray, restoreMonitorMeta)
+ }
+ }
+
+ var restoreMonitorMetaList tracker.RestoreMonitorMetaList = tracker.RestoreMonitorMetaList{}
+ restoreMonitorMetaList.AllRestoreMonitorMeta = restoreMonitorMetaArray
+
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+ tracker.PrintStatisticsInfo(restoreMonitorMetaList)
+
+ writeFailRestoreMonitorsFileList(resultFileName, restoreMonitorMetaArray)
+
+ fmt.Println()
+ fmt.Printf("Restore monitors done.\n")
+
+ os.Exit(0)
+ },
+}
+
+func writeFailRestoreMonitorsFileList(resultFileName string, restoreMonitorMetaArray []tracker.RestoreMonitorMeta) {
+ var totalCount = len(restoreMonitorMetaArray)
+ var successCount int = 0
+ var failCount int = 0
+ var failInfoContent string = ""
+ for _, meta := range restoreMonitorMetaArray {
+ if meta.OperationStatus == "fail" {
+ failCount++
+ failInfoContent = failInfoContent + meta.FileName + "\r\n"
+ } else {
+ successCount++
+ }
+ }
+ if failCount == 0 {
+ failInfoContent = "" //empty string to represent "no failed"
+ }
+ var fileLogName = resultFileName
+ err := ioutil.WriteFile(fileLogName, []byte(failInfoContent), 0666)
+ if err != nil {
+ fmt.Println(err)
+ }
+
+ fmt.Println()
+ fmt.Printf("Monitors to restore, total: " + strconv.Itoa(totalCount) + ", success: " + strconv.Itoa(successCount) + ", fail: " + strconv.Itoa(failCount))
+
+ if failCount > 0 {
+ os.Exit(1)
+ }
+}
+
+func exitRestoreMonitorWithError(returnValue tracker.ReturnValue) {
+ //print REST call
+ tracker.PrintStatisticsInfo(tracker.GlobalRESTCallResultList)
+ fmt.Println()
+
+ fmt.Println(returnValue.OriginalError)
+ fmt.Println(returnValue.TypicalError)
+ fmt.Println(returnValue.Description)
+ fmt.Println()
+
+ fmt.Println("Failed to restore monitors, exit.")
+ os.Exit(1)
+}
+
+func init() {
+ RestoreCmd.AddCommand(monitorsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+
+}
diff --git a/cmd/root.go b/cmd/root.go
new file mode 100644
index 0000000..8526617
--- /dev/null
+++ b/cmd/root.go
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package cmd
+
+import (
+ "fmt"
+ "os"
+
+ addCmd "github.com/IBM/newrelic-cli/cmd/add"
+ backupCmd "github.com/IBM/newrelic-cli/cmd/backup"
+ createCmd "github.com/IBM/newrelic-cli/cmd/create"
+ deleteCmd "github.com/IBM/newrelic-cli/cmd/delete"
+ getCmd "github.com/IBM/newrelic-cli/cmd/get"
+ insertCmd "github.com/IBM/newrelic-cli/cmd/insert"
+ patchCmd "github.com/IBM/newrelic-cli/cmd/patch"
+ restoreCmd "github.com/IBM/newrelic-cli/cmd/restore"
+ updateCmd "github.com/IBM/newrelic-cli/cmd/update"
+ homedir "github.com/mitchellh/go-homedir"
+ "github.com/spf13/cobra"
+ "github.com/spf13/viper"
+)
+
+var cfgFile string
+
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
+ Use: "nr",
+ Short: "nr is a command line tool for NewRelic",
+ // Long: `A longer description that spans multiple lines and likely contains
+ // examples and usage of using your application. For example:
+
+ // Cobra is a CLI library for Go that empowers applications.
+ // This application is a tool to generate the needed files
+ // to quickly create a Cobra application.`,
+ // Uncomment the following line if your bare application
+ // has an action associated with it:
+ // Run: func(cmd *cobra.Command, args []string) {},
+}
+
+// Execute adds all child commands to the root command and sets flags appropriately.
+// This is called by main.main(). It only needs to happen once to the rootCmd.
+func Execute() {
+ if err := rootCmd.Execute(); err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+}
+
+func init() {
+ cobra.OnInitialize(initConfig)
+
+ // Here you will define your flags and configuration settings.
+ // Cobra supports persistent flags, which, if defined here,
+ // will be global for your application.
+ // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.nr.yaml)")
+
+ // Cobra also supports local flags, which will only run
+ // when this action is called directly.
+ // rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+
+ rootCmd.AddCommand(getCmd.GetCmd)
+ rootCmd.AddCommand(deleteCmd.DeleteCmd)
+ rootCmd.AddCommand(createCmd.CreateCmd)
+ rootCmd.AddCommand(updateCmd.UpdateCmd)
+ rootCmd.AddCommand(patchCmd.PatchCmd)
+ rootCmd.AddCommand(backupCmd.BackupCmd)
+ rootCmd.AddCommand(restoreCmd.RestoreCmd)
+ rootCmd.AddCommand(addCmd.AddCmd)
+ rootCmd.AddCommand(insertCmd.InsertCmd)
+}
+
+// initConfig reads in config file and ENV variables if set.
+func initConfig() {
+ if cfgFile != "" {
+ // Use config file from the flag.
+ viper.SetConfigFile(cfgFile)
+ } else {
+ // Find home directory.
+ home, err := homedir.Dir()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ }
+
+ // Search config in home directory with name ".nr" (without extension).
+ viper.AddConfigPath(home)
+ viper.SetConfigName(".nr")
+ }
+
+ viper.AutomaticEnv() // read in environment variables that match
+
+ // If a config file is found, read it in.
+ viper.ReadInConfig()
+ // if err := viper.ReadInConfig(); err == nil {
+ // fmt.Println("Using config file:", viper.ConfigFileUsed())
+ // }
+}
diff --git a/cmd/update/update.go b/cmd/update/update.go
new file mode 100644
index 0000000..067bd83
--- /dev/null
+++ b/cmd/update/update.go
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package update
+
+import (
+ "github.com/spf13/cobra"
+)
+
+// UpdateCmd represents the update command
+var UpdateCmd = &cobra.Command{
+ Use: "update",
+ Short: "Update a NewRelic resource using specified subcommand.",
+}
+
+func init() {
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // UpdateCmd.PersistentFlags().String("foo", "", "A help for foo")
+ UpdateCmd.PersistentFlags().StringP("file", "f", "", "Filename to update resource with, yaml/json format is supported.")
+ UpdateCmd.MarkPersistentFlagRequired("file")
+
+ UpdateCmd.PersistentFlags().StringP("output", "o", "json", "Output format. json/yaml are supported")
+
+ UpdateCmd.PersistentFlags().StringP("type-condition", "t", "default", "Alert condition type. Only used for 'alertsconditions' command. default|sythentics|ext|plugin|nrql are supported")
+
+ UpdateCmd.PersistentFlags().StringP("script-file", "s", "", "Synthetics monitor javascript file name. Only used for 'monitor' command.")
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // UpdateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/update/update_alertschannels.go b/cmd/update/update_alertschannels.go
new file mode 100644
index 0000000..04af1e7
--- /dev/null
+++ b/cmd/update/update_alertschannels.go
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package update
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var alertschannelsCmd = &cobra.Command{
+ Use: "alertschannels",
+ Short: "Update policy/channel associations from a file.",
+ Example: "nr update alertschannels -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var p = new(newrelic.PolicyChannelsAssociation)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.PolicyChannelsAssociation), p) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+
+ // start to udpate
+ err, _ = UpdatePolicyChannels(*p.PolicyID, p.ChannelIDList)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ os.Exit(0)
+ },
+}
+
+func UpdatePolicyChannels(policyId int64, channelIds []*int64) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_CHANNEL, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+
+ resp, err := client.AlertsChannels.UpdatePolicyChannels(context.Background(), policyId, channelIds)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_CHANNEL, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.AlertsChannels, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_CHANNEL, resp.StatusCode, "")
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update policy and channels associations.'\n", statusCode)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_CHANNEL, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_CHANNEL, nil, nil, "")
+ return nil, ret
+}
+
+func init() {
+ UpdateCmd.AddCommand(alertschannelsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/update/update_alertsconditions.go b/cmd/update/update_alertsconditions.go
new file mode 100644
index 0000000..24b63b3
--- /dev/null
+++ b/cmd/update/update_alertsconditions.go
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package update
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var alertsconditionsCmd = &cobra.Command{
+ Use: "alertsconditions",
+ Short: "Update alerts_conditions from a file.",
+ Aliases: []string{"ac", "alertcondition", "alertscondition"},
+ Example: "nr update alertsconditions -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+
+ flags := cmd.Flags()
+ var conditionType string
+ var errConditionType error
+ if flags.Lookup("type-condition") != nil {
+
+ conditionType, errConditionType = cmd.Flags().GetString("type-condition")
+ if errConditionType != nil {
+ fmt.Printf("error accessing flag %s for command %s: %v\n", "type-condition", cmd.Name(), errConditionType)
+ os.Exit(1)
+ return
+ }
+
+ var alertConditionID int64
+
+ var cat newrelic.ConditionCategory
+ var ac = new(newrelic.AlertsConditionEntity)
+
+ if conditionType == "plugins" {
+ var ace = new(newrelic.AlertsPluginsConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for plugins type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsPluginsConditionEntity), ace) {
+ fmt.Printf("Error validating for plugins type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ cat = newrelic.ConditionPlugins
+ ac.AlertsPluginsConditionEntity = ace
+ alertConditionID = *ac.AlertsPluginsConditionEntity.AlertsPluginsCondition.ID
+ } else if conditionType == "synthetics" {
+ var ace = new(newrelic.AlertsSyntheticsConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for synthetics type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsSyntheticsConditionEntity), ace) {
+ fmt.Printf("Error validating for synthetics type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ cat = newrelic.ConditionSynthetics
+ ac.AlertsSyntheticsConditionEntity = ace
+ alertConditionID = *ac.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition.ID
+ } else if conditionType == "ext" {
+ var ace = new(newrelic.AlertsExternalServiceConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for ext type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsExternalServiceConditionEntity), ace) {
+ fmt.Printf("Error validating for ext type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ cat = newrelic.ConditionExternalService
+ ac.AlertsExternalServiceConditionEntity = ace
+ alertConditionID = *ac.AlertsExternalServiceConditionEntity.AlertsExternalServiceCondition.ID
+ } else if conditionType == "nrql" {
+ var ace = new(newrelic.AlertsNRQLConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for nrql type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsNRQLConditionEntity), ace) {
+ fmt.Printf("Error validating for nrql type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ cat = newrelic.ConditionNRQL
+ ac.AlertsNRQLConditionEntity = ace
+ alertConditionID = *ac.AlertsNRQLConditionEntity.AlertsNRQLCondition.ID
+ } else {
+ var ace = new(newrelic.AlertsDefaultConditionEntity)
+ err = decorder.Decode(ace)
+ if err != nil {
+ fmt.Printf("Unable to decode for default type condition %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsDefaultConditionEntity), ace) {
+ fmt.Printf("Error validating for default type condition %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ cat = newrelic.ConditionDefault
+ ac.AlertsDefaultConditionEntity = ace
+ alertConditionID = *ac.AlertsDefaultConditionEntity.AlertsDefaultCondition.ID
+ }
+ // start to update
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ _, resp, err := client.AlertsConditions.Update(context.Background(), cat, ac, alertConditionID)
+ if err != nil {
+ fmt.Printf("Failed to update condition, %v\n", err)
+ os.Exit(1)
+ return
+ } else {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update alert conditions, condition id: '%d'\n", statusCode, alertConditionID)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ } else {
+ fmt.Println("Can not find type-condition argument.")
+ os.Exit(1)
+ return
+ }
+ os.Exit(0)
+ },
+}
+
+func UpdateCondition(cat newrelic.ConditionCategory, ac *newrelic.AlertsConditionEntity, alertConditionID int64) (*newrelic.AlertsConditionEntity, error, tracker.ReturnValue) {
+ // start to update
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_CONDITION_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ alertsConditionEntity, resp, err := client.AlertsConditions.Update(context.Background(), cat, ac, alertConditionID)
+ if err != nil {
+ fmt.Printf("Failed to update condition, %v\n", err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_CONDITION_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.AlertsConditions, tracker.OPERATION_NAME_UPDATE_ALERT_CONDITION_BY_ID, resp.StatusCode, "alert condtion id:"+strconv.FormatInt(alertConditionID, 10))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update alert conditions, condition id: '%d'\n", statusCode, alertConditionID)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_CONDITION_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_ALERT_CONDITION_BY_ID, nil, nil, "")
+ return alertsConditionEntity, err, ret
+}
+
+func init() {
+ UpdateCmd.AddCommand(alertsconditionsCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertsconditionsCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertsconditionsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/update/update_alertspolicies.go b/cmd/update/update_alertspolicies.go
new file mode 100644
index 0000000..bb6d0f5
--- /dev/null
+++ b/cmd/update/update_alertspolicies.go
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package update
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+)
+
+var alertspoliciesCmd = &cobra.Command{
+ Use: "alertspolicies",
+ Short: "Update alerts_policies from a file.",
+ Aliases: []string{"ap", "alertpolicy", "alertspolicy"},
+ Example: "nr update alertspolicies -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var p = new(newrelic.AlertsPolicyEntity)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.AlertsPolicy), p) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ if p.AlertsPolicy.ID == nil {
+ fmt.Printf("Can't find {.policy.id} in %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ // start Update
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+ _, resp, err := client.AlertsPolicies.Update(context.Background(), p, *p.AlertsPolicy.ID)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.Status)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func UpdateByPolicyID(policy *newrelic.AlertsPolicyEntity, alertPolicyID int64) (*newrelic.AlertsPolicyEntity, error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return nil, err, ret
+ }
+ policyEntity, resp, err := client.AlertsPolicies.Update(context.Background(), policy, alertPolicyID)
+ if err != nil {
+ fmt.Printf("Failed to update alert policy, %v\n", err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return nil, err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.AlertsPolicies, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_BY_ID, resp.StatusCode, "alert policy id:"+strconv.FormatInt(alertPolicyID, 10)+",alert policy name:"+(*policy.AlertsPolicy.Name))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update alert policy, alert policy id: '%d'\n", statusCode, alertPolicyID)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return nil, err, ret
+ }
+ }
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_BY_ID, nil, nil, "")
+ return policyEntity, err, ret
+}
+
+func UpdateByPolicyName(policy *newrelic.AlertsPolicy, policyName string) (*newrelic.AlertsPolicy, error, tracker.ReturnValue) {
+ list, err, ret := get.GetAllAlertPolicies()
+ if err != nil {
+ fmt.Println(err)
+ return nil, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return nil, err, ret
+ }
+ }
+ for _, p := range list.AlertsPolicies {
+ if *p.Name == policyName {
+ policy.ID = p.ID
+ var pEntity *newrelic.AlertsPolicyEntity = &newrelic.AlertsPolicyEntity{}
+ pEntity.AlertsPolicy = policy
+ newPolicy, err, ret := UpdateByPolicyID(pEntity, *policy.ID)
+ if err != nil {
+ fmt.Println(err)
+ return nil, err, ret
+ } else {
+ if ret.IsContinue == false {
+ return nil, err, ret
+ }
+ }
+ return newPolicy.AlertsPolicy, err, ret
+ }
+ }
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_ALERT_POLICY_BY_NAME, nil, nil, "")
+ return nil, err, ret
+}
+
+func init() {
+ UpdateCmd.AddCommand(alertspoliciesCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/update/update_dashboard.go b/cmd/update/update_dashboard.go
new file mode 100644
index 0000000..83eeba3
--- /dev/null
+++ b/cmd/update/update_dashboard.go
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package update
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+ "github.com/spf13/cobra"
+ "github.com/tidwall/gjson"
+ "github.com/tidwall/sjson"
+)
+
+var dashboardCmd = &cobra.Command{
+ Use: "dashboard",
+ Short: "Update dashboard from a json file.",
+ Example: "nr update dashboard -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ fileName, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ bytes, err := ioutil.ReadFile(fileName)
+ if err != nil {
+ fmt.Print(err)
+ os.Exit(1)
+ return
+ }
+ fileContent := string(bytes)
+ if !gjson.Valid(fileContent) {
+ fmt.Printf("Incorrect JSON format: %v.\n", errors.New("invalid json"))
+ os.Exit(1)
+ return
+ }
+
+ //start to update
+ id := gjson.Parse(fileContent).Get("id").String()
+ dashboardId, _ := strconv.ParseInt(id, 10, 64)
+ UpdateDashboardByID(fileContent, dashboardId)
+ },
+}
+
+func UpdateDashboardByID(dashboard string, id int64) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient()
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_DASHBOARD_BY_ID, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ title := gjson.Parse(dashboard).Get("title").String()
+
+ resp, bytes, err := client.Dashboards.Update(context.Background(), dashboard, id)
+
+ var retMsg string
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_DASHBOARD_BY_ID, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ retMsg = string(bytes)
+ tracker.AppendRESTCallResult(client.Dashboards, tracker.OPERATION_NAME_UPDATE_DASHBOARD_BY_ID, resp.StatusCode, "dashboard title:"+title+", dashboard id:"+strconv.FormatInt(id, 10))
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update dashboard '%s'', dashboard id: '%d'\n", statusCode, title, id)
+ if resp.StatusCode >= 400 {
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_DASHBOARD_BY_ID, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, retMsg)
+ return err, ret
+ }
+ }
+
+ ret := tracker.ToReturnValue(true, tracker.OPERATION_NAME_CREATE_DASHBOARD, nil, nil, "")
+ return err, ret
+}
+
+func UpdateByDashboardTitle(dashboardContent string, title string) (error, tracker.ReturnValue) {
+ resultStr, err, ret := get.GetAllDashboards()
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ } else {
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ dashboardArr := gjson.Parse(resultStr).Get("dashboards").Array()
+ for _, existDashboard := range dashboardArr {
+ t := gjson.Parse(existDashboard.String()).Get("title").String()
+ if t == title {
+ id := gjson.Parse(existDashboard.String()).Get("id")
+ dashboardContent2, _ := sjson.Set(dashboardContent, "dashboard.id", id.Num)
+ fmt.Println(dashboardContent2)
+ dashboardId, _ := strconv.ParseInt(id.String(), 10, 64)
+ err, ret := UpdateDashboardByID(dashboardContent2, dashboardId)
+ if err != nil {
+ fmt.Println(err)
+ return err, ret
+ } else {
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ return err, ret
+ }
+ }
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_DASHBOARD_BY_NAME, nil, nil, "")
+ return err, ret
+}
diff --git a/cmd/update/update_monitor.go b/cmd/update/update_monitor.go
new file mode 100644
index 0000000..399b2ab
--- /dev/null
+++ b/cmd/update/update_monitor.go
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package update
+
+import (
+ "context"
+ "encoding/base64"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "reflect"
+ "strings"
+
+ "github.com/spf13/cobra"
+
+ "github.com/IBM/newrelic-cli/cmd/add"
+ "github.com/IBM/newrelic-cli/cmd/delete"
+ "github.com/IBM/newrelic-cli/cmd/get"
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/tracker"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+var monitorCmd = &cobra.Command{
+ Use: "monitor",
+ Short: "Update monitor from a file.",
+ Example: "nr update monitor -f ",
+ Run: func(cmd *cobra.Command, args []string) {
+ file, err := utils.GetArg(cmd, "file")
+ if err != nil {
+ fmt.Printf("Unable to get argument 'file': %v\n", err)
+ os.Exit(1)
+ return
+ }
+ f, err := os.Open(file)
+ defer f.Close()
+ if err != nil {
+ fmt.Printf("Unable to open file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ // validation
+ decorder := utils.NewYAMLOrJSONDecoder(f, 4096)
+ var p = new(newrelic.Monitor)
+ err = decorder.Decode(p)
+ if err != nil {
+ fmt.Printf("Unable to decode %q: %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ if reflect.DeepEqual(new(newrelic.Monitor), p) {
+ fmt.Printf("Error validating %q.\n", file)
+ os.Exit(1)
+ return
+ }
+ // start to udpate
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ }
+
+ if p.ID == nil {
+ fmt.Printf("Can't find {.id} in %q.\n", file)
+ os.Exit(1)
+ return
+ }
+
+ resp, err := client.SyntheticsMonitors.Update(context.Background(), p, p.ID)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Println(resp.Status)
+ fmt.Println(resp.StatusCode)
+ }
+
+ if *p.Type == "SCRIPT_BROWSER" || *p.Type == "SCRIPT_API" {
+ var scriptTextEncoded *newrelic.Script
+ scriptTextEncoded = &newrelic.Script{}
+
+ flags := cmd.Flags()
+ if flags.Lookup("script-file") != nil {
+ scriptFileName, err := cmd.Flags().GetString("script-file")
+ if err != nil {
+ fmt.Printf("error accessing flag %s for command %s: %v\n", "script-file", cmd.Name(), err)
+ os.Exit(1)
+ return
+ }
+
+ if scriptFileName != "" {
+ sf, err := os.Open(scriptFileName)
+ defer sf.Close()
+ if err != nil {
+ fmt.Printf("Unable to open monitor script file '%v': %v\n", file, err)
+ os.Exit(1)
+ return
+ }
+ byteArr, err := ioutil.ReadAll(sf)
+ sfContentEncoded := base64.StdEncoding.EncodeToString(byteArr)
+ scriptTextEncoded.ScriptText = &sfContentEncoded
+ } else {
+ scriptTextEncoded = p.Script
+ }
+ } else {
+ scriptTextEncoded = p.Script
+ }
+
+ if scriptTextEncoded != nil && scriptTextEncoded.ScriptText != nil {
+ id := *p.ID
+ resp, err := client.SyntheticsScript.UpdateByID(context.Background(), scriptTextEncoded, id)
+ if err != nil {
+ fmt.Println(err)
+ os.Exit(1)
+ return
+ } else {
+ fmt.Println(resp.Status)
+ if resp.StatusCode >= 400 {
+ os.Exit(1)
+ return
+ }
+ }
+ }
+ }
+
+ os.Exit(0)
+ },
+}
+
+func UpdateMonitorByID(monitorId *string, p *newrelic.Monitor, scriptTextEncoded *newrelic.Script) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+ //update monitor itself
+ resp, err := client.SyntheticsMonitors.Update(context.Background(), p, monitorId)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_UPDATE_MONITOR, resp.StatusCode, "monitor id: "+(*monitorId)+",monitor name: "+(*p.Name))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update monitor '%s', monitor id: '%s'\n", statusCode, *p.Name, *monitorId)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+
+ }
+ //update script if needed
+ if scriptTextEncoded != nil && scriptTextEncoded.ScriptText != nil {
+ id := *p.ID
+ resp, err := client.SyntheticsScript.UpdateByID(context.Background(), scriptTextEncoded, id)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR_SCRIPT, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsScript, tracker.OPERATION_NAME_UPDATE_MONITOR, resp.StatusCode, "monitor id: "+(*monitorId)+",monitor name: "+(*p.Name))
+
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update script to monitor '%s', monitor id: '%s'\n", statusCode, *p.Name, id)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+ }
+ //update labels if needed
+ labelList, err, ret := get.GetLabelsByMonitorID(*p.ID)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ labelListLen := len(labelList)
+ if labelListLen > 0 {
+ //delete all labels on this monitor first
+ for _, label := range labelList {
+ err, ret := delete.DeleteLabelFromMonitor(*p.ID, *label)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ }
+ //and then, add new lables to this monitor
+ newLabelList := p.Labels
+ for _, label := range newLabelList {
+ var monitorLabel *newrelic.MonitorLabel
+ monitorLabel = &newrelic.MonitorLabel{}
+ arr := strings.Split(*label, ":")
+ monitorLabel.Category = &arr[0]
+ monitorLabel.Label = &arr[1]
+ err, ret := add.AddLabelToMonitor(*p.ID, monitorLabel)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_MONITOR, nil, nil, "")
+
+ return err, ret
+}
+
+func UpdateMonitorByName(p *newrelic.Monitor, scriptTextEncoded *newrelic.Script) (error, tracker.ReturnValue) {
+ client, err := utils.GetNewRelicClient("synthetics")
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, err, tracker.ERR_CREATE_NR_CLINET, "")
+ return err, ret
+ }
+
+ curMonitor, err, ret := get.GetMonitorByName(*p.Name)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+
+ monitorId := curMonitor.ID
+
+ //update monitor itself
+ resp, err := client.SyntheticsMonitors.Update(context.Background(), p, monitorId)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsMonitors, tracker.OPERATION_NAME_UPDATE_MONITOR, resp.StatusCode, "monitor id: "+(*monitorId)+",monitor name: "+(*p.Name))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update monitor '%s', monitor id: '%s'\n", statusCode, *p.Name, *monitorId)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+
+ }
+ //update script if needed
+ if scriptTextEncoded != nil && scriptTextEncoded.ScriptText != nil {
+ resp, err := client.SyntheticsScript.UpdateByID(context.Background(), scriptTextEncoded, *monitorId)
+ if err != nil {
+ fmt.Println(err)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR_SCRIPT, err, tracker.ERR_REST_CALL, "")
+ return err, ret
+ } else {
+ tracker.AppendRESTCallResult(client.SyntheticsScript, tracker.OPERATION_NAME_UPDATE_MONITOR, resp.StatusCode, "monitor id: "+(*monitorId)+",monitor name: "+(*p.Name))
+ if resp.StatusCode >= 400 {
+ var statusCode = resp.StatusCode
+ fmt.Printf("Response status code: %d. Update script to monitor '%s', monitor id: '%s'\n", statusCode, *p.Name, *monitorId)
+ ret := tracker.ToReturnValue(false, tracker.OPERATION_NAME_UPDATE_MONITOR, tracker.ERR_REST_CALL_NOT_2XX, tracker.ERR_REST_CALL_NOT_2XX, "")
+ return err, ret
+ }
+ }
+ }
+ //update labels if needed
+ labelList, err, ret := get.GetLabelsByMonitorID(*monitorId)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ labelListLen := len(labelList)
+ if labelListLen > 0 {
+ //delete all labels on this monitor first
+ for _, label := range labelList {
+ err, ret := delete.DeleteLabelFromMonitor(*monitorId, *label)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+ }
+ //and then, add new lables to this monitor
+ newLabelList := p.Labels
+ for _, label := range newLabelList {
+ var monitorLabel *newrelic.MonitorLabel
+ monitorLabel = &newrelic.MonitorLabel{}
+ arr := strings.Split(*label, ":")
+ monitorLabel.Category = &arr[0]
+ monitorLabel.Label = &arr[1]
+ err, ret := add.AddLabelToMonitor(*monitorId, monitorLabel)
+ if ret.IsContinue == false {
+ return err, ret
+ }
+ }
+
+ ret = tracker.ToReturnValue(true, tracker.OPERATION_NAME_UPDATE_MONITOR, nil, nil, "")
+
+ return err, ret
+}
+
+func init() {
+ UpdateCmd.AddCommand(monitorCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // alertspoliciesCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // alertspoliciesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/version.go b/cmd/version.go
new file mode 100644
index 0000000..bfb565b
--- /dev/null
+++ b/cmd/version.go
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package cmd
+
+import (
+ "fmt"
+
+ "github.com/spf13/cobra"
+)
+
+var version = "v0.1.2"
+
+// versionCmd represents the version command
+var versionCmd = &cobra.Command{
+ Use: "version",
+ Short: "Print out current version number",
+ Run: func(cmd *cobra.Command, args []string) {
+ fmt.Println(version)
+ },
+}
+
+func init() {
+ rootCmd.AddCommand(versionCmd)
+
+ // Here you will define your flags and configuration settings.
+
+ // Cobra supports Persistent Flags which will work for this command
+ // and all subcommands, e.g.:
+ // versionCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+ // Cobra supports local flags which will only run when this command
+ // is called directly, e.g.:
+ // versionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/newrelic/alerts_channels.go b/newrelic/alerts_channels.go
new file mode 100644
index 0000000..d57dd27
--- /dev/null
+++ b/newrelic/alerts_channels.go
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "strconv"
+)
+
+var channelTypes = make(map[AlertsChannelType]func() interface{})
+
+func init() {
+ channelTypes[ChannelByUser] = func() interface{} { return new(ChannelUserConfig) }
+ channelTypes[ChannelByEmail] = func() interface{} { return new(ChannelEmailConfig) }
+ channelTypes[ChannelBySlack] = func() interface{} { return new(ChannelSlackConfig) }
+ channelTypes[ChannelByPagerDuty] = func() interface{} { return new(ChannelPagerDutyConfig) }
+ channelTypes[ChannelByWebhook] = func() interface{} { return new(ChannelWebhookConfig) }
+ channelTypes[ChannelByCampfire] = func() interface{} { return new(ChannelCampfireConfig) }
+ channelTypes[ChannelByHipChat] = func() interface{} { return new(ChannelHipChatConfig) }
+ channelTypes[ChannelByOpsGenie] = func() interface{} { return new(ChannelOpsGenieConfig) }
+ channelTypes[ChannelByVictorOps] = func() interface{} { return new(ChannelVictorOpsConfig) }
+}
+
+type AlertsChannelType string
+type AlertsChannelWebhookType string
+
+const (
+ ChannelByUser AlertsChannelType = "user"
+ ChannelByEmail AlertsChannelType = "email"
+ ChannelBySlack AlertsChannelType = "slack"
+ ChannelByPagerDuty AlertsChannelType = "pagerduty"
+ ChannelByWebhook AlertsChannelType = "webhook"
+ ChannelByCampfire AlertsChannelType = "campfire"
+ ChannelByHipChat AlertsChannelType = "hipchat"
+ ChannelByOpsGenie AlertsChannelType = "opsgenie"
+ ChannelByVictorOps AlertsChannelType = "victorops"
+ // TODO: complete possible options: e.g. xMatters
+
+ ChannelWebhookByJSON AlertsChannelWebhookType = "application/json"
+ ChannelWebhookByForm AlertsChannelWebhookType = "application/x-www-form-urlencoded"
+)
+
+// ChannelUserConfig is system generated alerts channel, it's non-editable
+type ChannelUserConfig struct {
+ UserID *string `json:"user_id,omitempty"`
+}
+
+// ChannelEmailConfig is struct of Email Alert Channel
+type ChannelEmailConfig struct {
+ Recipients *string `json:"recipients,omitempty"`
+ IncludeJSONAttachment *bool `json:"include_json_attachment,omitempty"`
+}
+
+// ChannelSlackConfig is struct of Slack Alert Channel
+type ChannelSlackConfig struct {
+ URL *string `json:"url,omitempty"`
+ Channel *string `json:"channel,omitempty"`
+}
+
+// ChannelPagerDutyConfig is struct of Pagerduty Alert Channel
+type ChannelPagerDutyConfig struct {
+ ServiceKey *string `json:"service_key,omitempty"`
+}
+
+// ChannelWebhookConfig is struct of Webhook Alert Channel
+type ChannelWebhookConfig struct {
+ BaseURL *string `json:"base_url,omitempty"`
+ AuthUsername *string `json:"auth_username,omitempty"`
+ AuthPassword *string `json:"auth_password,omitempty"`
+ PayloadType AlertsChannelWebhookType `json:"payload_type,omitempty"`
+ Payload *map[string]interface{} `json:"payload,omitempty"`
+ Headers *map[string]string `json:"headers,omitempty"`
+}
+
+type ChannelHipChatConfig struct {
+ AuthToken *string `json:"auth_token,omitempty"`
+ RoomId *string `json:"room_id,omitempty"`
+}
+
+type ChannelOpsGenieConfig struct {
+ ApiKey *string `json:"api_key,omitempty"`
+ Teams *string `json:"teams,omitempty"`
+ Tags *string `json:"tags,omitempty"`
+ Recipients *string `json:"recipients,omitempty"`
+}
+
+type ChannelCampfireConfig struct {
+ Subdomain *string `json:"subdomain,omitempty"`
+ Token *string `json:"token,omitempty"`
+ Room *string `json:"room,omitempty"`
+}
+
+type ChannelVictorOpsConfig struct {
+ Key *string `json:"key,omitempty"`
+ RouteKey *string `json:"route_key,omitempty"`
+}
+
+type AlertsChannelsService service
+
+type AlertsChannel struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Type AlertsChannelType `json:"type,omitempty"`
+ Configuration interface{} `json:"configuration,omitempty"`
+ Links *AlertsChannelLinks `json:"links,omitempty"`
+}
+
+// UnmarshalJSON customizes UnmarshalJSON method so that Configuration field
+// can be properly unmarshlled
+func (c *AlertsChannel) UnmarshalJSON(data []byte) error {
+ var envelope struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Type AlertsChannelType `json:"type,omitempty"`
+ Configuration json.RawMessage `json:"configuration,omitempty"`
+ Links *AlertsChannelLinks `json:"links,omitempty"`
+ }
+ if err := json.Unmarshal(data, &envelope); err != nil {
+ return err
+ }
+ configure, ok := channelTypes[envelope.Type]
+ if !ok {
+ return fmt.Errorf("type %q is not supported", envelope.Type)
+ }
+ configuration := configure()
+ // in some cases, NewRelic mask or totally remove some fields
+ // which results in the Configuration be a nil
+ // so we should bypass the json decode err here
+ json.Unmarshal(envelope.Configuration, configuration)
+ // if err := json.Unmarshal(envelope.Configuration, configuration); err != nil {
+ // return err
+ // }
+ c.Configuration = configuration
+ c.ID = envelope.ID
+ c.Name = envelope.Name
+ c.Type = envelope.Type
+ c.Links = envelope.Links
+ return nil
+}
+
+// AlertsChannelLinks holds the links to AlertsPolicies
+type AlertsChannelLinks struct {
+ PolicyIDs []*int64 `json:"policy_ids,omitempty"`
+}
+
+type AlertsChannelEntity struct {
+ AlertsChannel *AlertsChannel `json:"channel,omitempty"`
+}
+
+type AlertsChannelList struct {
+ AlertsChannels []*AlertsChannel `json:"channels,omitempty"`
+ AlertsLinks *AlertsLinks `json:"links,omitempty"`
+}
+
+type AlertsLinks struct {
+ ChannelPolicyIDs *string `json:"channel.policy_ids,omitempty"`
+}
+
+type AlertsChannelListOptions struct {
+ PageOptions
+}
+
+type PolicyChannelsAssociation struct {
+ PolicyID *int64 `json:"policyId,omitempty"`
+ ChannelIDList []*int64 `json:"channels,omitempty"`
+}
+
+func (s *AlertsChannelsService) ListAll(ctx context.Context, opt *AlertsChannelListOptions) (*AlertsChannelList, *Response, error) {
+ u, err := addOptions("alerts_channels.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ alertsChannelList := new(AlertsChannelList)
+ resp, err := s.client.Do(ctx, req, alertsChannelList)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return alertsChannelList, resp, nil
+}
+
+// Create POST a AlertsChannelEntity to create
+//
+// maybe a potential bug in NewRelic side
+// from API document, Create returns a AlertsChannel json payload
+// but actually it returns a AlertsChannelList json
+// {"channels":[{"id":1104874,"name":"newrelic-cli-integration-test-channel","type":"email","configuration":{"recipients":""},"links":{"policy_ids":[]}}],"links":{"channel.policy_ids":"/v2/policies/{policy_id}"}}
+// so change returned parameter *AlertsChannelEntity to *AlertsChannelList
+func (s *AlertsChannelsService) Create(ctx context.Context, c *AlertsChannelEntity) (*AlertsChannelList, *Response, error) {
+ u := "alerts_channels.json"
+ req, err := s.client.NewRequest("POST", u, c)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ channelList := new(AlertsChannelList)
+ resp, err := s.client.Do(ctx, req, channelList)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return channelList, resp, nil
+}
+
+func (s *AlertsChannelsService) DeleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_channels/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *AlertsChannelsService) UpdatePolicyChannels(ctx context.Context, policyId int64, channelIds []*int64) (*Response, error) {
+ u := "alerts_policy_channels.json"
+
+ var channels string
+ var channelsLen = len(channelIds)
+ for index, channelID := range channelIds {
+ if index < (channelsLen - 1) {
+ channels = channels + strconv.FormatInt(*channelID, 10) + ","
+ } else {
+ channels = channels + strconv.FormatInt(*channelID, 10)
+ }
+ }
+
+ var c = "policy_id=" + strconv.FormatInt(policyId, 10) + "&channel_ids=" + channels
+
+ u = u + "?" + c
+
+ req, err := s.client.NewRequest("PUT", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ alertChannels := new(PolicyChannelsAssociation)
+ resp, err := s.client.Do(ctx, req, alertChannels)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, err
+}
diff --git a/newrelic/alerts_conditions.go b/newrelic/alerts_conditions.go
new file mode 100644
index 0000000..3d91193
--- /dev/null
+++ b/newrelic/alerts_conditions.go
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+const (
+ // https://docs.newrelic.com/docs/alerts/rest-api-alerts/new-relic-alerts-rest-api/rest-api-calls-new-relic-alerts
+ ConditionDefault ConditionCategory = "condition"
+ ConditionPlugins ConditionCategory = "plugins_condition"
+ ConditionExternalService ConditionCategory = "external_service_condition"
+ ConditionSynthetics ConditionCategory = "synthetics_condition"
+ ConditionNRQL ConditionCategory = "nrql_condition"
+)
+
+type ConditionCategory string
+
+type AlertsConditionsService struct {
+ *defaultConditions
+ *pluginsConditions
+ *externalServiceConditions
+ *syntheticsConditions
+ *nrqlConditions
+}
+
+type AlertsConditionsOptions struct {
+ PolicyIDOptions string `url:"policy_id,omitempty"`
+
+ PageOptions
+}
+
+type AlertsConditionList struct {
+ *AlertsDefaultConditionList
+ *AlertsExternalServiceConditionList
+ *AlertsNRQLConditionList
+ *AlertsPluginsConditionList
+ *AlertsSyntheticsConditionList
+}
+
+type AlertsConditionEntity struct {
+ *AlertsDefaultConditionEntity
+ *AlertsExternalServiceConditionEntity
+ *AlertsNRQLConditionEntity
+ *AlertsPluginsConditionEntity
+ *AlertsSyntheticsConditionEntity
+}
+
+func (s *AlertsConditionsService) ListAll(ctx context.Context, opt *AlertsConditionsOptions) (*AlertsConditionList, error) {
+ if opt == nil || opt.PolicyIDOptions == "" {
+ return nil, fmt.Errorf("policy_id is required")
+ }
+
+ list := new(AlertsConditionList)
+ cats := []ConditionCategory{ConditionDefault, ConditionPlugins, ConditionExternalService, ConditionSynthetics, ConditionNRQL}
+ for _, cat := range cats {
+ // TODO: paralleize and use ctx.Done() to cancel the parent context
+ listFunc := s.listByCategory(cat)
+ resp, err := listFunc(ctx, list, opt)
+ if err != nil || resp.StatusCode >= 400 {
+ return nil, fmt.Errorf("%v.Response: %v. Error: %v.", cat, resp, err)
+ }
+ }
+
+ return list, nil
+}
+
+func (s *AlertsConditionsService) List(ctx context.Context, opt *AlertsConditionsOptions, cat ConditionCategory) (*AlertsConditionList, *Response, error) {
+ if opt == nil || opt.PolicyIDOptions == "" {
+ return nil, nil, fmt.Errorf("policy_id is required")
+ }
+
+ list := new(AlertsConditionList)
+ listFunc := s.listByCategory(cat)
+ resp, err := listFunc(ctx, list, opt)
+ return list, resp, err
+}
+
+func (s *AlertsConditionsService) Create(ctx context.Context, cat ConditionCategory, c *AlertsConditionEntity, conditionID int64) (*AlertsConditionEntity, *Response, error) {
+ createFunc := s.createByCategory(cat)
+ condition, resp, err := createFunc(ctx, c, conditionID)
+ return condition, resp, err
+}
+
+func (s *AlertsConditionsService) Update(ctx context.Context, cat ConditionCategory, c *AlertsConditionEntity, conditionID int64) (*AlertsConditionEntity, *Response, error) {
+ updateFunc := s.updateByCategory(cat)
+ condition, resp, err := updateFunc(ctx, c, conditionID)
+ return condition, resp, err
+}
+
+func (s *AlertsConditionsService) DeleteByID(ctx context.Context, cat ConditionCategory, conditionID int64) (*Response, error) {
+ deleteFunc := s.deleteByCategory(cat)
+ resp, err := deleteFunc(ctx, conditionID)
+ return resp, err
+}
+
+func (s *AlertsConditionsService) listByCategory(cat ConditionCategory) func(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ switch cat {
+ case ConditionDefault:
+ return s.defaultConditions.listAll
+ case ConditionExternalService:
+ return s.externalServiceConditions.listAll
+ case ConditionNRQL:
+ return s.nrqlConditions.listAll
+ case ConditionPlugins:
+ return s.pluginsConditions.listAll
+ case ConditionSynthetics:
+ return s.syntheticsConditions.listAll
+ default:
+ return func(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ return nil, fmt.Errorf("unsupported category %q", cat)
+ }
+ }
+}
+
+func (s *AlertsConditionsService) createByCategory(cat ConditionCategory) func(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ switch cat {
+ case ConditionDefault:
+ return s.defaultConditions.create
+ case ConditionExternalService:
+ return s.externalServiceConditions.create
+ case ConditionNRQL:
+ return s.nrqlConditions.create
+ case ConditionPlugins:
+ return s.pluginsConditions.create
+ case ConditionSynthetics:
+ return s.syntheticsConditions.create
+ default:
+ return func(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ return nil, nil, fmt.Errorf("unsupported category %q", cat)
+ }
+ }
+}
+
+func (s *AlertsConditionsService) updateByCategory(cat ConditionCategory) func(ctx context.Context, c *AlertsConditionEntity, conditionID int64) (*AlertsConditionEntity, *Response, error) {
+ switch cat {
+ case ConditionDefault:
+ return s.defaultConditions.update
+ case ConditionExternalService:
+ return s.externalServiceConditions.update
+ case ConditionNRQL:
+ return s.nrqlConditions.update
+ case ConditionPlugins:
+ return s.pluginsConditions.update
+ case ConditionSynthetics:
+ return s.syntheticsConditions.update
+ default:
+ return func(ctx context.Context, c *AlertsConditionEntity, conditionID int64) (*AlertsConditionEntity, *Response, error) {
+ return nil, nil, fmt.Errorf("unsupported category %q", cat)
+ }
+ }
+}
+
+func (s *AlertsConditionsService) deleteByCategory(cat ConditionCategory) func(ctx context.Context, conditionID int64) (*Response, error) {
+ switch cat {
+ case ConditionDefault:
+ return s.defaultConditions.deleteByID
+ case ConditionExternalService:
+ return s.externalServiceConditions.deleteByID
+ case ConditionNRQL:
+ return s.nrqlConditions.deleteByID
+ case ConditionPlugins:
+ return s.pluginsConditions.deleteByID
+ case ConditionSynthetics:
+ return s.syntheticsConditions.deleteByID
+ default:
+ return func(ctx context.Context, conditionID int64) (*Response, error) {
+ return nil, fmt.Errorf("unsupported category %q", cat)
+ }
+ }
+}
+
+type AlertsConditionTerm struct {
+ Duration *string `json:"duration,omitempty"`
+ Operator *string `json:"operator,omitempty"`
+ Priority *string `json:"priority,omitempty"`
+ Threshold *string `json:"threshold,omitempty"`
+ TimeFunction *string `json:"time_function,omitempty"`
+}
diff --git a/newrelic/alerts_default_conditions.go b/newrelic/alerts_default_conditions.go
new file mode 100644
index 0000000..6d65a4b
--- /dev/null
+++ b/newrelic/alerts_default_conditions.go
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+// API: https://rpm.newrelic.com/api/explore/alerts_conditions/list
+
+type defaultConditions service
+
+type AlertsDefaultConditionList struct {
+ AlertsDefaultConditions []*AlertsDefaultCondition `json:"conditions,omitempty"`
+}
+
+// AlertsDefaultCondition manages Conditions of
+// * APM Application
+// * Key Transaction
+// * Browser application metric
+// * Mobile application metric
+// for your alert policies
+//
+// NOTICE: API documents says Entities are integers, but it's string actually
+type AlertsDefaultCondition struct {
+ ID *int64 `json:"id,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+ Entities []*string `json:"entities,omitempty"`
+ Metric *string `json:"metric,omitempty"`
+ GCMetric *string `json:"gc_metric,omitempty"`
+ RunbookURL *string `json:"runbook_url,omitempty"`
+ ConditionScope *string `json:"condition_scope,omitempty"`
+ ViolationCloseTimer *int64 `json:"violation_close_timer,omitempty"`
+ Terms []*AlertsConditionTerm `json:"terms,omitempty"`
+ UserDefined *AlertsDefaultConditionUserDefined `json:"user_defined,omitempty"`
+}
+
+type AlertsDefaultConditionEntity struct {
+ AlertsDefaultCondition *AlertsDefaultCondition `json:"condition,omitempty"`
+}
+
+type AlertsDefaultConditionUserDefined struct {
+ Metric *string `json:"metric,omitempty"`
+ ValueFunction *string `json:"value_function,omitempty"`
+}
+
+func (s *defaultConditions) listAll(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ u, err := addOptions("alerts_conditions.json", opt)
+ if err != nil {
+ return nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ list.AlertsDefaultConditionList = new(AlertsDefaultConditionList)
+ resp, err := s.client.Do(ctx, req, list.AlertsDefaultConditionList)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
+
+func (s *defaultConditions) deleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_conditions/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *defaultConditions) create(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_conditions/policies/%v.json", policyID)
+ if c.AlertsDefaultConditionEntity.AlertsDefaultCondition.ID != nil {
+ c.AlertsDefaultConditionEntity.AlertsDefaultCondition.ID = nil
+ }
+ req, err := s.client.NewRequest("POST", u, c.AlertsDefaultConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsDefaultConditionEntity = new(AlertsDefaultConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsDefaultConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
+
+func (s *defaultConditions) update(ctx context.Context, c *AlertsConditionEntity, id int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_conditions/%v.json", id)
+ req, err := s.client.NewRequest("PUT", u, c.AlertsDefaultConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsDefaultConditionEntity = new(AlertsDefaultConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsDefaultConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
diff --git a/newrelic/alerts_events.go b/newrelic/alerts_events.go
new file mode 100644
index 0000000..4054536
--- /dev/null
+++ b/newrelic/alerts_events.go
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import "context"
+
+type AlertsEventService service
+
+type AlertsEventList struct {
+ RecentEvents []*RecentEvent `json:"recent_events,omitempty"`
+}
+
+type RecentEvent struct {
+ ID *int64 `json:"id,omitempty"`
+ EventType *string `json:"event_type,omitempty"`
+ Description *string `json:"description,omitempty"`
+ Timestamp *int64 `json:"timestamp,omitempty"`
+ IncidentID *int64 `json:"incident_id,omitempty"`
+ Product *string `json:"product,omitempty"`
+ EntityType *string `json:"entity_type,omitempty"`
+ EntityGroupID *int64 `json:"entity_group_id,omitempty"`
+ EntityID *int64 `json:"entity_id,omitempty"`
+ Priority *string `json:"priority,omitempty"`
+}
+
+type AlertsEventListOptions struct {
+ PageOptions
+ Product string `url:"filter[product],omitempty"`
+ EntityType string `url:"filter[entity_type],omitempty"`
+ EntityGroupID int64 `url:"filter[entity_group_id],omitempty"`
+ EntityID int64 `url:"filter[entity_id],omitempty"`
+ EventType string `url:"filter[event_type],omitempty"`
+ IncidentID int64 `url:"filter[incident_id],omitempty"`
+}
+
+func (s *AlertsEventService) ListAll(ctx context.Context, opt *AlertsEventListOptions) (*AlertsEventList, *Response, error) {
+ u, err := addOptions("alerts_events.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ alertsEventList := new(AlertsEventList)
+ resp, err := s.client.Do(ctx, req, alertsEventList)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return alertsEventList, resp, nil
+}
diff --git a/newrelic/alerts_external_service_conditions.go b/newrelic/alerts_external_service_conditions.go
new file mode 100644
index 0000000..ec71d9f
--- /dev/null
+++ b/newrelic/alerts_external_service_conditions.go
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+// API: https://rpm.newrelic.com/api/explore/alerts_external_service_conditions/list
+
+type externalServiceConditions service
+
+type AlertsExternalServiceConditionList struct {
+ AlertsExternalServiceConditions []*AlertsExternalServiceCondition `json:"external_service_conditions,omitempty"`
+}
+
+type AlertsExternalServiceCondition struct {
+ ID *int64 `json:"id,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+ Entities []*string `json:"entities,omitempty"`
+ ExternalServiceURL *string `json:"external_service_url,omitempty"`
+ Metric *string `json:"metric,omitempty"`
+ RunbookURL *string `json:"runbook_url,omitempty"`
+ Terms []*AlertsConditionTerm `json:"terms,omitempty"`
+}
+
+type AlertsExternalServiceConditionEntity struct {
+ AlertsExternalServiceCondition *AlertsExternalServiceCondition `json:"external_service_condition,omitempty"`
+}
+
+func (s *externalServiceConditions) listAll(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ u, err := addOptions("alerts_external_service_conditions.json", opt)
+ if err != nil {
+ return nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ list.AlertsExternalServiceConditionList = new(AlertsExternalServiceConditionList)
+ resp, err := s.client.Do(ctx, req, list.AlertsExternalServiceConditionList)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
+
+func (s *externalServiceConditions) deleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_external_service_conditions/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *externalServiceConditions) create(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_external_service_conditions/policies/%v.json", policyID)
+ if c.AlertsExternalServiceConditionEntity.AlertsExternalServiceCondition.ID != nil {
+ c.AlertsExternalServiceConditionEntity.AlertsExternalServiceCondition.ID = nil
+ }
+ req, err := s.client.NewRequest("POST", u, c.AlertsExternalServiceConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsExternalServiceConditionEntity = new(AlertsExternalServiceConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsExternalServiceConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
+
+func (s *externalServiceConditions) update(ctx context.Context, c *AlertsConditionEntity, id int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_external_service_conditions/%v.json", id)
+ req, err := s.client.NewRequest("PUT", u, c.AlertsExternalServiceConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsExternalServiceConditionEntity = new(AlertsExternalServiceConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsExternalServiceConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
diff --git a/newrelic/alerts_incidents.go b/newrelic/alerts_incidents.go
new file mode 100644
index 0000000..30cd468
--- /dev/null
+++ b/newrelic/alerts_incidents.go
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import "context"
+
+type AlertsIncidentService service
+
+type AlertsIncidentList struct {
+ Incidents []*AlertsIncident `json:"incidents,omitempty"`
+ Links *AlertsIncidentListLinks `json:"links,omitempty"`
+}
+
+type AlertsIncident struct {
+ ID *int64 `json:"id,omitempty"`
+ OpenedAt *int64 `json:"opened_at,omitempty"`
+ IncidentPreference *string `json:"incident_preference,omitempty"`
+ Links *AlertsIncidentLinks `json:"links,omitempty"`
+}
+
+type AlertsIncidentLinks struct {
+ Violations []*int64 `json:"violations,omitempty"`
+ PolicyID *int64 `json:"policy_id,omitempty"`
+}
+
+type AlertsIncidentListLinks struct {
+ IncidentPolicyID *string `json:"incident.policy_id,omitempty"`
+}
+
+type AlertsIncidentListOptions struct {
+ PageOptions
+ OnlyOpen bool `url:"only_open,omitempty"`
+}
+
+func (s *AlertsIncidentService) ListAll(ctx context.Context, opt *AlertsIncidentListOptions) (*AlertsIncidentList, *Response, error) {
+ u, err := addOptions("alerts_incidents.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ alertsIncidentList := new(AlertsIncidentList)
+ resp, err := s.client.Do(ctx, req, alertsIncidentList)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return alertsIncidentList, resp, nil
+}
diff --git a/newrelic/alerts_nrql_conditions.go b/newrelic/alerts_nrql_conditions.go
new file mode 100644
index 0000000..20bcc4b
--- /dev/null
+++ b/newrelic/alerts_nrql_conditions.go
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type nrqlConditions service
+
+type AlertsNRQLConditionList struct {
+ AlertsNRQLConditions []*AlertsNRQLCondition `json:"nrql_conditions,omitempty"`
+}
+
+type AlertsNRQLCondition struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ RunbookURL *string `json:"runbook_url,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+ Terms []*AlertsConditionTerm `json:"terms,omitempty"`
+ ValueFunction *string `json:"value_function,omitempty"`
+ NRQL *AlertsNRQLConditionNRQL `json:"nrql,omitempty"`
+}
+
+type AlertsNRQLConditionNRQL struct {
+ Query *string `json:"query,omitempty"`
+ SinceValue *string `json:"since_value,omitempty"`
+}
+
+type AlertsNRQLConditionEntity struct {
+ AlertsNRQLCondition *AlertsNRQLCondition `json:"nrql_condition,omitempty"`
+}
+
+func (s *nrqlConditions) listAll(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ u, err := addOptions("alerts_nrql_conditions.json", opt)
+ if err != nil {
+ return nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ list.AlertsNRQLConditionList = new(AlertsNRQLConditionList)
+ resp, err := s.client.Do(ctx, req, list.AlertsNRQLConditionList)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
+
+func (s *nrqlConditions) deleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_nrql_conditions/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *nrqlConditions) create(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_nrql_conditions/policies/%v.json", policyID)
+ if c.AlertsNRQLConditionEntity.AlertsNRQLCondition.ID != nil {
+ c.AlertsNRQLConditionEntity.AlertsNRQLCondition.ID = nil
+ }
+ req, err := s.client.NewRequest("POST", u, c.AlertsNRQLConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsNRQLConditionEntity = new(AlertsNRQLConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsNRQLConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
+
+func (s *nrqlConditions) update(ctx context.Context, c *AlertsConditionEntity, id int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_nrql_conditions/%v.json", id)
+ req, err := s.client.NewRequest("PUT", u, c.AlertsNRQLConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsNRQLConditionEntity = new(AlertsNRQLConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsNRQLConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
diff --git a/newrelic/alerts_plugins_conditions.go b/newrelic/alerts_plugins_conditions.go
new file mode 100644
index 0000000..d199179
--- /dev/null
+++ b/newrelic/alerts_plugins_conditions.go
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type pluginsConditions service
+
+type AlertsPluginsConditionList struct {
+ AlertsPluginsConditions []*AlertsPluginsCondition `json:"plugins_conditions,omitempty"`
+}
+
+type AlertsPluginsCondition struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+ Entities []*int64 `json:"entities,omitempty"`
+ MetricDescription *string `json:"metric_description,omitempty"`
+ Metric *string `json:"metric,omitempty"`
+ ValueFunction *string `json:"value_function,omitempty"`
+ RunbookURL *string `json:"runbook_url,omitempty"`
+ Terms []*AlertsConditionTerm `json:"terms,omitempty"`
+ Plugin *AlertsPluginsConditionPlugin `json:"plugin,omitempty"`
+}
+
+type AlertsPluginsConditionPlugin struct {
+ ID *string `json:"id,omitempty"`
+ GUID *string `json:"guid,omitempty"`
+}
+
+type AlertsPluginsConditionEntity struct {
+ AlertsPluginsCondition *AlertsPluginsCondition `json:"plugins_condition,omitempty"`
+}
+
+func (s *pluginsConditions) listAll(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ u, err := addOptions("alerts_plugins_conditions.json", opt)
+ if err != nil {
+ return nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ list.AlertsPluginsConditionList = new(AlertsPluginsConditionList)
+ resp, err := s.client.Do(ctx, req, list.AlertsPluginsConditionList)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
+
+func (s *pluginsConditions) deleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_plugins_conditions/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *pluginsConditions) create(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_plugins_conditions/policies/%v.json", policyID)
+ if c.AlertsPluginsConditionEntity.AlertsPluginsCondition.ID != nil {
+ c.AlertsPluginsConditionEntity.AlertsPluginsCondition.ID = nil
+ }
+ req, err := s.client.NewRequest("POST", u, c.AlertsPluginsConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsPluginsConditionEntity = new(AlertsPluginsConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsPluginsConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
+
+func (s *pluginsConditions) update(ctx context.Context, c *AlertsConditionEntity, id int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_plugins_conditions/%v.json", id)
+ req, err := s.client.NewRequest("PUT", u, c.AlertsPluginsConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsPluginsConditionEntity = new(AlertsPluginsConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsPluginsConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
diff --git a/newrelic/alerts_policies.go b/newrelic/alerts_policies.go
new file mode 100644
index 0000000..e12b563
--- /dev/null
+++ b/newrelic/alerts_policies.go
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+const (
+ // https://docs.newrelic.com/docs/alerts/rest-api-alerts/new-relic-alerts-rest-api/rest-api-calls-new-relic-alerts#policies-create
+ IncidentPerPolicy IncidentPreferenceOption = "PER_POLICY"
+ IncidentPerCondition IncidentPreferenceOption = "PER_CONDITION"
+ IncidentPerConditionAndTaret IncidentPreferenceOption = "PER_CONDITION_AND_TARGET"
+)
+
+type IncidentPreferenceOption string
+
+type AlertsPoliciesService service
+
+type AlertsPolicy struct {
+ ID *int64 `json:"id,omitempty"`
+ IncidentPreference IncidentPreferenceOption `json:"incident_preference,omitempty"`
+ Name *string `json:"name,omitempty"`
+ CreatedAt *int64 `json:"created_at,omitempty"`
+ UpdatedAt *int64 `json:"updated_at,omitempty"`
+}
+
+type AlertsPolicyEntity struct {
+ AlertsPolicy *AlertsPolicy `json:"policy,omitempty"`
+}
+
+type AlertsPolicyList struct {
+ AlertsPolicies []*AlertsPolicy `json:"policies,omitempty"`
+}
+
+type AlertsPolicyListOptions struct {
+ NameOptions string `url:"filter[name],omitempty"`
+
+ PageOptions
+}
+
+func (s *AlertsPoliciesService) ListAll(ctx context.Context, opt *AlertsPolicyListOptions) (*AlertsPolicyList, *Response, error) {
+ u, err := addOptions("alerts_policies.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ alertsPolicyList := new(AlertsPolicyList)
+ resp, err := s.client.Do(ctx, req, alertsPolicyList)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return alertsPolicyList, resp, nil
+}
+
+// Create tries to create an alerts policy
+// CAVEAT: it's good practice to check if a `p` existed
+// If a `p` is "Created" twice, two alerts policies will be created with same Name but different ID
+func (s *AlertsPoliciesService) Create(ctx context.Context, p *AlertsPolicyEntity) (*AlertsPolicyEntity, *Response, error) {
+ u := "alerts_policies.json"
+ req, err := s.client.NewRequest("POST", u, p)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ policy := new(AlertsPolicyEntity)
+ resp, err := s.client.Do(ctx, req, policy)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return policy, resp, nil
+}
+
+func (s *AlertsPoliciesService) Update(ctx context.Context, p *AlertsPolicyEntity, id int64) (*AlertsPolicyEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_policies/%v.json", id)
+ req, err := s.client.NewRequest("PUT", u, p)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ policy := new(AlertsPolicyEntity)
+ resp, err := s.client.Do(ctx, req, policy)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return policy, resp, nil
+}
+
+func (s *AlertsPoliciesService) DeleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_policies/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/newrelic/alerts_synthetics_conditions.go b/newrelic/alerts_synthetics_conditions.go
new file mode 100644
index 0000000..83d4585
--- /dev/null
+++ b/newrelic/alerts_synthetics_conditions.go
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type syntheticsConditions service
+
+type AlertsSyntheticsConditionList struct {
+ AlertsSyntheticsConditions []*AlertsSyntheticsCondition `json:"synthetics_conditions,omitempty"`
+}
+
+type AlertsSyntheticsCondition struct {
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ MonitorID *string `json:"monitor_id,omitempty"`
+ RunbookURL *string `json:"runbook_url,omitempty"`
+ Enabled *bool `json:"enabled,omitempty"`
+}
+
+type AlertsSyntheticsConditionEntity struct {
+ AlertsSyntheticsCondition *AlertsSyntheticsCondition `json:"synthetics_condition,omitempty"`
+}
+
+func (s *syntheticsConditions) listAll(ctx context.Context, list *AlertsConditionList, opt *AlertsConditionsOptions) (*Response, error) {
+ u, err := addOptions("alerts_synthetics_conditions.json", opt)
+ if err != nil {
+ return nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ list.AlertsSyntheticsConditionList = new(AlertsSyntheticsConditionList)
+ resp, err := s.client.Do(ctx, req, list.AlertsSyntheticsConditionList)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
+
+func (s *syntheticsConditions) deleteByID(ctx context.Context, id int64) (*Response, error) {
+ u := fmt.Sprintf("alerts_synthetics_conditions/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *syntheticsConditions) create(ctx context.Context, c *AlertsConditionEntity, policyID int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_synthetics_conditions/policies/%v.json", policyID)
+ if c.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition.ID != nil {
+ c.AlertsSyntheticsConditionEntity.AlertsSyntheticsCondition.ID = nil
+ }
+ req, err := s.client.NewRequest("POST", u, c.AlertsSyntheticsConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsSyntheticsConditionEntity = new(AlertsSyntheticsConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsSyntheticsConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
+
+func (s *syntheticsConditions) update(ctx context.Context, c *AlertsConditionEntity, id int64) (*AlertsConditionEntity, *Response, error) {
+ u := fmt.Sprintf("alerts_synthetics_conditions/%v.json", id)
+ req, err := s.client.NewRequest("PUT", u, c.AlertsSyntheticsConditionEntity)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ condition := new(AlertsConditionEntity)
+ condition.AlertsSyntheticsConditionEntity = new(AlertsSyntheticsConditionEntity)
+ resp, err := s.client.Do(ctx, req, condition.AlertsSyntheticsConditionEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return condition, resp, nil
+}
diff --git a/newrelic/alerts_violations.go b/newrelic/alerts_violations.go
new file mode 100644
index 0000000..0ac60a6
--- /dev/null
+++ b/newrelic/alerts_violations.go
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+)
+
+type AlertsViolationService service
+
+type AlertsViolationList struct {
+ Violations []*AlertsViolation `json:"violations,omitempty"`
+ Links *AlertsViolationListLinks `json:"links,omitempty"`
+}
+
+type AlertsViolation struct {
+ ID *int64 `json:"id,omitempty"`
+ Label *string `json:"label,omitempty"`
+ Duration *int64 `json:"duration,omitempty"`
+ PolicyName *string `json:"policy_name,omitempty"`
+ ConditionName *string `json:"condition_name,omitempty"`
+ Priority *string `json:"priority,omitempty"`
+ OpenedAt *int64 `json:"opened_at,omitempty"`
+ Entity *AlertsViolationEntity `json:"entity,omitempty"`
+ Links *AlertsViolationLinks `json:"links,omitempty"`
+ ClosedAt *int64 `json:"closed_at,omitempty"`
+}
+
+type AlertsViolationEntity struct {
+ Product *string `json:"product,omitempty"`
+ Type *string `json:"type,omitempty"`
+ GroupID *int64 `json:"group_id,omitempty"`
+ ID *int64 `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+}
+
+type AlertsViolationLinks struct {
+ PolicyID *int64 `json:"policy_id,omitempty"`
+ ConditionID *int64 `json:"condition_id,omitempty"`
+}
+
+type AlertsViolationListLinks struct {
+ ViolationPolicyID *string `json:"violation.policy_id,omitempty"`
+ ViolationConditionID *string `json:"violation.condition_id,omitempty"`
+}
+
+type AlertsViolationListOptions struct {
+ PageOptions
+ OnlyOpen bool `url:"only_open,omitempty"`
+ StartDate string `url:"start_date,omitempty"`
+ EndDate string `url:"end_date,omitempty"`
+}
+
+func (s *AlertsViolationService) ListAll(ctx context.Context, opt *AlertsViolationListOptions) (*AlertsViolationList, *Response, error) {
+ u, err := addOptions("alerts_violations.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ alertsViolationList := new(AlertsViolationList)
+ resp, err := s.client.Do(ctx, req, alertsViolationList)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return alertsViolationList, resp, nil
+}
diff --git a/newrelic/base.go b/newrelic/base.go
new file mode 100644
index 0000000..4781e0f
--- /dev/null
+++ b/newrelic/base.go
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "bytes"
+ "context"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "reflect"
+ "strings"
+
+ "github.com/google/go-querystring/query"
+)
+
+const (
+ defaultBaseURL = "https://api.newrelic.com/v2/"
+ syntheticsURL = "https://synthetics.newrelic.com/synthetics/api/v3/monitors/"
+ userAgent = "go-newrelic"
+ labelSyntheticsURL = "https://synthetics.newrelic.com/synthetics/api/v4/monitors/"
+ insightsURL = "https://insights-collector.newrelic.com/v1/accounts/"
+)
+
+type Client struct {
+ client *http.Client
+
+ BaseURL *url.URL
+ UserAgent string
+ XApiKey string
+ ProxyAuth string
+
+ common service
+
+ Users *UsersService
+ AlertsPolicies *AlertsPoliciesService
+ AlertsChannels *AlertsChannelsService
+ Labels *LabelsService
+ AlertsIncidents *AlertsIncidentService
+ AlertsViolations *AlertsViolationService
+ AlertsEvents *AlertsEventService
+ AlertsConditions *AlertsConditionsService
+ SyntheticsMonitors *SyntheticsService
+ SyntheticsScript *ScriptService
+ LabelsSynthetics *LabelsSyntheticsService
+ Dashboards *DashboardService
+ CustomEvents *CustomEventService
+}
+
+type service struct {
+ client *Client
+}
+
+type Response struct {
+ *http.Response
+
+ NextPage int
+ PrePage int
+ FirstPage int
+ LastPage int
+}
+
+func (r *Response) String() string {
+ if r == nil {
+ return "nil"
+ }
+ return r.Status
+}
+
+type PageOptions struct {
+ Page int `url:"page,omitempty"`
+}
+
+func NewClient(httpClient *http.Client, endpointType string) *Client {
+ if httpClient == nil {
+ httpClient = http.DefaultClient
+ }
+ var baseURL *url.URL
+
+ if endpointType != "synthetics" && endpointType != "labelSynthetics" && endpointType != "insights" {
+ baseURL, _ = url.Parse(defaultBaseURL)
+ } else {
+ if endpointType == "synthetics" {
+ baseURL, _ = url.Parse(syntheticsURL)
+ } else if endpointType == "labelSynthetics" {
+ baseURL, _ = url.Parse(labelSyntheticsURL)
+ } else if endpointType == "insights" {
+ baseURL, _ = url.Parse(insightsURL)
+ }
+ }
+
+ c := &Client{
+ client: httpClient,
+ BaseURL: baseURL,
+ UserAgent: userAgent,
+ }
+ c.common.client = c
+ c.Users = (*UsersService)(&c.common)
+ c.AlertsPolicies = (*AlertsPoliciesService)(&c.common)
+ c.AlertsChannels = (*AlertsChannelsService)(&c.common)
+ c.Labels = (*LabelsService)(&c.common)
+ c.AlertsIncidents = (*AlertsIncidentService)(&c.common)
+ c.AlertsViolations = (*AlertsViolationService)(&c.common)
+ c.AlertsEvents = (*AlertsEventService)(&c.common)
+
+ c.AlertsConditions = &AlertsConditionsService{}
+ c.AlertsConditions.defaultConditions = (*defaultConditions)(&c.common)
+ c.AlertsConditions.pluginsConditions = (*pluginsConditions)(&c.common)
+ c.AlertsConditions.externalServiceConditions = (*externalServiceConditions)(&c.common)
+ c.AlertsConditions.syntheticsConditions = (*syntheticsConditions)(&c.common)
+ c.AlertsConditions.nrqlConditions = (*nrqlConditions)(&c.common)
+
+ c.SyntheticsMonitors = (*SyntheticsService)(&c.common)
+ c.SyntheticsScript = (*ScriptService)(&c.common)
+ c.LabelsSynthetics = (*LabelsSyntheticsService)(&c.common)
+
+ c.Dashboards = (*DashboardService)(&c.common)
+
+ c.CustomEvents = (*CustomEventService)(&c.common)
+ return c
+}
+
+func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) {
+ if !strings.HasSuffix(c.BaseURL.Path, "/") {
+ return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL)
+ }
+ u, err := c.BaseURL.Parse(urlStr)
+ if err != nil {
+ return nil, err
+ }
+
+ var buf io.ReadWriter
+ if body != nil {
+ buf = new(bytes.Buffer)
+ enc := json.NewEncoder(buf)
+ enc.SetEscapeHTML(false)
+ err := enc.Encode(body)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ req, err := http.NewRequest(method, u.String(), buf)
+ if err != nil {
+ return nil, err
+ }
+
+ if body != nil {
+ req.Header.Set("Content-Type", "application/json")
+ }
+ if c.UserAgent != "" {
+ req.Header.Set("User-Agent", c.UserAgent)
+ }
+ if c.XApiKey != "" {
+ req.Header.Set("X-Api-Key", c.XApiKey)
+ }
+ if c.ProxyAuth != "" {
+ basic := "Basic " + base64.StdEncoding.EncodeToString([]byte(c.ProxyAuth))
+ req.Header.Set("Proxy-Authorization", basic)
+ }
+ return req, nil
+}
+
+func (c *Client) NewRequestForNonJSON(method, urlStr string, body string) (*http.Request, error) {
+ if !strings.HasSuffix(c.BaseURL.Path, "/") {
+ return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL)
+ }
+ u, err := c.BaseURL.Parse(urlStr)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest(method, u.String(), strings.NewReader(body))
+ if err != nil {
+ return nil, err
+ }
+
+ if body != "" {
+ req.Header.Set("Content-Type", "application/json")
+ }
+ if c.UserAgent != "" {
+ req.Header.Set("User-Agent", c.UserAgent)
+ }
+ if c.XApiKey != "" {
+ req.Header.Set("X-Api-Key", c.XApiKey)
+ }
+ return req, nil
+}
+
+func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) {
+ resp, err := c.client.Do(req)
+ if err != nil {
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ default:
+ }
+
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ response := &Response{Response: resp}
+
+ if v != nil {
+ if w, ok := v.(io.Writer); ok {
+ io.Copy(w, resp.Body)
+ } else {
+ decErr := json.NewDecoder(resp.Body).Decode(v)
+ if decErr == io.EOF {
+ decErr = nil // ignore EOF errors caused by empty response body
+ }
+ if decErr != nil {
+ err = decErr
+ }
+ }
+ }
+
+ return response, err
+}
+
+func (c *Client) DoWithBytes(ctx context.Context, req *http.Request) (*Response, []byte, error) {
+ resp, err := c.client.Do(req)
+ if err != nil {
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ select {
+ case <-ctx.Done():
+ return nil, nil, ctx.Err()
+ default:
+ }
+
+ return nil, nil, err
+ }
+ defer resp.Body.Close()
+
+ response := &Response{Response: resp}
+
+ var retBytes []byte
+ retBytes, err = ioutil.ReadAll(resp.Body)
+
+ return response, retBytes, err
+}
+
+// addOptions adds the parameters in opt as URL query parameters to s. opt
+// must be a struct whose fields may contain "url" tags.
+func addOptions(s string, opt interface{}) (string, error) {
+ v := reflect.ValueOf(opt)
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ return s, nil
+ }
+
+ u, err := url.Parse(s)
+ if err != nil {
+ return s, err
+ }
+
+ qs, err := query.Values(opt)
+ if err != nil {
+ return s, err
+ }
+
+ u.RawQuery = qs.Encode()
+ return u.String(), nil
+}
diff --git a/newrelic/custom_events.go b/newrelic/custom_events.go
new file mode 100644
index 0000000..7ee6981
--- /dev/null
+++ b/newrelic/custom_events.go
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type CustomEventService service
+
+func (s *CustomEventService) Insert(ctx context.Context, insertKey string, accountID string, jsonData string) (*Response, []byte, error) {
+ u := fmt.Sprintf("%v/events", accountID)
+ req, err := s.client.NewRequestForNonJSON("POST", u, jsonData)
+ if err != nil {
+ return nil, nil, err
+ }
+ req.Header.Set("X-Insert-Key", insertKey)
+
+ resp, bytes, err := s.client.DoWithBytes(ctx, req)
+ if err != nil {
+ return resp, nil, err
+ }
+
+ return resp, bytes, nil
+}
diff --git a/newrelic/dashboards.go b/newrelic/dashboards.go
new file mode 100644
index 0000000..654d2cd
--- /dev/null
+++ b/newrelic/dashboards.go
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type Dashboard struct {
+ // ID *int64 `json:"id,omitempty"`
+ // Title *string `json:"title,omitempty"`
+}
+
+type DashboardList struct {
+ Dashboards []*Dashboard `json:"dashboards,omitempty"`
+}
+
+type DashboardListOptions struct {
+ PageOptions
+}
+
+type DashboardService service
+
+func (s *DashboardService) ListAll(ctx context.Context, opt *DashboardListOptions) (*Response, []byte, error) {
+ u, err := addOptions("dashboards.json", opt)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+
+ if err != nil {
+ fmt.Println(err)
+ return nil, nil, err
+ }
+
+ resp, bytes, err := s.client.DoWithBytes(ctx, req)
+ if err != nil {
+ return resp, nil, err
+ }
+
+ return resp, bytes, nil
+}
+
+func (s *DashboardService) GetByID(ctx context.Context, id int64) (*Response, []byte, error) {
+ u := fmt.Sprintf("dashboards/%v.json", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ resp, bytes, err := s.client.DoWithBytes(ctx, req)
+ if err != nil {
+ return resp, nil, err
+ }
+
+ return resp, bytes, nil
+}
+
+func (s *DashboardService) DeleteByID(ctx context.Context, id int64) (*Response, []byte, error) {
+ u := fmt.Sprintf("dashboards/%v.json", id)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ resp, bytes, err := s.client.DoWithBytes(ctx, req)
+ if err != nil {
+ return resp, nil, err
+ }
+
+ return resp, bytes, nil
+}
+
+func (s *DashboardService) Create(ctx context.Context, dashboard string) (*Response, []byte, error) {
+ u := "dashboards.json"
+ req, err := s.client.NewRequestForNonJSON("POST", u, dashboard)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ resp, bytes, err := s.client.DoWithBytes(ctx, req)
+ if err != nil {
+ return resp, nil, err
+ }
+
+ return resp, bytes, nil
+}
+
+func (s *DashboardService) Update(ctx context.Context, dashboard string, id int64) (*Response, []byte, error) {
+ u := fmt.Sprintf("dashboards/%v.json", id)
+ req, err := s.client.NewRequestForNonJSON("PUT", u, dashboard)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ resp, bytes, err := s.client.DoWithBytes(ctx, req)
+ if err != nil {
+ return resp, nil, err
+ }
+
+ return resp, bytes, nil
+}
diff --git a/newrelic/labels.go b/newrelic/labels.go
new file mode 100644
index 0000000..ced9693
--- /dev/null
+++ b/newrelic/labels.go
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+// NewRelic API docs: https://docs.newrelic.com/docs/apis/rest-api-v2/labels-examples-v2/list-labels-v2
+
+// LabelsService handles communication with label
+// related method of the NewRelic API
+
+type LabelsService service
+
+type LabelEntity struct {
+ Label *Label `json:"label,omitempty"`
+}
+
+type LabelList struct {
+ Labels []*Label `json:"labels,omitempty"`
+ LabelListLinks *LabelListLinks `json:"links,omitempty"`
+}
+
+type Label struct {
+ Key *string `json:"key,omitempty"`
+ Category *string `json:"category,omitempty"`
+ Name *string `json:"name,omitempty"`
+ LabelsApplicationHealthStatus *LabelsHealthStatus `json:"application_health_status,omitempty"`
+ LabelsServerHealthStatus *LabelsHealthStatus `json:"server_health_status,omitempty"`
+ LabelLinks *LabelLinks `json:"links,omitempty"`
+}
+
+type LabelsHealthStatus struct {
+ Green []*int64 `json:"green,omitempty"`
+ Orange []*int64 `json:"orange,omitempty"`
+ Red []*int64 `json:"red,omitempty"`
+ Gray []*int64 `json:"gray,omitempty"`
+}
+
+type LabelLinks struct {
+ Applications []*int64 `json:"applications,omitempty"`
+ Servers []*int64 `json:"servers,omitempty"`
+}
+
+type LabelListLinks struct {
+ LabelApplications *string `json:"label.applications,omitempty"`
+ LabelServers *string `json:"label.servers,omitempty"`
+ LabelServer *string `json:"label.server,omitempty"`
+}
+
+type LabelListOptions struct {
+ PageOptions
+}
+
+func (s *LabelsService) ListAll(ctx context.Context, opt *LabelListOptions) (*LabelList, *Response, error) {
+ u, err := addOptions("labels.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ labelList := new(LabelList)
+ resp, err := s.client.Do(ctx, req, labelList)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return labelList, resp, nil
+}
+
+func (s *LabelsService) Create(ctx context.Context, l *LabelEntity) (*LabelEntity, *Response, error) {
+ u := "labels.json"
+ req, err := s.client.NewRequest("PUT", u, l)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ labelEntity := new(LabelEntity)
+ resp, err := s.client.Do(ctx, req, labelEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return labelEntity, resp, nil
+}
+
+func (s *LabelsService) DeleteByKey(ctx context.Context, key string) (*Response, error) {
+ u := fmt.Sprintf("labels/%v.json", key)
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
diff --git a/newrelic/labels_monitors.go b/newrelic/labels_monitors.go
new file mode 100644
index 0000000..8140311
--- /dev/null
+++ b/newrelic/labels_monitors.go
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type LabelsSyntheticsService service
+
+type MonitorRef struct {
+ ID *string `json:"id,omitempty"`
+ HREF *string `json:"href,omitempty"`
+}
+
+type MonitorRefList struct {
+ MonitorRefs []*MonitorRef `json:"monitorRefs,omitempty"`
+}
+
+// type PagedDataEntity struct {
+// PagedData *MonitorRefList `json:"pagedData,omitempty"`
+// }
+
+type Metadata struct {
+ Limit *int `json:"limit,omitempty"`
+ Offset *int `json:"offset,omitempty"`
+}
+
+type LabelSynthetics struct {
+ PagedData *MonitorRefList `json:"pagedData,omitempty"`
+ Metadata *Metadata `json:"metadata,omitempty"`
+}
+
+type MonitorLabel struct {
+ Category *string `json:"id,omitempty"`
+ Label *string `json:"href,omitempty"`
+}
+
+func (s *LabelsSyntheticsService) GetMonitorsByLabel(ctx context.Context, opt *PageLimitOptions, label string) (*LabelSynthetics, *Response, error) {
+ u := fmt.Sprintf("labels/%v", label)
+ u, err := addOptions(u, opt)
+
+ // if err != nil {
+ // return nil, nil, err
+ // }
+ //DEBUG
+ // var u = "labels/Monitor:PagerDuty"
+ //DEBUG
+
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ labelSynthetics := new(LabelSynthetics)
+ resp, err := s.client.Do(ctx, req, labelSynthetics)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ return labelSynthetics, resp, nil
+}
+
+func (s *LabelsSyntheticsService) AddLabelToMonitor(ctx context.Context, monitorId string, monitorLabel *MonitorLabel) (*Response, error) {
+ u := fmt.Sprintf("%v/labels", monitorId)
+
+ var label string
+ label = *monitorLabel.Category + ":" + *monitorLabel.Label
+ req, err := s.client.NewRequestForNonJSON("POST", u, label)
+ if err != nil {
+ return nil, err
+ }
+
+ labelSynthetics := new(LabelSynthetics)
+ resp, err := s.client.Do(ctx, req, labelSynthetics)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
+
+func (s *LabelsSyntheticsService) DeleteLabelFromMonitor(ctx context.Context, monitorId string, label string) (*Response, error) {
+ u := fmt.Sprintf("%v/labels/%v", monitorId, label)
+
+ req, err := s.client.NewRequest("DELETE", u, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, label)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp, nil
+}
diff --git a/newrelic/monitors.go b/newrelic/monitors.go
new file mode 100644
index 0000000..b0110e0
--- /dev/null
+++ b/newrelic/monitors.go
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "path"
+)
+
+type Monitor struct {
+ ID *string `json:"id,omitempty"`
+ Name *string `json:"name,omitempty"`
+ Type *string `json:"type,omitempty"`
+ Frequency *int64 `json:"frequency,omitempty"`
+ URI *string `json:"uri,omitempty"`
+ Locations []*string `json:"locations,omitempty"`
+ Status *string `json:"status,omitempty"`
+ SLAThreshold *float64 `json:"slaThreshold,omitempty"`
+ UserID *int64 `json:"userId,omitempty"`
+ ApiVersion *string `json:"apiVersion,omitempty"`
+ CreatedAt *string `json:"createdAt,omitempty"`
+ UpdatedAt *string `json:"modifiedAt,omitempty"`
+ Options MonitorOptions `json:"options,omitempty"`
+ Script *Script `json:"script,omitempty"`
+ Labels []*string `json:"labels,omitempty"`
+}
+
+type MonitorOptions struct {
+ ValidationString *string `json:"validationString,omitempty"`
+ VerifySSL bool `json:"verifySSL,omitempty"`
+ BypassHEADRequest bool `json:"bypassHEADRequest,omitempty"`
+ TreatRedirectAsFailure bool `json:"treatRedirectAsFailure,omitempty"`
+}
+
+type MonitorList struct {
+ Monitors []*Monitor `json:"monitors,omitempty"`
+}
+
+type PageLimitOptions struct {
+ Limit int `url:"limit,omitempty"`
+ Offset int `url:"offset,omitempty"`
+}
+
+type MonitorListOptions struct {
+ PageOptions
+ PageLimitOptions
+}
+
+type SyntheticsService service
+
+func (s *SyntheticsService) ListAll(ctx context.Context, opt *MonitorListOptions) (*MonitorList, *Response, error) {
+ u, err := addOptions("", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ req, err := s.client.NewRequest("GET", u, nil)
+
+ if err != nil {
+ return nil, nil, err
+ }
+
+ monitorList := new(MonitorList)
+
+ resp, err := s.client.Do(ctx, req, monitorList)
+ if err != nil {
+ return nil, resp, err
+ }
+ return monitorList, resp, nil
+}
+
+func (s *SyntheticsService) GetByID(ctx context.Context, id string) (*Monitor, *Response, error) {
+ req, err := s.client.NewRequest("GET", id, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ monitor := new(Monitor)
+ resp, err := s.client.Do(ctx, req, monitor)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return monitor, resp, nil
+}
+
+func (s *SyntheticsService) Create(ctx context.Context, monitor *Monitor) (*Monitor, *Response, error) {
+ req, err := s.client.NewRequest("POST", "", monitor)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, monitor)
+ if err != nil {
+ return nil, resp, err
+ }
+ monitorUUID := path.Base(resp.Header.Get("Location"))
+ monitor.ID = &monitorUUID
+ return monitor, resp, nil
+}
+
+func (s *SyntheticsService) Update(ctx context.Context, monitor *Monitor, id *string) (*Response, error) {
+ req, err := s.client.NewRequest("PUT", *id, monitor)
+ if err != nil {
+ return nil, err
+ }
+
+ m := new(Monitor)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
+
+func (s *SyntheticsService) DeleteByID(ctx context.Context, id *string) (*Response, error) {
+ req, err := s.client.NewRequest("DELETE", *id, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return s.client.Do(ctx, req, nil)
+}
+
+func (s *SyntheticsService) Patch(ctx context.Context, monitor *Monitor, id *string) (*Response, error) {
+ req, err := s.client.NewRequest("Patch", *id, monitor)
+ if err != nil {
+ return nil, err
+ }
+
+ m := new(Monitor)
+ resp, err := s.client.Do(ctx, req, m)
+ if err != nil {
+ return resp, err
+ }
+
+ return resp, nil
+}
diff --git a/newrelic/script.go b/newrelic/script.go
new file mode 100644
index 0000000..1c61e7f
--- /dev/null
+++ b/newrelic/script.go
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+type Script struct {
+ ScriptText *string `json:"scriptText,omitempty"`
+}
+
+type ScriptService service
+
+func (s *ScriptService) GetByID(ctx context.Context, id string) (*Script, *Response, error) {
+ u := fmt.Sprintf("%v/script/", id)
+ //fmt.Println("path : ", u)
+
+ req, err := s.client.NewRequest("GET", u, nil)
+
+ if err != nil {
+ fmt.Println(err)
+ return nil, nil, err
+ }
+
+ script := new(Script)
+ resp, err := s.client.Do(ctx, req, script)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return script, resp, nil
+}
+
+func (s *ScriptService) UpdateByID(ctx context.Context, scriptText *Script, id string) (*Response, error) {
+ u := fmt.Sprintf("%v/script/", id)
+ req, err := s.client.NewRequest("PUT", u, scriptText)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := s.client.Do(ctx, req, scriptText)
+ return resp, err
+}
diff --git a/newrelic/users.go b/newrelic/users.go
new file mode 100644
index 0000000..92bfefb
--- /dev/null
+++ b/newrelic/users.go
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package newrelic
+
+import (
+ "context"
+ "fmt"
+)
+
+// UsersService handles communication with the user related
+// methods of the NewRelic API.
+//
+// NewRelic API docs: https://docs.newrelic.com/docs/apis/rest-api-v2/account-examples-v2/listing-users-your-account
+type UsersService service
+
+// User represents a NewRelic user.
+type User struct {
+ ID *int64 `json:"id,omitempty"`
+ FirstName *string `json:"first_name,omitempty"`
+ LastName *string `json:"last_name,omitempty"`
+ Email *string `json:"email,omitempty"`
+ Role *string `json:"role,omitempty"`
+}
+
+// UserEntity corresponds to a JSON payload returned by NewRelic API
+type UserEntity struct {
+ User *User `json:"user,omitempty"`
+}
+
+// UserList represents a collection of NewRelic users.
+type UserList struct {
+ Users []*User `json:"users,omitempty"`
+}
+
+// UserListOptions specifies optional parameters to the UsersService.ListAll
+// method.
+type UserListOptions struct {
+ IDOptions string `url:"filter[ids],omitempty"`
+ EmailOptions string `url:"filter[email],omitempty"`
+
+ PageOptions
+}
+
+// ListAll retruns all NewRelic users under current account/NEW_RELIC_API_KEY
+// When given `opt`, it returns fitlered resultset
+func (s *UsersService) ListAll(ctx context.Context, opt *UserListOptions) (*UserList, *Response, error) {
+ u, err := addOptions("users.json", opt)
+ if err != nil {
+ return nil, nil, err
+ }
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ userList := new(UserList)
+ resp, err := s.client.Do(ctx, req, userList)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return userList, resp, nil
+}
+
+// GetByID returns specfic NewRelic user by given `id`
+func (s *UsersService) GetByID(ctx context.Context, id int64) (*UserEntity, *Response, error) {
+ u := fmt.Sprintf("users/%v.json", id)
+ req, err := s.client.NewRequest("GET", u, nil)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ userEntity := new(UserEntity)
+ resp, err := s.client.Do(ctx, req, userEntity)
+ if err != nil {
+ return nil, resp, err
+ }
+
+ return userEntity, resp, nil
+}
diff --git a/nr.go b/nr.go
new file mode 100644
index 0000000..13a7bfa
--- /dev/null
+++ b/nr.go
@@ -0,0 +1,21 @@
+// Copyright © 2018 NAME HERE
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import "github.com/IBM/newrelic-cli/cmd"
+
+func main() {
+ cmd.Execute()
+}
diff --git a/shell-samples/backup-alert-conditions.sh b/shell-samples/backup-alert-conditions.sh
new file mode 100755
index 0000000..aafdbfa
--- /dev/null
+++ b/shell-samples/backup-alert-conditions.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+## Set the NEW_RELIC_APIKEY env here if needed by comment out below export cmd
+#export NEW_RELIC_APIKEY="xxx-xxxx-xxx"
+
+curDateFolder=$(date +%Y%m%d-%H%M%S)
+
+basepath=$(cd `dirname $0`; pwd)
+
+targetFolder=${basepath}/backup_alert_conditions/$curDateFolder
+if [ ! -d $targetFolder ];then
+ mkdir -p $targetFolder
+fi
+
+${basepath}/nr backup alertsconditions -d $targetFolder -r fail-backup-conditions.log
+exitCode=$?""
+
+if [ $exitCode == "0" ];then
+ echo ""
+ echo "Success, backup end."
+ exit 0
+else
+ echo ""
+ echo "Some conditions to backup failed, begin to retry..."
+fi
+
+counter=0
+while [ $exitCode != "0" ]
+do
+ counter=`expr $counter + 1`
+
+ ${basepath}/nr backup alertsconditions -d $targetFolder -r fail-backup-conditions.log
+ exitCode=$?""
+
+ if [ $exitCode != "0" ];then
+ echo ""
+ echo "Some conditions to backup failed in this retry: "$counter"."
+ if [ $counter -ge 3 ];then
+ echo ""
+ echo "Retry 3 times, backup end."
+ exit 1
+ fi
+ else
+ echo ""
+ echo "After retry, no failed, backup end."
+ exit 0
+ fi
+done
diff --git a/shell-samples/backup-dashboards.sh b/shell-samples/backup-dashboards.sh
new file mode 100755
index 0000000..55ccef1
--- /dev/null
+++ b/shell-samples/backup-dashboards.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+## Can set the NEW_RELIC_APIKEY env here by comment out below export cmd
+#export NEW_RELIC_APIKEY="xxx-xxxx-xxx"
+
+curDateFolder=$(date +%Y%m%d-%H%M%S)
+
+basepath=$(cd `dirname $0`; pwd)
+
+targetFolder=${basepath}/backup_dashboards/$curDateFolder
+if [ ! -d $targetFolder ];then
+ mkdir -p $targetFolder
+fi
+
+${basepath}/nr backup dashboards -d $targetFolder -r fail-backup-dashboards.log
+exitCode=$?""
+
+if [ $exitCode == "0" ];then
+ echo ""
+ echo "Success, backup end."
+ exit 0
+else
+ echo ""
+ echo "Some dashboards to backup failed, begin to retry..."
+fi
+
+counter=0
+while [ $exitCode != "0" ]
+do
+ counter=`expr $counter + 1`
+
+ ${basepath}/nr backup dashboards -d $targetFolder -r fail-backup-dashboards.log
+ exitCode=$?""
+
+ if [ $exitCode != "0" ];then
+ echo ""
+ echo "Some dashboards to backup failed in this retry: "$counter"."
+ if [ $counter -ge 3 ];then
+ echo ""
+ echo "Retry 3 times, backup end."
+ exit 1
+ fi
+ else
+ echo ""
+ echo "After retry, no failed, backup end."
+ exit 0
+ fi
+done
diff --git a/shell-samples/backup-monitors.sh b/shell-samples/backup-monitors.sh
new file mode 100755
index 0000000..beaf35e
--- /dev/null
+++ b/shell-samples/backup-monitors.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+## Can set the NEW_RELIC_APIKEY env here by comment out below export cmd
+#export NEW_RELIC_APIKEY="xxx-xxxx-xxx"
+
+curDateFolder=$(date +%Y%m%d-%H%M%S)
+
+basepath=$(cd `dirname $0`; pwd)
+
+targetFolder=${basepath}/backup_monitors/$curDateFolder
+if [ ! -d $targetFolder ];then
+ mkdir -p $targetFolder
+fi
+
+${basepath}/nr backup monitors -d $targetFolder -r fail-backup-monitors.log
+exitCode=$?""
+
+if [ $exitCode == "0" ];then
+ echo ""
+ echo "Success, backup end."
+ exit 0
+else
+ echo ""
+ echo "Some monitors to backup failed, begin to retry..."
+fi
+
+counter=0
+while [ $exitCode != "0" ]
+do
+ counter=`expr $counter + 1`
+
+ ${basepath}/nr backup monitors -d $targetFolder -r fail-backup-monitors.log
+ exitCode=$?""
+
+ if [ $exitCode != "0" ];then
+ echo ""
+ echo "Some monitors to backup failed in this retry: "$counter"."
+ if [ $counter -ge 3 ];then
+ echo ""
+ echo "Retry 3 times, backup end."
+ exit 1
+ fi
+ else
+ echo ""
+ echo "After retry, no failed, backup end."
+ exit 0
+ fi
+done
diff --git a/shell-samples/restore-monitors.sh b/shell-samples/restore-monitors.sh
new file mode 100755
index 0000000..922d373
--- /dev/null
+++ b/shell-samples/restore-monitors.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+noNRKey="No NEW_RELIC_APIKEY detected."
+noNRKey=${noNRKey}"\n\n"
+noNRKey=${noNRKey}"Please export New Relic API key."
+noNRKey=${noNRKey}"\n\n"
+noNRKey=${noNRKey}"Example:\n"
+noNRKey=${noNRKey}" export NEW_RELIC_APIKEY=xxx-xxxxx-xx"
+noNRKey=${noNRKey}"\n"
+if [ $NEW_RELIC_APIKEY"" == "" ];then
+ echo -e "${noNRKey}"
+ exit 1
+fi
+
+basepath=$(cd `dirname $0`; pwd)
+
+${basepath}/nr restore monitors -d ${basepath}/backup_monitors_folder -r fail-restore-monitors.log
+exitCode=$?""
+
+if [ $exitCode == "0" ];then
+ echo ""
+ echo "Success, restore end."
+ exit 0
+else
+ echo ""
+ echo "Some monitors to restore failed, begin to retry..."
+fi
+
+counter=0
+while [ $exitCode != "0" ]
+do
+ counter=`expr $counter + 1`
+
+ ${basepath}/nr restore monitors -F ${basepath}/fail-restore-monitors.log -r fail-restore-monitors.log
+ exitCode=$?""
+
+ if [ $exitCode != "0" ];then
+ echo ""
+ echo "Some monitors to restore failed in this retry: "$counter"."
+ if [ $counter -ge 3 ];then
+ echo ""
+ echo "Retry 3 times, restore end."
+ exit 1
+ fi
+ else
+ echo ""
+ echo "After retry, no failed, restore end."
+ exit 0
+ fi
+done
diff --git a/test/fixture/create/alertschannels_email.json b/test/fixture/create/alertschannels_email.json
new file mode 100644
index 0000000..c6a4bb9
--- /dev/null
+++ b/test/fixture/create/alertschannels_email.json
@@ -0,0 +1,9 @@
+{
+ "channel": {
+ "name": "newrelic-cli-integration-test-channel-email",
+ "type": "email",
+ "configuration": {
+ "recipients": "newrelic-cli-integration-test-channel-email@ibm.com"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/fixture/create/alertschannels_email.yaml b/test/fixture/create/alertschannels_email.yaml
new file mode 100644
index 0000000..5e0e3c2
--- /dev/null
+++ b/test/fixture/create/alertschannels_email.yaml
@@ -0,0 +1,5 @@
+channel:
+ name: newrelic-cli-integration-test-channel-email
+ type: email
+ configuration:
+ recipients: newrelic-cli-integration-test-channel-email@ibm.com
diff --git a/test/fixture/create/alertschannels_webhook.json b/test/fixture/create/alertschannels_webhook.json
new file mode 100644
index 0000000..89ca8d3
--- /dev/null
+++ b/test/fixture/create/alertschannels_webhook.json
@@ -0,0 +1,45 @@
+{
+ "channel": {
+ "name": "newrelic-cli-integration-test-channel-webhook",
+ "type": "webhook",
+ "configuration": {
+ "base_url": "https://www.sos.ibm.com/hooks/test-tip-newrelic",
+ "headers": {
+ "Authorization": "abcdefghijklmnopqrstuvwxyz123456"
+ },
+ "payload": {
+ "alert_id": "AAAABBBB",
+ "alert_ui_url": "$INCIDENT_URL",
+ "console": "analytics",
+ "crn": {
+ "cname": "internal",
+ "ctype": "Local",
+ "location": "DAL09",
+ "resource": "",
+ "resource_type": "",
+ "scope": "",
+ "service_instance": "WDPMON-1",
+ "service_name": "WDPMON",
+ "version": "v1"
+ },
+ "customer_impacting": "false",
+ "disable_pager": "false",
+ "long_description": "Violated New Relic condition: $CONDITION_NAME. Details: $EVENT_DETAILS. Policy: $POLICY_NAME. Account $ACCOUNT_NAME ($ACCOUNT_ID). URL: $INCIDENT_URL.",
+ "nr_account_id": "$ACCOUNT_ID",
+ "nr_account_name": "$ACCOUNT_NAME",
+ "nr_current_state": "$EVENT_STATE",
+ "nr_severity": "$SEVERITY",
+ "nr_targets": "$TARGETS",
+ "nr_timestamp": "$TIMESTAMP",
+ "runbook_toc_enabled": "false",
+ "runbook_url": "$RUNBOOK_URL",
+ "short_description": "Condition: $CONDITION_NAME. Details: $EVENT_DETAILS",
+ "situation": "$CONDITION_NAME",
+ "source": "newrelic-$ACCOUNT_ID",
+ "tribe_name": "WDPMON",
+ "version": "1.0"
+ },
+ "payload_type": "application/json"
+ }
+ }
+ }
\ No newline at end of file
diff --git a/test/fixture/create/alertschannels_webhook.yaml b/test/fixture/create/alertschannels_webhook.yaml
new file mode 100644
index 0000000..c921029
--- /dev/null
+++ b/test/fixture/create/alertschannels_webhook.yaml
@@ -0,0 +1,39 @@
+channel:
+ name: newrelic-cli-integration-test-channel-webhook
+ type: webhook
+ configuration:
+ base_url: https://www.sos.ibm.com/hooks/test-tip-newrelic
+ headers:
+ Authorization: abcdefghijklmnopqrstuvwxyz123456
+ payload:
+ alert_id: AAAABBBB
+ alert_ui_url: $INCIDENT_URL
+ console: analytics
+ crn:
+ cname: internal
+ ctype: Local
+ location: DAL09
+ resource: ""
+ resource_type: ""
+ scope: ""
+ service_instance: WDPMON-1
+ service_name: WDPMON
+ version: v1
+ customer_impacting: "false"
+ disable_pager: "false"
+ long_description: 'Violated New Relic condition: $CONDITION_NAME. Details: $EVENT_DETAILS.
+ Policy: $POLICY_NAME. Account $ACCOUNT_NAME ($ACCOUNT_ID). URL: $INCIDENT_URL.'
+ nr_account_id: $ACCOUNT_ID
+ nr_account_name: $ACCOUNT_NAME
+ nr_current_state: $EVENT_STATE
+ nr_severity: $SEVERITY
+ nr_targets: $TARGETS
+ nr_timestamp: $TIMESTAMP
+ runbook_toc_enabled: "false"
+ runbook_url: $RUNBOOK_URL
+ short_description: 'Condition: $CONDITION_NAME. Details: $EVENT_DETAILS'
+ situation: $CONDITION_NAME
+ source: newrelic-$ACCOUNT_ID
+ tribe_name: WDPMON
+ version: "1.0"
+ payload_type: application/json
\ No newline at end of file
diff --git a/test/fixture/create/alertspolicies.json b/test/fixture/create/alertspolicies.json
new file mode 100644
index 0000000..15f8f77
--- /dev/null
+++ b/test/fixture/create/alertspolicies.json
@@ -0,0 +1,7 @@
+{
+ "policy": {
+ "name": "newrelic-cli-integration-test-policy",
+ "incident_preference": "PER_POLICY"
+ }
+}
+
diff --git a/test/fixture/create/alertspolicies.yaml b/test/fixture/create/alertspolicies.yaml
new file mode 100644
index 0000000..1e410a1
--- /dev/null
+++ b/test/fixture/create/alertspolicies.yaml
@@ -0,0 +1,3 @@
+policy:
+ name: newrelic-cli-integration-test-policy
+ incident_preference: PER_POLICY
\ No newline at end of file
diff --git a/test/fixture/create/test-script-monitor.json b/test/fixture/create/test-script-monitor.json
new file mode 100644
index 0000000..501c1e1
--- /dev/null
+++ b/test/fixture/create/test-script-monitor.json
@@ -0,0 +1,24 @@
+{
+ "id": "9f5b47da-356a-4003-972b-4e123a1f0412",
+ "name": "Test-Script-Monitor",
+ "type": "SCRIPT_BROWSER",
+ "frequency": 1440,
+ "uri": "",
+ "locations": [
+ "AWS_US_EAST_1",
+ "AWS_US_WEST_1"
+ ],
+ "status": "ENABLED",
+ "slaThreshold": 7,
+ "userId": 0,
+ "apiVersion": "0.5.2",
+ "createdAt": "2018-08-02T07:47:55.193+0000",
+ "modifiedAt": "2018-08-08T08:10:58.604+0000",
+ "options": {},
+ "script": {
+ "scriptText": "Ly9WaXNpdCBodHRwczovL2RvY3MubmV3cmVsaWMuY29tCiRicm93c2VyLmdldCgiaHR0cHM6Ly9kb2NzLm5ld3JlbGljLmNvbSIpOwo="
+ },
+ "Labels": [
+ "Type:Script"
+ ]
+}
\ No newline at end of file
diff --git a/test/fixture/update/alertspolicies.json b/test/fixture/update/alertspolicies.json
new file mode 100644
index 0000000..20e49d0
--- /dev/null
+++ b/test/fixture/update/alertspolicies.json
@@ -0,0 +1,8 @@
+{
+ "policy": {
+ "id": 236864,
+ "name": "newrelic-cli-integration-test-policy-update",
+ "incident_preference": "PER_POLICY"
+ }
+}
+
diff --git a/test/fixture/update/alertspolicies.yaml b/test/fixture/update/alertspolicies.yaml
new file mode 100644
index 0000000..924521c
--- /dev/null
+++ b/test/fixture/update/alertspolicies.yaml
@@ -0,0 +1,4 @@
+policy:
+ id: 236864
+ name: newrelic-cli-integration-test-policy-update
+ incident_preference: PER_POLICY
\ No newline at end of file
diff --git a/test/integration/alertsconditions/alertsconditions_test.go b/test/integration/alertsconditions/alertsconditions_test.go
new file mode 100644
index 0000000..6618972
--- /dev/null
+++ b/test/integration/alertsconditions/alertsconditions_test.go
@@ -0,0 +1,20 @@
+package alertsconditions
+
+import (
+ "testing"
+
+ i "github.com/IBM/newrelic-cli/test/integration"
+)
+
+// func TestCreateMonitor(t *testing.T) {
+// i.EXENRCLI("create", "monitor", "-f", "../../fixture/create/test-script-monitor.json")
+// }
+
+func TestBackupAlertsConditions(t *testing.T) {
+
+ i.EXENRCLI("backup", "alertsconditions", "-d", "../../fixture/backup/alertsconditions", "-r", "list.log")
+
+ i.EXEOperationCmd("rm", "-rf", "./list.log")
+ i.EXEOperationCmd("rm", "-rf", "./../../fixture/backup/alertsconditions")
+ i.EXEOperationCmd("mkdir", "-p", "./../../fixture/backup/alertsconditions")
+}
diff --git a/test/integration/init.go b/test/integration/init.go
new file mode 100644
index 0000000..8ca2743
--- /dev/null
+++ b/test/integration/init.go
@@ -0,0 +1,51 @@
+package integration
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+)
+
+var (
+ NEW_RELIC_APIKEY string
+)
+
+func init() {
+ NEW_RELIC_APIKEY = "c60cd5e9e752a0204d29330cccf8207f"
+}
+
+func EXENRCLI(args ...string) {
+
+ cmd := exec.Command("../../../nr", args...)
+
+ env := os.Environ()
+ env = append(env, "NEW_RELIC_APIKEY="+NEW_RELIC_APIKEY)
+ cmd.Env = env
+
+ var out bytes.Buffer
+ cmd.Stdout = &out
+
+ err := cmd.Run()
+ if err != nil {
+ fmt.Printf("output for failure: %q\n", out.String())
+ fmt.Println()
+ log.Fatal(err)
+ }
+ fmt.Printf("output: %q\n", out.String())
+
+}
+
+func EXEOperationCmd(name string, args ...string) {
+ cmd := exec.Command(name, args...)
+ var out bytes.Buffer
+ cmd.Stdout = &out
+ err := cmd.Run()
+ if err != nil {
+ fmt.Printf("output for failure: %q\n", out.String())
+ fmt.Println()
+ log.Fatal(err)
+ }
+ fmt.Printf("output: %q\n", out.String())
+}
diff --git a/test/integration/monitors/monitors_test.go b/test/integration/monitors/monitors_test.go
new file mode 100644
index 0000000..bc1e948
--- /dev/null
+++ b/test/integration/monitors/monitors_test.go
@@ -0,0 +1,20 @@
+package monitors
+
+import (
+ "testing"
+
+ i "github.com/IBM/newrelic-cli/test/integration"
+)
+
+// func TestCreateMonitor(t *testing.T) {
+// i.EXENRCLI("create", "monitor", "-f", "../../fixture/create/test-script-monitor.json")
+// }
+
+func TestBackupMonitors(t *testing.T) {
+
+ i.EXENRCLI("backup", "monitors", "-d", "../../fixture/backup/monitors", "-r", "list.log")
+
+ i.EXEOperationCmd("rm", "-rf", "./list.log")
+ i.EXEOperationCmd("rm", "-rf", "./../../fixture/backup/monitors")
+ i.EXEOperationCmd("mkdir", "-p", "./../../fixture/backup/monitors")
+}
diff --git a/test/integration/users/get_users_test.go b/test/integration/users/get_users_test.go
new file mode 100644
index 0000000..537283c
--- /dev/null
+++ b/test/integration/users/get_users_test.go
@@ -0,0 +1,11 @@
+package users
+
+import (
+ "testing"
+
+ i "github.com/IBM/newrelic-cli/test/integration"
+)
+
+func TestGetUsers(t *testing.T) {
+ i.EXENRCLI("get", "users", "-o", "yaml")
+}
diff --git a/tracker/result_tracker.go b/tracker/result_tracker.go
new file mode 100644
index 0000000..4fce138
--- /dev/null
+++ b/tracker/result_tracker.go
@@ -0,0 +1,435 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tracker
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "reflect"
+ "strconv"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+ "github.com/IBM/newrelic-cli/utils"
+)
+
+type RESTCallResultList struct {
+ AllRESTCallResult []RESTCallResult
+}
+
+type BackupMonitorMetaList struct {
+ AllBackupMonitorMeta []BackupMonitorMeta
+}
+
+type BackupMonitorMeta struct {
+ Name string
+ Type string
+ Script bool
+ Labels []string
+ LabelCount int
+ ID string
+}
+
+type BackupPolicyMetaList struct {
+ AllBackupPolicyMeta []BackupPolicyMeta
+}
+
+type BackupPolicyMeta struct {
+ FileName string
+ OperationStatus string
+}
+
+type BackupDashboardMetaList struct {
+ AllBackupDashboardMeta []BackupDashboardMeta
+}
+
+type BackupDashboardMeta struct {
+ FileName string
+ OperationStatus string
+}
+
+type RestoreMonitorMetaList struct {
+ AllRestoreMonitorMeta []RestoreMonitorMeta
+}
+
+type RestoreMonitorMeta struct {
+ FileName string
+ // Name string
+ Type string
+ Script bool
+ Labels []string
+ LabelCount int
+ // PropertiesStatus string
+ // ScriptStatus string
+ // LabelStatus string
+ OperationStatus string
+}
+
+type RestoreAlertPolicyMetaList struct {
+ AllRestoreAlertPolicyMeta []RestoreAlertPolicyMeta
+}
+
+type RestoreAlertPolicyMeta struct {
+ FileName string
+ OperationStatus string
+}
+
+type RestoreDashboardMetaList struct {
+ AllRestoreDashboardMeta []RestoreDashboardMeta
+}
+
+type RestoreDashboardMeta struct {
+ FileName string
+ OperationStatus string
+}
+
+type RESTCallResult struct {
+ OperationName string
+ StatusCode int
+ Description string
+ // HTTPMethod string
+ Message string
+}
+
+// type MonitorResult struct {
+// Name string
+// Type string
+// Labels []string
+// OperationStatus string
+// }
+
+type AlertResult struct {
+ AlertPolicyName string
+ OperationStatus string
+}
+
+type AlertConditionResult struct {
+ AlertConditionName string
+ OperationStatus string
+}
+
+type ReturnValue struct {
+ OriginalError error
+ IsContinue bool
+ TypicalError error
+ Description string
+ OperationName string
+}
+
+var OPERATION_NAME_GET_MONITORS = "Get Monitors"
+var OPERATION_NAME_GET_MONITOR_BY_ID = "Get Monitor By ID"
+var OPERATION_NAME_GET_MONITOR_BY_NAME = "Get Monitor By Name"
+var OPERATION_NAME_GET_MONITOR_SCRIPT = "Get Monitor Script"
+var OPERATION_NAME_GET_LABELS = "Get Labels"
+var OPERATION_NAME_GET_LABELS_BY_MONITOR_ID = "Get Labels By Monitor ID"
+var OPERATION_NAME_GET_MONITORS_BY_LABEL = "Get Monitors By Label"
+var OPERATION_NAME_GET_ALERT_CHANNELS = "Get Alert Channels"
+var OPERATION_NAME_GET_ALERT_POLICIES = "Get Alert Policies"
+var OPERATION_NAME_GET_CONDITIONS_BY_POLICY_ID = "Get Conditions By Alert Policy ID"
+var OPERATION_NAME_GET_DASHBOARDS = "Get Dashboards"
+var OPERATION_NAME_GET_DASHBOARD_BY_ID = "Get Dashboard By ID"
+var OPERATION_NAME_GET_DASHBOARD_BY_NAME = "Get Dashboard By Name"
+
+var OPERATION_NAME_CHECK_ALERT_CHANNEL_NAME_EXISTS = "Check Alert Channel Name Exists"
+var OPERATION_NAME_CHECK_ALERT_POLICY_NAME_EXISTS = "Check Alert Policy Name Exists"
+var OPERATION_NAME_CHECK_MONITOR_NAME_EXISTS = "Check Monitor Name Exists"
+var OPERATION_NAME_CHECK_DASHBOARD_TITLE_EXISTS = "Check Dashboard Title Exists"
+
+var OPERATION_NAME_CREATE_MONITOR = "Create Monitor"
+var OPERATION_NAME_CREATE_ALERT_POLICY = "Create Alert Policy"
+var OPERATION_NAME_CREATE_ALERT_CONDITIION = "Create Alert Condition"
+var OPERATION_NAME_CREATE_DASHBOARD = "Create Dashboard"
+
+var OPERATION_NAME_UPDATE_MONITOR = "Update Monitor"
+var OPERATION_NAME_UPDATE_MONITOR_SCRIPT = "Create Monitor"
+var OPERATION_NAME_UPDATE_ALERT_POLICY_BY_NAME = "Update Alert Policy By Name"
+var OPERATION_NAME_UPDATE_ALERT_POLICY_BY_ID = "Update Alert Policy By ID"
+var OPERATION_NAME_UPDATE_ALERT_CONDITION_BY_ID = "Update Alert Condition By ID"
+var OPERATION_NAME_UPDATE_ALERT_POLICY_CHANNEL = "Update Alert Policy Channel"
+var OPERATION_NAME_UPDATE_DASHBOARD_BY_ID = "Update Dashboard By ID"
+var OPERATION_NAME_UPDATE_DASHBOARD_BY_NAME = "Update Dashboard By Name"
+
+var OPERATION_NAME_PATCH_MONITOR = "Patch Monitor"
+
+var OPERATION_NAME_DELETE_MONITOR = "Delete Monitor"
+var OPERATION_NAME_DELETE_LABEL_FROM_MONITOR = "Delete Label From Monitor"
+var OPERATION_NAME_DELETE_ALERT_POLICY_BY_ID = "Delete Alert Policy By ID"
+var OPERATION_NAME_DELETE_ALERT_POLICY_BY_NAME = "Delete Alert Policy By Name"
+var OPERATION_NAME_DELETE_ALERT_CONDITION = "Delete Alert Condition"
+var OPERATION_NAME_DELETE_DASHBOARD_BY_ID = "Delete Dashboard By ID"
+
+var OPERATION_NAME_ADD_LABEL_MONITOR = "Add Label Monitor"
+
+var OPERATION_NAME_INSERT_CUSTOM_EVENTS = "Insert Custom Events"
+
+var ERR_CREATE_NR_CLINET = errors.New("Call NewRelic REST error")
+var ERR_REST_CALL = errors.New("Call NewRelic REST error")
+var ERR_REST_CALL_NOT_2XX = errors.New("Status code is not 2XX calling NewRelic REST")
+var ERR_REST_CALL_400 = errors.New("Status code is 400 calling NewRelic REST")
+var ERR_REST_CHANNEL_NOT_EXIST = errors.New("No any notification channels")
+
+// var ERR_GET_MONITOR = errors.New("Get Monitor error")
+// var ERR_CREATE_MONITOR = errors.New("Create Monitor error")
+// var ERR_UPDATE_MONITOR = errors.New("Create Monitor error")
+// var ERR_PATCH_MONITOR = errors.New("Create Monitor error")
+// var ERR_DELETE_MONITOR = errors.New("Create Monitor error")
+
+var STATUS_CODE_MAPPING_CONDITIONS = make(map[int]string)
+var STATUS_CODE_MAPPING_MONITORS = make(map[int]string)
+var STATUS_CODE_MAPPING_MONITORS_SCRIPT = make(map[int]string)
+var STATUS_CODE_MAPPING_LABELS = make(map[int]string)
+var STATUS_CODE_MAPPING_LABELS_SYNTHETICS = make(map[int]string)
+var STATUS_CODE_MAPPING_ALERT_CHANNELS = make(map[int]string)
+var STATUS_CODE_MAPPING_ALERT_POLICIES = make(map[int]string)
+var STATUS_CODE_MAPPING_ALERT_CONDITIONS = make(map[int]string)
+var STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS = make(map[int]string)
+
+var GlobalRESTCallResultList RESTCallResultList
+
+func init() {
+ /*
+ alert conditions:
+
+ 401 Invalid API key
+ 401 Invalid request, API key required
+ 403 New Relic API access has not been enabled
+ 500 A server error occurred, please contact New Relic support
+ 404 No Alerts condition was found with the given ID
+ 406 Bad entity type
+ 422 Validation error occurred while trying to update the alert condition
+ */
+ STATUS_CODE_MAPPING_CONDITIONS[200] = "Success"
+ STATUS_CODE_MAPPING_CONDITIONS[400] = "Bad request"
+ STATUS_CODE_MAPPING_CONDITIONS[401] = "Invalid request, API key required"
+ STATUS_CODE_MAPPING_CONDITIONS[403] = "New Relic API access has not been enabled"
+ STATUS_CODE_MAPPING_CONDITIONS[500] = "A server error occurred, please contact New Relic support"
+ STATUS_CODE_MAPPING_CONDITIONS[404] = "No Alerts condition was found with the given ID"
+ STATUS_CODE_MAPPING_CONDITIONS[406] = "Bad entity type"
+ STATUS_CODE_MAPPING_CONDITIONS[422] = "Validation error occurred while trying to update the alert condition"
+
+ /*
+ synthetics monitors:
+ */
+ STATUS_CODE_MAPPING_MONITORS[200] = "Success"
+ STATUS_CODE_MAPPING_MONITORS[201] = "Success"
+ STATUS_CODE_MAPPING_MONITORS[204] = "Success"
+
+ STATUS_CODE_MAPPING_MONITORS[400] = "The monitor values is invalid, or the format of the request is invalid."
+ STATUS_CODE_MAPPING_MONITORS[404] = "The specified monitor doesn not exist"
+ STATUS_CODE_MAPPING_MONITORS[500] = "A server error occurred, please contact New Relic support"
+
+ /*
+ synthetics monitor script:
+ */
+ STATUS_CODE_MAPPING_MONITORS_SCRIPT[200] = "Success"
+ STATUS_CODE_MAPPING_MONITORS_SCRIPT[204] = "Success"
+
+ STATUS_CODE_MAPPING_MONITORS[400] = "The monitor values is invalid, or the format of the request is invalid."
+ STATUS_CODE_MAPPING_MONITORS[404] = "The specified monitor doesn not exist"
+ STATUS_CODE_MAPPING_MONITORS[500] = "A server error occurred, please contact New Relic support"
+
+ /*
+ labels
+
+ 401 Invalid API key
+ 401 Invalid request, API key required
+ 403 New Relic API access has not been enabled
+ 500 A server error occurred, please contact New Relic support
+ */
+ STATUS_CODE_MAPPING_LABELS[200] = "Success"
+ STATUS_CODE_MAPPING_LABELS[400] = "Bad request"
+ STATUS_CODE_MAPPING_LABELS[401] = "Invalid request, API key required"
+ STATUS_CODE_MAPPING_LABELS[403] = "New Relic API access has not been enabled"
+ STATUS_CODE_MAPPING_LABELS[500] = "A server error occurred, please contact New Relic support"
+
+ /*
+ label synthetics
+ */
+ STATUS_CODE_MAPPING_LABELS_SYNTHETICS[200] = "Success"
+ STATUS_CODE_MAPPING_LABELS_SYNTHETICS[204] = "Success"
+
+ STATUS_CODE_MAPPING_LABELS_SYNTHETICS[400] = "Bad request, or the format of the request is invalid."
+ STATUS_CODE_MAPPING_LABELS_SYNTHETICS[404] = "The specified label doesn not exist"
+ STATUS_CODE_MAPPING_LABELS_SYNTHETICS[500] = "A server error occurred, please contact New Relic support"
+
+ /*
+ alert channels
+
+ 401 Invalid API key
+ 401 Invalid request, API key required
+ 403 New Relic API access has not been enabled
+ 500 A server error occurred, please contact New Relic support
+ 422 Validation or internal error occurred
+ */
+
+ STATUS_CODE_MAPPING_ALERT_CHANNELS[200] = "Success"
+ STATUS_CODE_MAPPING_ALERT_CHANNELS[400] = "Bad request"
+ STATUS_CODE_MAPPING_ALERT_CHANNELS[401] = "Invalid request, API key required"
+ STATUS_CODE_MAPPING_ALERT_CHANNELS[403] = "New Relic API access has not been enabled"
+ STATUS_CODE_MAPPING_ALERT_CHANNELS[500] = "A server error occurred, please contact New Relic support"
+ STATUS_CODE_MAPPING_ALERT_CHANNELS[422] = "Validation or internal error occurred"
+
+ /*
+ alert policies
+
+ 401 Invalid API key
+ 401 Invalid request, API key required
+ 403 New Relic API access has not been enabled
+ 500 A server error occurred, please contact New Relic support
+ 422 Validation or internal error occurred
+ */
+
+ STATUS_CODE_MAPPING_ALERT_POLICIES[200] = "Success"
+ STATUS_CODE_MAPPING_ALERT_POLICIES[400] = "Bad request"
+ STATUS_CODE_MAPPING_ALERT_POLICIES[401] = "Invalid request, API key required"
+ STATUS_CODE_MAPPING_ALERT_POLICIES[403] = "New Relic API access has not been enabled"
+ STATUS_CODE_MAPPING_ALERT_POLICIES[500] = "A server error occurred, please contact New Relic support"
+ STATUS_CODE_MAPPING_ALERT_POLICIES[422] = "Validation or internal error occurred"
+
+ /*
+ alert conditions
+
+ 401 Invalid API key
+ 401 Invalid request, API key required
+ 403 New Relic API access has not been enabled
+ 500 A server error occurred, please contact New Relic support
+ 404 No Alerts policy was found for the given ID
+ 422 Validation error occurred while trying to create the alert condition
+ */
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[200] = "Success"
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[400] = "Bad request"
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[401] = "Invalid request, API key required"
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[403] = "New Relic API access has not been enabled"
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[404] = "No Alerts policy was found for the given ID"
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[500] = "A server error occurred, please contact New Relic support"
+ STATUS_CODE_MAPPING_ALERT_CONDITIONS[422] = "Validation error occurred while trying to create the alert condition"
+
+ /*
+ Insights custom events
+ */
+ STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[200] = "Success"
+ STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[400] = "Bad request"
+ STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[403] = "Invalid insert key"
+ STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[408] = "Request timed out"
+ STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[413] = "Content too large"
+ STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[429] = "Too many requests"
+
+ GlobalRESTCallResultList = RESTCallResultList{}
+}
+
+func AppendRESTCallResult(serviceInstance interface{}, operationName string, statusCode int, message string) {
+ ret := ToRESTCallResult(serviceInstance, operationName, statusCode, message)
+ GlobalRESTCallResultList.AllRESTCallResult = append(GlobalRESTCallResultList.AllRESTCallResult, ret)
+}
+
+func ToRESTCallResult(serviceInstance interface{}, operationName string, statusCode int, message string) RESTCallResult {
+ var ret RESTCallResult = RESTCallResult{}
+ ret.OperationName = operationName
+ ret.StatusCode = statusCode
+ ret.Message = message
+ var desc string = ""
+ desc = GetDescByStatusCode(serviceInstance, statusCode)
+ ret.Description = desc
+ return ret
+}
+
+func ToReturnValue(isContinue bool, operationName string, originalErr error, typicalErr error, description string) ReturnValue {
+ var ret ReturnValue = ReturnValue{}
+ ret.OriginalError = originalErr
+ ret.IsContinue = isContinue
+ ret.TypicalError = typicalErr
+ ret.Description = description
+ ret.OperationName = operationName
+ return ret
+}
+
+func GetDescByStatusCode(serviceInstance interface{}, statusCode int) string {
+ var desc string = ""
+
+ if statusCode == 200 {
+ desc = "Success"
+ return desc
+ }
+
+ var typeName string = reflect.TypeOf(serviceInstance).String()
+
+ if typeName == "" {
+
+ } else if typeName == "*newrelic.SyntheticsService" {
+ desc = STATUS_CODE_MAPPING_MONITORS[statusCode]
+ } else if typeName == "*newrelic.ScriptService" {
+ desc = STATUS_CODE_MAPPING_MONITORS_SCRIPT[statusCode]
+ } else if typeName == "*newrelic.LabelsService" {
+ desc = STATUS_CODE_MAPPING_LABELS[statusCode]
+ } else if typeName == "*newrelic.LabelsSyntheticsService" {
+ desc = STATUS_CODE_MAPPING_LABELS_SYNTHETICS[statusCode]
+ } else if typeName == "*newrelic.AlertsChannelsService" {
+ desc = STATUS_CODE_MAPPING_ALERT_CHANNELS[statusCode]
+ } else if typeName == "*newrelic.AlertsPoliciesService" {
+ desc = STATUS_CODE_MAPPING_ALERT_POLICIES[statusCode]
+ } else if typeName == "*newrelic.AlertsConditionsService" {
+ desc = STATUS_CODE_MAPPING_ALERT_CONDITIONS[statusCode]
+ } else if typeName == "*newrelic.CustomEventService" {
+ desc = STATUS_CODE_MAPPING_ALERT_CUSTOM_EVENTS[statusCode]
+ }
+
+ return desc
+}
+
+func GenerateBackupMonitorMeta(monitorList []*newrelic.Monitor) BackupMonitorMetaList {
+ var backupMonitorMetaList []BackupMonitorMeta
+ for _, monitor := range monitorList {
+ var m BackupMonitorMeta = BackupMonitorMeta{}
+ m.ID = *monitor.ID
+ m.Name = *monitor.Name
+ m.Type = *monitor.Type
+ if monitor.Script != nil && monitor.Script.ScriptText != nil {
+ m.Script = true
+ } else {
+ m.Script = false
+ }
+ if monitor.Labels != nil {
+ var labels []string
+ for _, label := range monitor.Labels {
+ labels = append(labels, *label)
+ }
+ m.Labels = labels
+ var labelLen = len(m.Labels)
+ m.LabelCount = labelLen
+ }
+ backupMonitorMetaList = append(backupMonitorMetaList, m)
+ }
+
+ var allList BackupMonitorMetaList = BackupMonitorMetaList{}
+ allList.AllBackupMonitorMeta = backupMonitorMetaList
+
+ return allList
+}
+
+func PrintStatisticsInfo(obj interface{}) {
+ //print statistics
+ var printer utils.Printer = &utils.TablePrinter{}
+ printer.Print(obj, os.Stdout)
+}
+
+func PrintBackupMonitorInfo(monitorList []*newrelic.Monitor) {
+ allList := GenerateBackupMonitorMeta(monitorList)
+ PrintStatisticsInfo(allList)
+ var monitorLen = len(monitorList)
+ var msg = strconv.Itoa(monitorLen) + " monitors backuped."
+ fmt.Println()
+ fmt.Println(msg)
+}
diff --git a/utils/decoder.go b/utils/decoder.go
new file mode 100644
index 0000000..c152ffb
--- /dev/null
+++ b/utils/decoder.go
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package utils
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strings"
+ "unicode"
+
+ "github.com/ghodss/yaml"
+)
+
+// ToJSON converts a single YAML document into a JSON document
+// or returns an error. If the document appears to be JSON the
+// YAML decoding path is not used (so that error messages are
+// JSON specific).
+func ToJSON(data []byte) ([]byte, error) {
+ if hasJSONPrefix(data) {
+ return data, nil
+ }
+ return yaml.YAMLToJSON(data)
+}
+
+// YAMLToJSONDecoder decodes YAML documents from an io.Reader by
+// separating individual documents. It first converts the YAML
+// body to JSON, then unmarshals the JSON.
+type YAMLToJSONDecoder struct {
+ reader Reader
+}
+
+// NewYAMLToJSONDecoder decodes YAML documents from the provided
+// stream in chunks by converting each document (as defined by
+// the YAML spec) into its own chunk, converting it to JSON via
+// yaml.YAMLToJSON, and then passing it to json.Decoder.
+func NewYAMLToJSONDecoder(r io.Reader) *YAMLToJSONDecoder {
+ reader := bufio.NewReader(r)
+ return &YAMLToJSONDecoder{
+ reader: NewYAMLReader(reader),
+ }
+}
+
+// Decode reads a YAML document as JSON from the stream or returns
+// an error. The decoding rules match json.Unmarshal, not
+// yaml.Unmarshal.
+func (d *YAMLToJSONDecoder) Decode(into interface{}) error {
+ bytes, err := d.reader.Read()
+ if err != nil && err != io.EOF {
+ return err
+ }
+
+ if len(bytes) != 0 {
+ err := yaml.Unmarshal(bytes, into)
+ if err != nil {
+ return YAMLSyntaxError{err}
+ }
+ }
+ return err
+}
+
+// YAMLDecoder reads chunks of objects and returns ErrShortBuffer if
+// the data is not sufficient.
+type YAMLDecoder struct {
+ r io.ReadCloser
+ scanner *bufio.Scanner
+ remaining []byte
+}
+
+// NewDocumentDecoder decodes YAML documents from the provided
+// stream in chunks by converting each document (as defined by
+// the YAML spec) into its own chunk. io.ErrShortBuffer will be
+// returned if the entire buffer could not be read to assist
+// the caller in framing the chunk.
+func NewDocumentDecoder(r io.ReadCloser) io.ReadCloser {
+ scanner := bufio.NewScanner(r)
+ scanner.Split(splitYAMLDocument)
+ return &YAMLDecoder{
+ r: r,
+ scanner: scanner,
+ }
+}
+
+// Read reads the previous slice into the buffer, or attempts to read
+// the next chunk.
+// TODO: switch to readline approach.
+func (d *YAMLDecoder) Read(data []byte) (n int, err error) {
+ left := len(d.remaining)
+ if left == 0 {
+ // return the next chunk from the stream
+ if !d.scanner.Scan() {
+ err := d.scanner.Err()
+ if err == nil {
+ err = io.EOF
+ }
+ return 0, err
+ }
+ out := d.scanner.Bytes()
+ d.remaining = out
+ left = len(out)
+ }
+
+ // fits within data
+ if left <= len(data) {
+ copy(data, d.remaining)
+ d.remaining = nil
+ return left, nil
+ }
+
+ // caller will need to reread
+ copy(data, d.remaining[:len(data)])
+ d.remaining = d.remaining[len(data):]
+ return len(data), io.ErrShortBuffer
+}
+
+func (d *YAMLDecoder) Close() error {
+ return d.r.Close()
+}
+
+const yamlSeparator = "\n---"
+const separator = "---"
+
+// splitYAMLDocument is a bufio.SplitFunc for splitting YAML streams into individual documents.
+func splitYAMLDocument(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ sep := len([]byte(yamlSeparator))
+ if i := bytes.Index(data, []byte(yamlSeparator)); i >= 0 {
+ // We have a potential document terminator
+ i += sep
+ after := data[i:]
+ if len(after) == 0 {
+ // we can't read any more characters
+ if atEOF {
+ return len(data), data[:len(data)-sep], nil
+ }
+ return 0, nil, nil
+ }
+ if j := bytes.IndexByte(after, '\n'); j >= 0 {
+ return i + j + 1, data[0 : i-sep], nil
+ }
+ return 0, nil, nil
+ }
+ // If we're at EOF, we have a final, non-terminated line. Return it.
+ if atEOF {
+ return len(data), data, nil
+ }
+ // Request more data.
+ return 0, nil, nil
+}
+
+// decoder is a convenience interface for Decode.
+type decoder interface {
+ Decode(into interface{}) error
+}
+
+// YAMLOrJSONDecoder attempts to decode a stream of JSON documents or
+// YAML documents by sniffing for a leading { character.
+type YAMLOrJSONDecoder struct {
+ r io.Reader
+ bufferSize int
+
+ decoder decoder
+ rawData []byte
+}
+
+type JSONSyntaxError struct {
+ Line int
+ Err error
+}
+
+func (e JSONSyntaxError) Error() string {
+ return fmt.Sprintf("json: line %d: %s", e.Line, e.Err.Error())
+}
+
+type YAMLSyntaxError struct {
+ err error
+}
+
+func (e YAMLSyntaxError) Error() string {
+ return e.err.Error()
+}
+
+// NewYAMLOrJSONDecoder returns a decoder that will process YAML documents
+// or JSON documents from the given reader as a stream. bufferSize determines
+// how far into the stream the decoder will look to figure out whether this
+// is a JSON stream (has whitespace followed by an open brace).
+func NewYAMLOrJSONDecoder(r io.Reader, bufferSize int) *YAMLOrJSONDecoder {
+ return &YAMLOrJSONDecoder{
+ r: r,
+ bufferSize: bufferSize,
+ }
+}
+
+// Decode unmarshals the next object from the underlying stream into the
+// provide object, or returns an error.
+func (d *YAMLOrJSONDecoder) Decode(into interface{}) error {
+ if d.decoder == nil {
+ buffer, origData, isJSON := GuessJSONStream(d.r, d.bufferSize)
+ if isJSON {
+ // fmt.Println("[DEBUG] decoding stream as JSON")
+ d.decoder = json.NewDecoder(buffer)
+ d.rawData = origData
+ } else {
+ // fmt.Println("[DEBUG] decoding stream as YAML")
+ d.decoder = NewYAMLToJSONDecoder(buffer)
+ }
+ }
+ err := d.decoder.Decode(into)
+ if jsonDecoder, ok := d.decoder.(*json.Decoder); ok {
+ if syntax, ok := err.(*json.SyntaxError); ok {
+ data, readErr := ioutil.ReadAll(jsonDecoder.Buffered())
+ if readErr != nil {
+ fmt.Printf("reading stream failed: %v\n", readErr)
+ }
+ js := string(data)
+
+ // if contents from io.Reader are not complete,
+ // use the original raw data to prevent panic
+ if int64(len(js)) <= syntax.Offset {
+ js = string(d.rawData)
+ }
+
+ start := strings.LastIndex(js[:syntax.Offset], "\n") + 1
+ line := strings.Count(js[:start], "\n")
+ return JSONSyntaxError{
+ Line: line,
+ Err: fmt.Errorf(syntax.Error()),
+ }
+ }
+ }
+ return err
+}
+
+type Reader interface {
+ Read() ([]byte, error)
+}
+
+type YAMLReader struct {
+ reader Reader
+}
+
+func NewYAMLReader(r *bufio.Reader) *YAMLReader {
+ return &YAMLReader{
+ reader: &LineReader{reader: r},
+ }
+}
+
+// Read returns a full YAML document.
+func (r *YAMLReader) Read() ([]byte, error) {
+ var buffer bytes.Buffer
+ for {
+ line, err := r.reader.Read()
+ if err != nil && err != io.EOF {
+ return nil, err
+ }
+
+ sep := len([]byte(separator))
+ if i := bytes.Index(line, []byte(separator)); i == 0 {
+ // We have a potential document terminator
+ i += sep
+ after := line[i:]
+ if len(strings.TrimRightFunc(string(after), unicode.IsSpace)) == 0 {
+ if buffer.Len() != 0 {
+ return buffer.Bytes(), nil
+ }
+ if err == io.EOF {
+ return nil, err
+ }
+ }
+ }
+ if err == io.EOF {
+ if buffer.Len() != 0 {
+ // If we're at EOF, we have a final, non-terminated line. Return it.
+ return buffer.Bytes(), nil
+ }
+ return nil, err
+ }
+ buffer.Write(line)
+ }
+}
+
+type LineReader struct {
+ reader *bufio.Reader
+}
+
+// Read returns a single line (with '\n' ended) from the underlying reader.
+// An error is returned iff there is an error with the underlying reader.
+func (r *LineReader) Read() ([]byte, error) {
+ var (
+ isPrefix bool = true
+ err error = nil
+ line []byte
+ buffer bytes.Buffer
+ )
+
+ for isPrefix && err == nil {
+ line, isPrefix, err = r.reader.ReadLine()
+ buffer.Write(line)
+ }
+ buffer.WriteByte('\n')
+ return buffer.Bytes(), err
+}
+
+// GuessJSONStream scans the provided reader up to size, looking
+// for an open brace indicating this is JSON. It will return the
+// bufio.Reader it creates for the consumer.
+func GuessJSONStream(r io.Reader, size int) (io.Reader, []byte, bool) {
+ buffer := bufio.NewReaderSize(r, size)
+ b, _ := buffer.Peek(size)
+ return buffer, b, hasJSONPrefix(b)
+}
+
+var jsonPrefix = []byte("{")
+
+// hasJSONPrefix returns true if the provided buffer appears to start with
+// a JSON open brace.
+func hasJSONPrefix(buf []byte) bool {
+ return hasPrefix(buf, jsonPrefix)
+}
+
+// Return true if the first non-whitespace bytes in buf is
+// prefix.
+func hasPrefix(buf []byte, prefix []byte) bool {
+ trim := bytes.TrimLeftFunc(buf, unicode.IsSpace)
+ return bytes.HasPrefix(trim, prefix)
+}
diff --git a/utils/printer.go b/utils/printer.go
new file mode 100644
index 0000000..432b411
--- /dev/null
+++ b/utils/printer.go
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package utils
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "reflect"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/ghodss/yaml"
+ "github.com/spf13/cobra"
+)
+
+type Printer interface {
+ Print(obj interface{}, out io.Writer)
+}
+
+func GetArg(cmd *cobra.Command, arg string) (string, error) {
+ flags := cmd.Flags()
+
+ var val string
+ var err error
+ if flags.Lookup(arg) != nil {
+ val, err = cmd.Flags().GetString(arg)
+ if err != nil {
+ return "", fmt.Errorf("error accessing flag %s for command %s: %v", arg, cmd.Name(), err)
+ }
+ }
+
+ return val, err
+}
+
+func NewPriter(cmd *cobra.Command) (Printer, error) {
+ flags := cmd.Flags()
+
+ var output string
+ var err error
+ if flags.Lookup("output") != nil {
+ output, err = cmd.Flags().GetString("output")
+ if err != nil {
+ return nil, fmt.Errorf("error accessing flag %s for command %s: %v", "output", cmd.Name(), err)
+ }
+ }
+
+ var printer Printer
+ switch output {
+ case "yaml", "yml":
+ printer = &YAMLPrinter{}
+ case "json":
+ printer = &JSONPrinter{}
+ default:
+ printer = &TablePrinter{}
+ }
+
+ return printer, nil
+}
+
+type JSONPrinter struct{}
+
+type YAMLPrinter struct{}
+
+type TablePrinter struct{}
+
+func (p *JSONPrinter) Print(obj interface{}, out io.Writer) {
+ if output, err := json.MarshalIndent(obj, "", " "); err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Printf("%s\n", string(output))
+ }
+}
+
+func (p *YAMLPrinter) Print(obj interface{}, out io.Writer) {
+ if output, err := yaml.Marshal(obj); err != nil {
+ fmt.Println(err)
+ } else {
+ fmt.Printf("%s\n", string(output))
+ }
+}
+
+func (p *TablePrinter) Print(obj interface{}, out io.Writer) {
+ w := new(tabwriter.Writer)
+ w.Init(out, 5, 1, 3, ' ', 0)
+
+ val := reflect.ValueOf(obj)
+ if val.Kind() == reflect.Ptr {
+ val = val.Elem()
+ }
+
+ // smartly detect if obj is a List or plain Object
+ if val.NumField() == 1 {
+ val = val.Field(0)
+ if val.Kind() == reflect.Ptr {
+ val = val.Elem()
+ }
+ if val.Kind() == reflect.Slice {
+ // iterate each Object
+ heading := []string{}
+ rows := []string{}
+ for i := 0; i < val.Len(); i++ {
+ e := val.Index(i)
+ if e.Kind() == reflect.Ptr {
+ e = e.Elem()
+ }
+ t := e.Type()
+ row := []string{}
+ for j := 0; j < e.NumField(); j++ {
+ f := e.Field(j)
+ if f.Kind() == reflect.Ptr {
+ f = f.Elem()
+ }
+ if i == 0 {
+ heading = append(heading, fmt.Sprint(t.Field(j).Name))
+ }
+ row = append(row, fmt.Sprint(f.Interface()))
+ // fmt.Printf("%d: %s %s = %v\n", j, t.Field(j).Name, f.Type(), f.Elem().Interface())
+ }
+ rows = append(rows, strings.Join(row, "\t"))
+ }
+ if len(heading) == 0 {
+ fmt.Fprintln(w, "No resources found.")
+ } else {
+ fmt.Fprintln(w, strings.Join(heading, "\t"))
+ fmt.Fprintln(w, strings.Join(rows, "\n"))
+ }
+ } else if val.Kind() == reflect.Struct {
+ t := val.Type()
+ heading := []string{}
+ row := []string{}
+ for j := 0; j < val.NumField(); j++ {
+ f := val.Field(j)
+ heading = append(heading, fmt.Sprint(t.Field(j).Name))
+ row = append(row, fmt.Sprint(f.Elem().Interface()))
+ // fmt.Printf("%d: %s %s = %v\n", j, t.Field(j).Name, f.Type(), f.Elem().Interface())
+ }
+ if len(heading) == 0 {
+ fmt.Fprintln(w, "No resources found.")
+ } else {
+ fmt.Fprintln(w, strings.Join(heading, "\t"))
+ fmt.Fprintln(w, strings.Join(row, "\t"))
+ }
+ }
+ } else {
+ fmt.Println("[WARNING] unsupported data format.")
+ }
+
+ w.Flush()
+}
diff --git a/utils/util.go b/utils/util.go
new file mode 100644
index 0000000..bc94081
--- /dev/null
+++ b/utils/util.go
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2017-2018 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package utils
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "os"
+
+ "github.com/IBM/newrelic-cli/newrelic"
+)
+
+// GetNewRelicClient returns a NewRelicClient, if env var NEW_RELIC_APIKEY is set
+func GetNewRelicClient(ctype ...string) (*newrelic.Client, error) {
+ var client *newrelic.Client
+
+ var httpClient *http.Client
+
+ proxyStr := os.Getenv("NEW_RELIC_PROXY")
+ if proxyStr != "" {
+ url, _ := url.Parse(proxyStr)
+ proxyURL := http.ProxyURL(url)
+ httpClient = &http.Client{
+ Transport: &http.Transport{
+ Proxy: proxyURL,
+ },
+ }
+ }
+
+ var needCheckAPIKey = true
+
+ if len(ctype) == 0 {
+ client = newrelic.NewClient(httpClient, "default")
+ } else {
+ if ctype[0] == "synthetics" {
+ client = newrelic.NewClient(httpClient, "synthetics")
+ } else if ctype[0] == "labelSynthetics" {
+ client = newrelic.NewClient(httpClient, "labelSynthetics")
+ } else if ctype[0] == "insights" {
+ client = newrelic.NewClient(httpClient, "insights")
+ needCheckAPIKey = false
+ }
+ }
+
+ if needCheckAPIKey == true {
+ apikey := os.Getenv("NEW_RELIC_APIKEY")
+ if apikey == "" {
+ return nil, fmt.Errorf("No NEW_RELIC_APIKEY detected.")
+ }
+
+ client.XApiKey = apikey
+ }
+
+ proxyAuth := os.Getenv("PROXY_AUTH")
+ client.ProxyAuth = proxyAuth
+ return client, nil
+}
+
+func MergeMonitorList(s1 []*newrelic.Monitor, s2 []*newrelic.Monitor) (slice []*newrelic.Monitor) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.Monitor, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return
+}
+
+func MergeLabelList(s1 []*newrelic.Label, s2 []*newrelic.Label) (slice []*newrelic.Label) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.Label, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return
+}
+
+func MergeMonitorReflList(s1 []*newrelic.MonitorRef, s2 []*newrelic.MonitorRef) (slice []*newrelic.MonitorRef) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.MonitorRef, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return
+}
+
+func MergeStringList(s1 []*string, s2 []*string) (slice []*string) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*string, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return
+}
+
+func MergeAlertPolicyList(s1 []*newrelic.AlertsPolicy, s2 []*newrelic.AlertsPolicy) (slice []*newrelic.AlertsPolicy) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsPolicy, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}
+
+func MergeAlertDefaultConditionsList(s1 []*newrelic.AlertsDefaultCondition, s2 []*newrelic.AlertsDefaultCondition) (slice []*newrelic.AlertsDefaultCondition) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsDefaultCondition, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}
+
+func MergeAlertExternalServiceConditionsList(s1 []*newrelic.AlertsExternalServiceCondition, s2 []*newrelic.AlertsExternalServiceCondition) (slice []*newrelic.AlertsExternalServiceCondition) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsExternalServiceCondition, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}
+
+func MergeAlertNRQLConditionsList(s1 []*newrelic.AlertsNRQLCondition, s2 []*newrelic.AlertsNRQLCondition) (slice []*newrelic.AlertsNRQLCondition) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsNRQLCondition, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}
+
+func MergeAlertPluginsConditionsList(s1 []*newrelic.AlertsPluginsCondition, s2 []*newrelic.AlertsPluginsCondition) (slice []*newrelic.AlertsPluginsCondition) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsPluginsCondition, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}
+
+func MergeAlertSyntheticsConditionsList(s1 []*newrelic.AlertsSyntheticsCondition, s2 []*newrelic.AlertsSyntheticsCondition) (slice []*newrelic.AlertsSyntheticsCondition) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsSyntheticsCondition, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}
+
+func MergeAlertConditionList(s1 *newrelic.AlertsConditionList, s2 *newrelic.AlertsConditionList) *newrelic.AlertsConditionList {
+ var newList *newrelic.AlertsConditionList = &newrelic.AlertsConditionList{}
+ newList.AlertsDefaultConditionList = &newrelic.AlertsDefaultConditionList{}
+ newList.AlertsExternalServiceConditionList = &newrelic.AlertsExternalServiceConditionList{}
+ newList.AlertsNRQLConditionList = &newrelic.AlertsNRQLConditionList{}
+ newList.AlertsPluginsConditionList = &newrelic.AlertsPluginsConditionList{}
+ newList.AlertsSyntheticsConditionList = &newrelic.AlertsSyntheticsConditionList{}
+
+ //default
+ if s1.AlertsDefaultConditionList != nil && s2.AlertsDefaultConditionList != nil {
+ newList.AlertsDefaultConditions = MergeAlertDefaultConditionsList(s1.AlertsDefaultConditionList.AlertsDefaultConditions, s2.AlertsDefaultConditionList.AlertsDefaultConditions)
+ }
+
+ //ExternalService
+ if s1.AlertsExternalServiceConditionList != nil && s2.AlertsExternalServiceConditionList != nil {
+ newList.AlertsExternalServiceConditions = MergeAlertExternalServiceConditionsList(s1.AlertsExternalServiceConditionList.AlertsExternalServiceConditions, s2.AlertsExternalServiceConditionList.AlertsExternalServiceConditions)
+ }
+ //nrql
+ if s1.AlertsNRQLConditionList != nil && s2.AlertsNRQLConditionList != nil {
+ newList.AlertsNRQLConditions = MergeAlertNRQLConditionsList(s1.AlertsNRQLConditionList.AlertsNRQLConditions, s2.AlertsNRQLConditionList.AlertsNRQLConditions)
+ }
+ //plugin
+ if s1.AlertsPluginsConditionList != nil && s2.AlertsPluginsConditionList != nil {
+ newList.AlertsPluginsConditions = MergeAlertPluginsConditionsList(s1.AlertsPluginsConditionList.AlertsPluginsConditions, s2.AlertsPluginsConditionList.AlertsPluginsConditions)
+ }
+ //synthetics
+ if s1.AlertsSyntheticsConditionList != nil && s2.AlertsSyntheticsConditionList != nil {
+ newList.AlertsSyntheticsConditions = MergeAlertSyntheticsConditionsList(s1.AlertsSyntheticsConditionList.AlertsSyntheticsConditions, s2.AlertsSyntheticsConditionList.AlertsSyntheticsConditions)
+ }
+ return newList
+}
+
+func MergeAlertChannelList(s1 []*newrelic.AlertsChannel, s2 []*newrelic.AlertsChannel) (slice []*newrelic.AlertsChannel) {
+ var len1 = len(s1)
+ var len2 = len(s2)
+ var len3 = len1 + len2
+ slice = make([]*newrelic.AlertsChannel, len3)
+
+ for i := 0; i < len1; i++ {
+ slice[i] = s1[i]
+ }
+ for j := 0; j < len2; j++ {
+ slice[j+len1] = s2[j]
+ }
+
+ return slice
+}