provider/ns1: Add notify list resource (#12373)
* Allow for local development with ns1 provider. * Adds first implementation of ns1 notification list resource. * NS1 record.use_client_subnet defaults to true, and added test for field. * Adds more test cases for monitoring jobs. * Adds webhook/datafeed notifier types and acctests for notifylists. * Adds docs for notifylists resource. * Updates ns1-go rest client via govendor * Fix typos in record docs
This commit is contained in:
parent
120e3af178
commit
ce633f2321
|
@ -1,6 +1,7 @@
|
||||||
package ns1
|
package ns1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
@ -19,6 +20,18 @@ func Provider() terraform.ResourceProvider {
|
||||||
DefaultFunc: schema.EnvDefaultFunc("NS1_APIKEY", nil),
|
DefaultFunc: schema.EnvDefaultFunc("NS1_APIKEY", nil),
|
||||||
Description: descriptions["api_key"],
|
Description: descriptions["api_key"],
|
||||||
},
|
},
|
||||||
|
"endpoint": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("NS1_ENDPOINT", nil),
|
||||||
|
Description: descriptions["endpoint"],
|
||||||
|
},
|
||||||
|
"ignore_ssl": &schema.Schema{
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
DefaultFunc: schema.EnvDefaultFunc("NS1_IGNORE_SSL", nil),
|
||||||
|
Description: descriptions["ignore_ssl"],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
"ns1_zone": zoneResource(),
|
"ns1_zone": zoneResource(),
|
||||||
|
@ -26,6 +39,7 @@ func Provider() terraform.ResourceProvider {
|
||||||
"ns1_datasource": dataSourceResource(),
|
"ns1_datasource": dataSourceResource(),
|
||||||
"ns1_datafeed": dataFeedResource(),
|
"ns1_datafeed": dataFeedResource(),
|
||||||
"ns1_monitoringjob": monitoringJobResource(),
|
"ns1_monitoringjob": monitoringJobResource(),
|
||||||
|
"ns1_notifylist": notifyListResource(),
|
||||||
"ns1_user": userResource(),
|
"ns1_user": userResource(),
|
||||||
"ns1_apikey": apikeyResource(),
|
"ns1_apikey": apikeyResource(),
|
||||||
"ns1_team": teamResource(),
|
"ns1_team": teamResource(),
|
||||||
|
@ -36,7 +50,19 @@ func Provider() terraform.ResourceProvider {
|
||||||
|
|
||||||
func ns1Configure(d *schema.ResourceData) (interface{}, error) {
|
func ns1Configure(d *schema.ResourceData) (interface{}, error) {
|
||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{}
|
||||||
n := ns1.NewClient(httpClient, ns1.SetAPIKey(d.Get("apikey").(string)))
|
decos := []func(*ns1.Client){}
|
||||||
|
decos = append(decos, ns1.SetAPIKey(d.Get("apikey").(string)))
|
||||||
|
if v, ok := d.GetOk("endpoint"); ok {
|
||||||
|
decos = append(decos, ns1.SetEndpoint(v.(string)))
|
||||||
|
}
|
||||||
|
if _, ok := d.GetOk("ignore_ssl"); ok {
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
httpClient.Transport = tr
|
||||||
|
}
|
||||||
|
|
||||||
|
n := ns1.NewClient(httpClient, decos...)
|
||||||
n.RateLimitStrategySleep()
|
n.RateLimitStrategySleep()
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,6 +166,7 @@ func monitoringJobToResourceData(d *schema.ResourceData, r *monitor.Job) error {
|
||||||
m["key"] = r.Key
|
m["key"] = r.Key
|
||||||
rules[i] = m
|
rules[i] = m
|
||||||
}
|
}
|
||||||
|
d.Set("rules", rules)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,11 @@ func TestAccMonitoringJob_basic(t *testing.T) {
|
||||||
testAccCheckMonitoringJobRapidRecheck(&mj, false),
|
testAccCheckMonitoringJobRapidRecheck(&mj, false),
|
||||||
testAccCheckMonitoringJobPolicy(&mj, "quorum"),
|
testAccCheckMonitoringJobPolicy(&mj, "quorum"),
|
||||||
testAccCheckMonitoringJobConfigSend(&mj, "HEAD / HTTP/1.0\r\n\r\n"),
|
testAccCheckMonitoringJobConfigSend(&mj, "HEAD / HTTP/1.0\r\n\r\n"),
|
||||||
testAccCheckMonitoringJobConfigPort(&mj, 80),
|
testAccCheckMonitoringJobConfigPort(&mj, 443),
|
||||||
testAccCheckMonitoringJobConfigHost(&mj, "1.1.1.1"),
|
testAccCheckMonitoringJobConfigHost(&mj, "1.2.3.4"),
|
||||||
|
testAccCheckMonitoringJobRuleValue(&mj, "200 OK"),
|
||||||
|
testAccCheckMonitoringJobRuleComparison(&mj, "contains"),
|
||||||
|
testAccCheckMonitoringJobRuleKey(&mj, "output"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -58,8 +61,11 @@ func TestAccMonitoringJob_updated(t *testing.T) {
|
||||||
testAccCheckMonitoringJobRapidRecheck(&mj, false),
|
testAccCheckMonitoringJobRapidRecheck(&mj, false),
|
||||||
testAccCheckMonitoringJobPolicy(&mj, "quorum"),
|
testAccCheckMonitoringJobPolicy(&mj, "quorum"),
|
||||||
testAccCheckMonitoringJobConfigSend(&mj, "HEAD / HTTP/1.0\r\n\r\n"),
|
testAccCheckMonitoringJobConfigSend(&mj, "HEAD / HTTP/1.0\r\n\r\n"),
|
||||||
testAccCheckMonitoringJobConfigPort(&mj, 80),
|
testAccCheckMonitoringJobConfigPort(&mj, 443),
|
||||||
testAccCheckMonitoringJobConfigHost(&mj, "1.1.1.1"),
|
testAccCheckMonitoringJobConfigHost(&mj, "1.2.3.4"),
|
||||||
|
testAccCheckMonitoringJobRuleValue(&mj, "200 OK"),
|
||||||
|
testAccCheckMonitoringJobRuleComparison(&mj, "contains"),
|
||||||
|
testAccCheckMonitoringJobRuleKey(&mj, "output"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
resource.TestStep{
|
resource.TestStep{
|
||||||
|
@ -76,6 +82,9 @@ func TestAccMonitoringJob_updated(t *testing.T) {
|
||||||
testAccCheckMonitoringJobConfigSend(&mj, "HEAD / HTTP/1.0\r\n\r\n"),
|
testAccCheckMonitoringJobConfigSend(&mj, "HEAD / HTTP/1.0\r\n\r\n"),
|
||||||
testAccCheckMonitoringJobConfigPort(&mj, 443),
|
testAccCheckMonitoringJobConfigPort(&mj, 443),
|
||||||
testAccCheckMonitoringJobConfigHost(&mj, "1.1.1.1"),
|
testAccCheckMonitoringJobConfigHost(&mj, "1.1.1.1"),
|
||||||
|
testAccCheckMonitoringJobRuleValue(&mj, "200"),
|
||||||
|
testAccCheckMonitoringJobRuleComparison(&mj, "<="),
|
||||||
|
testAccCheckMonitoringJobRuleKey(&mj, "connect"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -242,6 +251,33 @@ func testAccCheckMonitoringJobConfigHost(mj *monitor.Job, expected string) resou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccCheckMonitoringJobRuleValue(mj *monitor.Job, expected string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if mj.Rules[0].Value.(string) != expected {
|
||||||
|
return fmt.Errorf("Rules[0].Value: got: %#v want: %#v", mj.Rules[0].Value.(string), expected)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckMonitoringJobRuleComparison(mj *monitor.Job, expected string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if mj.Rules[0].Comparison != expected {
|
||||||
|
return fmt.Errorf("Rules[0].Comparison: got: %#v want: %#v", mj.Rules[0].Comparison, expected)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckMonitoringJobRuleKey(mj *monitor.Job, expected string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if mj.Rules[0].Key != expected {
|
||||||
|
return fmt.Errorf("Rules[0].Key: got: %#v want: %#v", mj.Rules[0].Key, expected)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const testAccMonitoringJobBasic = `
|
const testAccMonitoringJobBasic = `
|
||||||
resource "ns1_monitoringjob" "it" {
|
resource "ns1_monitoringjob" "it" {
|
||||||
job_type = "tcp"
|
job_type = "tcp"
|
||||||
|
@ -250,10 +286,16 @@ resource "ns1_monitoringjob" "it" {
|
||||||
regions = ["lga"]
|
regions = ["lga"]
|
||||||
frequency = 60
|
frequency = 60
|
||||||
|
|
||||||
config {
|
config = {
|
||||||
|
ssl = "1",
|
||||||
send = "HEAD / HTTP/1.0\r\n\r\n"
|
send = "HEAD / HTTP/1.0\r\n\r\n"
|
||||||
port = 80
|
port = 443
|
||||||
host = "1.1.1.1"
|
host = "1.2.3.4"
|
||||||
|
}
|
||||||
|
rules = {
|
||||||
|
value = "200 OK"
|
||||||
|
comparison = "contains"
|
||||||
|
key = "output"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -269,10 +311,16 @@ resource "ns1_monitoringjob" "it" {
|
||||||
rapid_recheck = true
|
rapid_recheck = true
|
||||||
policy = "all"
|
policy = "all"
|
||||||
|
|
||||||
config {
|
config = {
|
||||||
|
ssl = "1",
|
||||||
send = "HEAD / HTTP/1.0\r\n\r\n"
|
send = "HEAD / HTTP/1.0\r\n\r\n"
|
||||||
port = 443
|
port = 443
|
||||||
host = "1.1.1.1"
|
host = "1.1.1.1"
|
||||||
}
|
}
|
||||||
|
rules = {
|
||||||
|
value = 200
|
||||||
|
comparison = "<="
|
||||||
|
key = "connect"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
package ns1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
|
||||||
|
"gopkg.in/ns1/ns1-go.v2/rest/model/monitor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func notifyListResource() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"id": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
"name": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"notifications": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Resource{
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"type": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"config": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Create: NotifyListCreate,
|
||||||
|
Read: NotifyListRead,
|
||||||
|
Update: NotifyListUpdate,
|
||||||
|
Delete: NotifyListDelete,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyListToResourceData(d *schema.ResourceData, nl *monitor.NotifyList) error {
|
||||||
|
d.SetId(nl.ID)
|
||||||
|
d.Set("name", nl.Name)
|
||||||
|
|
||||||
|
if len(nl.Notifications) > 0 {
|
||||||
|
notifications := make([]map[string]interface{}, len(nl.Notifications))
|
||||||
|
for i, n := range nl.Notifications {
|
||||||
|
ni := make(map[string]interface{})
|
||||||
|
ni["type"] = n.Type
|
||||||
|
if n.Config != nil {
|
||||||
|
ni["config"] = n.Config
|
||||||
|
}
|
||||||
|
notifications[i] = ni
|
||||||
|
}
|
||||||
|
d.Set("notifications", notifications)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceDataToNotifyList(nl *monitor.NotifyList, d *schema.ResourceData) error {
|
||||||
|
nl.ID = d.Id()
|
||||||
|
|
||||||
|
if rawNotifications := d.Get("notifications").([]interface{}); len(rawNotifications) > 0 {
|
||||||
|
ns := make([]*monitor.Notification, len(rawNotifications))
|
||||||
|
for i, notificationRaw := range rawNotifications {
|
||||||
|
ni := notificationRaw.(map[string]interface{})
|
||||||
|
config := ni["config"].(map[string]interface{})
|
||||||
|
|
||||||
|
switch ni["type"].(string) {
|
||||||
|
case "webhook":
|
||||||
|
ns[i] = monitor.NewWebNotification(config["url"].(string))
|
||||||
|
case "email":
|
||||||
|
ns[i] = monitor.NewEmailNotification(config["email"].(string))
|
||||||
|
case "datafeed":
|
||||||
|
ns[i] = monitor.NewFeedNotification(config["sourceid"].(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nl.Notifications = ns
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyListCreate creates an ns1 notifylist
|
||||||
|
func NotifyListCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*ns1.Client)
|
||||||
|
nl := monitor.NewNotifyList(d.Get("name").(string))
|
||||||
|
|
||||||
|
if err := resourceDataToNotifyList(nl, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.Notifications.Create(nl); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifyListToResourceData(d, nl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyListRead fetches info for the given notifylist from ns1
|
||||||
|
func NotifyListRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*ns1.Client)
|
||||||
|
|
||||||
|
nl, _, err := client.Notifications.Get(d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifyListToResourceData(d, nl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyListDelete deletes the given notifylist from ns1
|
||||||
|
func NotifyListDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*ns1.Client)
|
||||||
|
|
||||||
|
_, err := client.Notifications.Delete(d.Id())
|
||||||
|
d.SetId("")
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyListUpdate updates the notifylist with given parameters
|
||||||
|
func NotifyListUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
client := meta.(*ns1.Client)
|
||||||
|
|
||||||
|
nl := monitor.NewNotifyList(d.Get("name").(string))
|
||||||
|
|
||||||
|
if err := resourceDataToNotifyList(nl, d); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := client.Notifications.Update(nl); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return notifyListToResourceData(d, nl)
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
package ns1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
|
||||||
|
ns1 "gopkg.in/ns1/ns1-go.v2/rest"
|
||||||
|
"gopkg.in/ns1/ns1-go.v2/rest/model/monitor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccNotifyList_basic(t *testing.T) {
|
||||||
|
var nl monitor.NotifyList
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckNotifyListDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccNotifyListBasic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckNotifyListExists("ns1_notifylist.test", &nl),
|
||||||
|
testAccCheckNotifyListName(&nl, "terraform test"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccNotifyList_updated(t *testing.T) {
|
||||||
|
var nl monitor.NotifyList
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckNotifyListDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccNotifyListBasic,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckNotifyListExists("ns1_notifylist.test", &nl),
|
||||||
|
testAccCheckNotifyListName(&nl, "terraform test"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccNotifyListUpdated,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckNotifyListExists("ns1_notifylist.test", &nl),
|
||||||
|
testAccCheckNotifyListName(&nl, "terraform test"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckNotifyListState(key, value string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources["ns1_notifylist.test"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Not found: %s", "ns1_notifylist.test")
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("No ID is set")
|
||||||
|
}
|
||||||
|
|
||||||
|
p := rs.Primary
|
||||||
|
if p.Attributes[key] != value {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"%s != %s (actual: %s)", key, value, p.Attributes[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckNotifyListExists(n string, nl *monitor.NotifyList) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Resource not found: %v", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := rs.Primary.ID
|
||||||
|
if id == "" {
|
||||||
|
return fmt.Errorf("ID is not set")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := testAccProvider.Meta().(*ns1.Client)
|
||||||
|
|
||||||
|
foundNl, _, err := client.Notifications.Get(id)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if foundNl.ID != id {
|
||||||
|
return fmt.Errorf("Notify List not found want: %#v, got %#v", id, foundNl)
|
||||||
|
}
|
||||||
|
|
||||||
|
*nl = *foundNl
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckNotifyListDestroy(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*ns1.Client)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "ns1_notifylist" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
nl, _, err := client.Notifications.Get(rs.Primary.Attributes["id"])
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Notify List still exists %#v: %#v", err, nl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckNotifyListName(nl *monitor.NotifyList, expected string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if nl.Name != expected {
|
||||||
|
return fmt.Errorf("Name: got: %#v want: %#v", nl.Name, expected)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccNotifyListBasic = `
|
||||||
|
resource "ns1_notifylist" "test" {
|
||||||
|
name = "terraform test"
|
||||||
|
notifications = {
|
||||||
|
type = "webhook"
|
||||||
|
config = {
|
||||||
|
url = "http://localhost:9090"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const testAccNotifyListUpdated = `
|
||||||
|
resource "ns1_notifylist" "test" {
|
||||||
|
name = "terraform test"
|
||||||
|
notifications = {
|
||||||
|
type = "webhook"
|
||||||
|
config = {
|
||||||
|
url = "http://localhost:9091"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
|
@ -69,7 +69,7 @@ func recordResource() *schema.Resource {
|
||||||
"use_client_subnet": &schema.Schema{
|
"use_client_subnet": &schema.Schema{
|
||||||
Type: schema.TypeBool,
|
Type: schema.TypeBool,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Default: false,
|
Default: true,
|
||||||
},
|
},
|
||||||
"answers": &schema.Schema{
|
"answers": &schema.Schema{
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
|
@ -264,10 +264,8 @@ func resourceDataToRecord(r *dns.Record, d *schema.ResourceData) error {
|
||||||
// if v, ok := d.GetOk("meta"); ok {
|
// if v, ok := d.GetOk("meta"); ok {
|
||||||
// metaDynamicToStruct(r.Meta, v)
|
// metaDynamicToStruct(r.Meta, v)
|
||||||
// }
|
// }
|
||||||
if v, ok := d.GetOk("use_client_subnet"); ok {
|
useClientSubnet := d.Get("use_client_subnet").(bool)
|
||||||
copy := v.(bool)
|
r.UseClientSubnet = &useClientSubnet
|
||||||
r.UseClientSubnet = ©
|
|
||||||
}
|
|
||||||
|
|
||||||
if rawFilters := d.Get("filters").([]interface{}); len(rawFilters) > 0 {
|
if rawFilters := d.Get("filters").([]interface{}); len(rawFilters) > 0 {
|
||||||
f := make([]*filter.Filter, len(rawFilters))
|
f := make([]*filter.Filter, len(rawFilters))
|
||||||
|
|
|
@ -26,6 +26,7 @@ func TestAccRecord_basic(t *testing.T) {
|
||||||
testAccCheckRecordExists("ns1_record.it", &record),
|
testAccCheckRecordExists("ns1_record.it", &record),
|
||||||
testAccCheckRecordDomain(&record, "test.terraform-record-test.io"),
|
testAccCheckRecordDomain(&record, "test.terraform-record-test.io"),
|
||||||
testAccCheckRecordTTL(&record, 60),
|
testAccCheckRecordTTL(&record, 60),
|
||||||
|
testAccCheckRecordUseClientSubnet(&record, true),
|
||||||
testAccCheckRecordRegionName(&record, []string{"cal"}),
|
testAccCheckRecordRegionName(&record, []string{"cal"}),
|
||||||
// testAccCheckRecordAnswerMetaWeight(&record, 10),
|
// testAccCheckRecordAnswerMetaWeight(&record, 10),
|
||||||
testAccCheckRecordAnswerRdata(&record, "test1.terraform-record-test.io"),
|
testAccCheckRecordAnswerRdata(&record, "test1.terraform-record-test.io"),
|
||||||
|
@ -48,6 +49,7 @@ func TestAccRecord_updated(t *testing.T) {
|
||||||
testAccCheckRecordExists("ns1_record.it", &record),
|
testAccCheckRecordExists("ns1_record.it", &record),
|
||||||
testAccCheckRecordDomain(&record, "test.terraform-record-test.io"),
|
testAccCheckRecordDomain(&record, "test.terraform-record-test.io"),
|
||||||
testAccCheckRecordTTL(&record, 60),
|
testAccCheckRecordTTL(&record, 60),
|
||||||
|
testAccCheckRecordUseClientSubnet(&record, true),
|
||||||
testAccCheckRecordRegionName(&record, []string{"cal"}),
|
testAccCheckRecordRegionName(&record, []string{"cal"}),
|
||||||
// testAccCheckRecordAnswerMetaWeight(&record, 10),
|
// testAccCheckRecordAnswerMetaWeight(&record, 10),
|
||||||
testAccCheckRecordAnswerRdata(&record, "test1.terraform-record-test.io"),
|
testAccCheckRecordAnswerRdata(&record, "test1.terraform-record-test.io"),
|
||||||
|
@ -59,6 +61,7 @@ func TestAccRecord_updated(t *testing.T) {
|
||||||
testAccCheckRecordExists("ns1_record.it", &record),
|
testAccCheckRecordExists("ns1_record.it", &record),
|
||||||
testAccCheckRecordDomain(&record, "test.terraform-record-test.io"),
|
testAccCheckRecordDomain(&record, "test.terraform-record-test.io"),
|
||||||
testAccCheckRecordTTL(&record, 120),
|
testAccCheckRecordTTL(&record, 120),
|
||||||
|
testAccCheckRecordUseClientSubnet(&record, false),
|
||||||
testAccCheckRecordRegionName(&record, []string{"ny", "wa"}),
|
testAccCheckRecordRegionName(&record, []string{"ny", "wa"}),
|
||||||
// testAccCheckRecordAnswerMetaWeight(&record, 5),
|
// testAccCheckRecordAnswerMetaWeight(&record, 5),
|
||||||
testAccCheckRecordAnswerRdata(&record, "test2.terraform-record-test.io"),
|
testAccCheckRecordAnswerRdata(&record, "test2.terraform-record-test.io"),
|
||||||
|
@ -143,6 +146,15 @@ func testAccCheckRecordTTL(r *dns.Record, expected int) resource.TestCheckFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAccCheckRecordUseClientSubnet(r *dns.Record, expected bool) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if *r.UseClientSubnet != expected {
|
||||||
|
return fmt.Errorf("UseClientSubnet: got: %#v want: %#v", *r.UseClientSubnet, expected)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckRecordRegionName(r *dns.Record, expected []string) resource.TestCheckFunc {
|
func testAccCheckRecordRegionName(r *dns.Record, expected []string) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
regions := make([]string, len(r.Regions))
|
regions := make([]string, len(r.Regions))
|
||||||
|
@ -240,7 +252,7 @@ resource "ns1_record" "it" {
|
||||||
domain = "test.${ns1_zone.test.zone}"
|
domain = "test.${ns1_zone.test.zone}"
|
||||||
type = "CNAME"
|
type = "CNAME"
|
||||||
ttl = 120
|
ttl = 120
|
||||||
use_client_subnet = true
|
use_client_subnet = false
|
||||||
|
|
||||||
// meta {
|
// meta {
|
||||||
// weight = 5
|
// weight = 5
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
.PHONY: all clean
|
|
||||||
|
|
||||||
all: .git/hooks/pre-commit
|
|
||||||
go build .
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f terraform-provider-nsone
|
|
||||||
|
|
||||||
.git/hooks/pre-commit:
|
|
||||||
if [ ! -f .git/hooks/pre-commit ]; then ln -s ../../git-hooks/pre-commit .git/hooks/pre-commit; fi
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# NS1 Golang SDK
|
# NS1 Golang SDK
|
||||||
|
|
||||||
The golang client for the NS1 API: https://api.nsone.net/
|
The golang client for the NS1 API: https://ns1.com/api/
|
||||||
|
|
||||||
# Installing
|
# Installing
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ func (s *APIKeysService) Delete(keyID string) (*http.Response, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrKeyExists bundles PUT create error.
|
// ErrKeyExists bundles PUT create error.
|
||||||
ErrKeyExists = errors.New("Key already exists.")
|
ErrKeyExists = errors.New("key already exists")
|
||||||
// ErrKeyMissing bundles GET/POST/DELETE error.
|
// ErrKeyMissing bundles GET/POST/DELETE error.
|
||||||
ErrKeyMissing = errors.New("Key does not exist.")
|
ErrKeyMissing = errors.New("key does not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -136,7 +136,7 @@ func (s *TeamsService) Delete(id string) (*http.Response, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrTeamExists bundles PUT create error.
|
// ErrTeamExists bundles PUT create error.
|
||||||
ErrTeamExists = errors.New("Team already exists.")
|
ErrTeamExists = errors.New("team already exists")
|
||||||
// ErrTeamMissing bundles GET/POST/DELETE error.
|
// ErrTeamMissing bundles GET/POST/DELETE error.
|
||||||
ErrTeamMissing = errors.New("Team does not exist.")
|
ErrTeamMissing = errors.New("team does not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -136,7 +136,7 @@ func (s *UsersService) Delete(username string) (*http.Response, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrUserExists bundles PUT create error.
|
// ErrUserExists bundles PUT create error.
|
||||||
ErrUserExists = errors.New("User already exists.")
|
ErrUserExists = errors.New("user already exists")
|
||||||
// ErrUserMissing bundles GET/POST/DELETE error.
|
// ErrUserMissing bundles GET/POST/DELETE error.
|
||||||
ErrUserMissing = errors.New("User does not exist.")
|
ErrUserMissing = errors.New("user does not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -271,3 +271,18 @@ func parseRate(resp *http.Response) RateLimit {
|
||||||
|
|
||||||
return rl
|
return rl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetTimeParam sets a url timestamp query param given the parameters name.
|
||||||
|
func SetTimeParam(key string, t time.Time) func(*url.Values) {
|
||||||
|
return func(v *url.Values) { v.Set(key, strconv.Itoa(int(t.Unix()))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBoolParam sets a url boolean query param given the parameters name.
|
||||||
|
func SetBoolParam(key string, b bool) func(*url.Values) {
|
||||||
|
return func(v *url.Values) { v.Set(key, strconv.FormatBool(b)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStringParam sets a url string query param given the parameters name.
|
||||||
|
func SetStringParam(key, val string) func(*url.Values) {
|
||||||
|
return func(v *url.Values) { v.Set(key, val) }
|
||||||
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package rest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRateLimit(t *testing.T) {
|
|
||||||
r := RateLimit{
|
|
||||||
Limit: 10,
|
|
||||||
Remaining: 10,
|
|
||||||
Period: 10,
|
|
||||||
}
|
|
||||||
if r.WaitTime() != time.Second {
|
|
||||||
t.Error("WaitTime is wrong duration ", r.WaitTime())
|
|
||||||
}
|
|
||||||
if r.PercentageLeft() != 100 {
|
|
||||||
t.Error("PercentLeft != 100")
|
|
||||||
}
|
|
||||||
r.Remaining = 5
|
|
||||||
if r.PercentageLeft() != 50 {
|
|
||||||
t.Error("PercentLeft != 50")
|
|
||||||
}
|
|
||||||
if r.WaitTime() != time.Second {
|
|
||||||
t.Error("WaitTime is wrong duration ", r.WaitTime())
|
|
||||||
}
|
|
||||||
if r.WaitTimeRemaining() != (time.Duration(2) * time.Second) {
|
|
||||||
t.Error("WaitTimeRemaining is wrong duration ", r.WaitTimeRemaining())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,117 +0,0 @@
|
||||||
package account
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUnmarshalUsers(t *testing.T) {
|
|
||||||
d := []byte(`[
|
|
||||||
{
|
|
||||||
"permissions": {},
|
|
||||||
"teams": [],
|
|
||||||
"email": "support@nsone.net",
|
|
||||||
"last_access": 1376325771.0,
|
|
||||||
"notify": {
|
|
||||||
"billing": true
|
|
||||||
},
|
|
||||||
"name": "API Example",
|
|
||||||
"username": "apiexample"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"permissions": {
|
|
||||||
"dns": {
|
|
||||||
"view_zones": true,
|
|
||||||
"manage_zones": true,
|
|
||||||
"zones_allow_by_default": false,
|
|
||||||
"zones_deny": [],
|
|
||||||
"zones_allow": ["example.com"]
|
|
||||||
},
|
|
||||||
"data": {
|
|
||||||
"push_to_datafeeds": false,
|
|
||||||
"manage_datasources": false,
|
|
||||||
"manage_datafeeds": false
|
|
||||||
},
|
|
||||||
"account": {
|
|
||||||
"manage_payment_methods": false,
|
|
||||||
"manage_plan": false,
|
|
||||||
"manage_teams": false,
|
|
||||||
"manage_apikeys": false,
|
|
||||||
"manage_account_settings": false,
|
|
||||||
"view_activity_log": false,
|
|
||||||
"view_invoices": false,
|
|
||||||
"manage_users": false
|
|
||||||
},
|
|
||||||
"monitoring": {
|
|
||||||
"manage_lists": false,
|
|
||||||
"manage_jobs": false,
|
|
||||||
"view_jobs": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"teams": ["520422919f782d37dffb588a"],
|
|
||||||
"email": "newuser@example.com",
|
|
||||||
"last_access": null,
|
|
||||||
"notify": {
|
|
||||||
"billing": true
|
|
||||||
},
|
|
||||||
"name": "New User",
|
|
||||||
"username": "newuser"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
`)
|
|
||||||
ul := []*User{}
|
|
||||||
if err := json.Unmarshal(d, &ul); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
assert.Equal(t, len(ul), 2, "Userlist should have 2 users")
|
|
||||||
|
|
||||||
u := ul[0]
|
|
||||||
assert.Equal(t, u.TeamIDs, []string{}, "User should have empty teams")
|
|
||||||
assert.Equal(t, u.Email, "support@nsone.net", "User wrong email")
|
|
||||||
assert.Equal(t, u.LastAccess, 1376325771.0, "User wrong last access")
|
|
||||||
assert.Equal(t, u.Name, "API Example", "User wrong name")
|
|
||||||
assert.Equal(t, u.Username, "apiexample", "User wrong username")
|
|
||||||
assert.Equal(t, u.Notify, NotificationSettings{true}, "User wrong notify")
|
|
||||||
assert.Equal(t, u.Permissions, PermissionsMap{}, "User should have empty permissions")
|
|
||||||
|
|
||||||
u2 := ul[1]
|
|
||||||
assert.Equal(t, u2.TeamIDs, []string{"520422919f782d37dffb588a"}, "User should have empty teams")
|
|
||||||
assert.Equal(t, u2.Email, "newuser@example.com", "User wrong email")
|
|
||||||
assert.Equal(t, u2.LastAccess, 0.0, "User wrong last access")
|
|
||||||
assert.Equal(t, u2.Name, "New User", "User wrong name")
|
|
||||||
assert.Equal(t, u2.Username, "newuser", "User wrong username")
|
|
||||||
assert.Equal(t, u.Notify, NotificationSettings{true}, "User wrong notify")
|
|
||||||
|
|
||||||
permMap := PermissionsMap{
|
|
||||||
DNS: PermissionsDNS{
|
|
||||||
ViewZones: true,
|
|
||||||
ManageZones: true,
|
|
||||||
ZonesAllowByDefault: false,
|
|
||||||
ZonesDeny: []string{},
|
|
||||||
ZonesAllow: []string{"example.com"},
|
|
||||||
},
|
|
||||||
Data: PermissionsData{
|
|
||||||
PushToDatafeeds: false,
|
|
||||||
ManageDatasources: false,
|
|
||||||
ManageDatafeeds: false,
|
|
||||||
},
|
|
||||||
Account: PermissionsAccount{
|
|
||||||
ManagePaymentMethods: false,
|
|
||||||
ManagePlan: false,
|
|
||||||
ManageTeams: false,
|
|
||||||
ManageApikeys: false,
|
|
||||||
ManageAccountSettings: false,
|
|
||||||
ViewActivityLog: false,
|
|
||||||
ViewInvoices: false,
|
|
||||||
ManageUsers: false,
|
|
||||||
},
|
|
||||||
Monitoring: PermissionsMonitoring{
|
|
||||||
ManageLists: false,
|
|
||||||
ManageJobs: false,
|
|
||||||
ViewJobs: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
assert.Equal(t, u2.Permissions, permMap, "User wrong permissions")
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
package data_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"gopkg.in/ns1/ns1-go.v2/rest/model/data"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleSource() {
|
|
||||||
// Construct an NSONE API data source.
|
|
||||||
source := data.NewSource("my api source", "nsone_v1")
|
|
||||||
fmt.Println(source.ID) // will be empty string
|
|
||||||
fmt.Println(source.Name)
|
|
||||||
fmt.Println(source.Type)
|
|
||||||
// Output:
|
|
||||||
// my api source
|
|
||||||
// nsone_v1
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleFeed() {
|
|
||||||
|
|
||||||
// Construct the london data feed.
|
|
||||||
feed := data.NewFeed(
|
|
||||||
"London Feed",
|
|
||||||
data.Config{"label": "London-UK"})
|
|
||||||
fmt.Println(feed.ID) // will be empty string
|
|
||||||
fmt.Println(feed.Name)
|
|
||||||
fmt.Println(feed.Config)
|
|
||||||
// Output:
|
|
||||||
// London Feed
|
|
||||||
// map[label:London-UK]
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleMeta() {
|
|
||||||
feedID := "feed_id"
|
|
||||||
|
|
||||||
meta := data.Meta{}
|
|
||||||
meta.Priority = 1
|
|
||||||
meta.Up = data.FeedPtr{FeedID: feedID}
|
|
||||||
fmt.Println(meta.Connections) // will be nil
|
|
||||||
fmt.Println(meta.Priority)
|
|
||||||
fmt.Println(meta.Up)
|
|
||||||
// Output:
|
|
||||||
// <nil>
|
|
||||||
// 1
|
|
||||||
// {feed_id}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRegions() {
|
|
||||||
feedPtr := data.FeedPtr{FeedID: "feed_id"}
|
|
||||||
|
|
||||||
regions := data.Regions{}
|
|
||||||
// Set a regions' 'up' metavalue to false('down').
|
|
||||||
regions["some_region"] = data.Region{
|
|
||||||
Meta: data.Meta{Up: false},
|
|
||||||
}
|
|
||||||
// Set a regions' 'connections' metavalue to receive from a feed.
|
|
||||||
regions["other_region"] = data.Region{
|
|
||||||
Meta: data.Meta{Connections: feedPtr},
|
|
||||||
}
|
|
||||||
fmt.Println(regions["some_region"].Meta.Up)
|
|
||||||
fmt.Println(regions["some_region"].Meta.Priority)
|
|
||||||
fmt.Println(regions["other_region"].Meta.Connections)
|
|
||||||
fmt.Println(regions["other_region"].Meta.Priority)
|
|
||||||
// Output:
|
|
||||||
// false
|
|
||||||
// <nil>
|
|
||||||
// {feed_id}
|
|
||||||
// <nil>
|
|
||||||
}
|
|
|
@ -38,7 +38,7 @@ type Meta struct {
|
||||||
// Indicates the "load average".
|
// Indicates the "load average".
|
||||||
// Values must be positive, and will be rounded to the nearest tenth.
|
// Values must be positive, and will be rounded to the nearest tenth.
|
||||||
// float64 or FeedPtr.
|
// float64 or FeedPtr.
|
||||||
LoadAvg interface{} `json:",loadavg,omitempty"`
|
LoadAvg interface{} `json:"loadavg,omitempty"`
|
||||||
|
|
||||||
// The Job ID of a Pulsar telemetry gathering job and routing granularities
|
// The Job ID of a Pulsar telemetry gathering job and routing granularities
|
||||||
// to associate with.
|
// to associate with.
|
||||||
|
|
|
@ -1,141 +0,0 @@
|
||||||
package dns_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"gopkg.in/ns1/ns1-go.v2/rest/model/data"
|
|
||||||
"gopkg.in/ns1/ns1-go.v2/rest/model/dns"
|
|
||||||
"gopkg.in/ns1/ns1-go.v2/rest/model/filter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleZone() {
|
|
||||||
z := dns.NewZone("example.com")
|
|
||||||
|
|
||||||
fmt.Println(z)
|
|
||||||
// Output:
|
|
||||||
// example.com
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example references https://ns1.com/articles/primary-dns-with-ns1
|
|
||||||
func ExamplePrimaryZone() {
|
|
||||||
// Secondary/slave dns server info.
|
|
||||||
secondary := dns.ZoneSecondaryServer{
|
|
||||||
IP: "1.2.3.4",
|
|
||||||
Port: 53,
|
|
||||||
Notify: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct the primary/master zone.
|
|
||||||
domain := "masterzone.example"
|
|
||||||
|
|
||||||
masterZone := dns.NewZone(domain)
|
|
||||||
masterZone.MakePrimary(secondary)
|
|
||||||
|
|
||||||
b, _ := json.MarshalIndent(masterZone, "", " ")
|
|
||||||
|
|
||||||
fmt.Println(string(b))
|
|
||||||
// Output:
|
|
||||||
// {
|
|
||||||
// "zone": "masterzone.example",
|
|
||||||
// "primary": {
|
|
||||||
// "enabled": true,
|
|
||||||
// "secondaries": [
|
|
||||||
// {
|
|
||||||
// "ip": "1.2.3.4",
|
|
||||||
// "port": 53,
|
|
||||||
// "notify": true
|
|
||||||
// }
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRecord() {
|
|
||||||
// Construct the A record
|
|
||||||
record := dns.NewRecord("test.com", "a", "A")
|
|
||||||
record.TTL = 300
|
|
||||||
|
|
||||||
// Construct primary answer(higher priority)
|
|
||||||
pAns := dns.NewAv4Answer("1.1.1.1")
|
|
||||||
pAns.Meta.Priority = 1
|
|
||||||
pAns.Meta.Up = data.FeedPtr{FeedID: "feed1_id"}
|
|
||||||
|
|
||||||
// Construct secondary answer(lower priority)
|
|
||||||
sAns := dns.NewAv4Answer("2.2.2.2")
|
|
||||||
sAns.Meta.Priority = 2
|
|
||||||
sAns.Meta.Up = data.FeedPtr{FeedID: "feed2_id"}
|
|
||||||
|
|
||||||
// Add both answers to record
|
|
||||||
record.AddAnswer(pAns)
|
|
||||||
record.AddAnswer(sAns)
|
|
||||||
|
|
||||||
// Construct and add both filters to the record(ORDER MATTERS)
|
|
||||||
record.AddFilter(filter.NewUp())
|
|
||||||
record.AddFilter(filter.NewSelFirstN(1))
|
|
||||||
|
|
||||||
// Add region 'test' to record(set as down)
|
|
||||||
record.Regions["test"] = data.Region{Meta: data.Meta{Up: false}}
|
|
||||||
|
|
||||||
fmt.Println(record)
|
|
||||||
fmt.Println(record.TTL)
|
|
||||||
|
|
||||||
fmt.Println("Primary answer:")
|
|
||||||
fmt.Println(record.Answers[0])
|
|
||||||
fmt.Println(record.Answers[0].Meta.Priority)
|
|
||||||
fmt.Println(record.Answers[0].Meta.Up)
|
|
||||||
|
|
||||||
fmt.Println("Secondary answer:")
|
|
||||||
fmt.Println(record.Answers[1])
|
|
||||||
fmt.Println(record.Answers[1].Meta.Priority)
|
|
||||||
fmt.Println(record.Answers[1].Meta.Up)
|
|
||||||
|
|
||||||
fmt.Println("First Filter in Chain:")
|
|
||||||
fmt.Println(record.Filters[0].Type)
|
|
||||||
fmt.Println(record.Filters[0].Config)
|
|
||||||
|
|
||||||
fmt.Println("Second Filter in Chain:")
|
|
||||||
fmt.Println(record.Filters[1].Type)
|
|
||||||
fmt.Println(record.Filters[1].Config)
|
|
||||||
|
|
||||||
fmt.Println("Regions:")
|
|
||||||
fmt.Println(record.Regions["test"].Meta.Up)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// a.test.com A
|
|
||||||
// 300
|
|
||||||
// Primary answer:
|
|
||||||
// 1.1.1.1
|
|
||||||
// 1
|
|
||||||
// {feed1_id}
|
|
||||||
// Secondary answer:
|
|
||||||
// 2.2.2.2
|
|
||||||
// 2
|
|
||||||
// {feed2_id}
|
|
||||||
// First Filter in Chain:
|
|
||||||
// up
|
|
||||||
// map[]
|
|
||||||
// Second Filter in Chain:
|
|
||||||
// select_first_n
|
|
||||||
// map[N:1]
|
|
||||||
// Regions:
|
|
||||||
// false
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleRecordLink() {
|
|
||||||
// Construct the src record
|
|
||||||
srcRecord := dns.NewRecord("test.com", "a", "A")
|
|
||||||
srcRecord.TTL = 300
|
|
||||||
srcRecord.Meta.Priority = 2
|
|
||||||
|
|
||||||
linkedRecord := dns.NewRecord("test.com", "l", "A")
|
|
||||||
linkedRecord.LinkTo(srcRecord.Domain)
|
|
||||||
fmt.Println(linkedRecord)
|
|
||||||
fmt.Println(linkedRecord.Meta)
|
|
||||||
fmt.Println(linkedRecord.Answers)
|
|
||||||
// Output:
|
|
||||||
// l.test.com A
|
|
||||||
// <nil>
|
|
||||||
// []
|
|
||||||
}
|
|
|
@ -19,10 +19,10 @@ type Job struct {
|
||||||
Config Config `json:"config"`
|
Config Config `json:"config"`
|
||||||
|
|
||||||
// The current status of the monitor.
|
// The current status of the monitor.
|
||||||
Status map[string]Status `json:"status,omitempty"`
|
Status map[string]*Status `json:"status,omitempty"`
|
||||||
|
|
||||||
// Rules for determining failure conditions.
|
// Rules for determining failure conditions.
|
||||||
Rules []*Rule `json:"rules"`
|
Rules []*Rule `json:"rules,omitempty"`
|
||||||
|
|
||||||
// List of regions in which to run the monitor.
|
// List of regions in which to run the monitor.
|
||||||
// eg, ["dal", "sin", "sjc", "lga", "ams"]
|
// eg, ["dal", "sin", "sjc", "lga", "ams"]
|
||||||
|
@ -66,7 +66,7 @@ type Job struct {
|
||||||
|
|
||||||
// If true, notifications are sent for any regional failure (and failback if desired),
|
// If true, notifications are sent for any regional failure (and failback if desired),
|
||||||
// in addition to global state notifications.
|
// in addition to global state notifications.
|
||||||
NotifyRegional bool `json:"notidy_regional"`
|
NotifyRegional bool `json:"notify_regional"`
|
||||||
|
|
||||||
// If true, a notification is sent when a job returns to an "up" state.
|
// If true, a notification is sent when a job returns to an "up" state.
|
||||||
NotifyFailback bool `json:"notify_failback"`
|
NotifyFailback bool `json:"notify_failback"`
|
||||||
|
@ -99,6 +99,15 @@ type Status struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StatusLog wraps an NS1 /monitoring/history resource
|
||||||
|
type StatusLog struct {
|
||||||
|
Job string `json:"job"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Since int `json:"since"`
|
||||||
|
Until int `json:"until"`
|
||||||
|
}
|
||||||
|
|
||||||
// Rule wraps an element of a Job's "rules" attribute
|
// Rule wraps an element of a Job's "rules" attribute
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
package monitor
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestUnmarshalJobs(t *testing.T) {
|
|
||||||
data := []byte(`[
|
|
||||||
{
|
|
||||||
"id": "52a27d4397d5f07003fdbe7b",
|
|
||||||
"config": {
|
|
||||||
"host": "1.2.3.4"
|
|
||||||
},
|
|
||||||
"status": {
|
|
||||||
"lga": {
|
|
||||||
"since": 1389407609,
|
|
||||||
"status": "up"
|
|
||||||
},
|
|
||||||
"global": {
|
|
||||||
"since": 1389407609,
|
|
||||||
"status": "up"
|
|
||||||
},
|
|
||||||
"sjc": {
|
|
||||||
"since": 1389404014,
|
|
||||||
"status": "up"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rules": [
|
|
||||||
{
|
|
||||||
"key": "rtt",
|
|
||||||
"value": 100,
|
|
||||||
"comparison": "<"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"job_type": "ping",
|
|
||||||
"regions": [
|
|
||||||
"lga",
|
|
||||||
"sjc"
|
|
||||||
],
|
|
||||||
"active": true,
|
|
||||||
"frequency": 60,
|
|
||||||
"policy": "quorum",
|
|
||||||
"region_scope": "fixed"
|
|
||||||
}
|
|
||||||
]`)
|
|
||||||
mjl := []*Job{}
|
|
||||||
if err := json.Unmarshal(data, &mjl); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
if len(mjl) != 1 {
|
|
||||||
fmt.Println(mjl)
|
|
||||||
t.Error("Do not have any jobs")
|
|
||||||
}
|
|
||||||
j := mjl[0]
|
|
||||||
if j.ID != "52a27d4397d5f07003fdbe7b" {
|
|
||||||
t.Error("Wrong ID")
|
|
||||||
}
|
|
||||||
conf := j.Config
|
|
||||||
if conf["host"] != "1.2.3.4" {
|
|
||||||
t.Error("Wrong host")
|
|
||||||
}
|
|
||||||
status := j.Status["global"]
|
|
||||||
if status.Since != 1389407609 {
|
|
||||||
t.Error("since has unexpected value")
|
|
||||||
}
|
|
||||||
if status.Status != "up" {
|
|
||||||
t.Error("Status is not up")
|
|
||||||
}
|
|
||||||
r := j.Rules[0]
|
|
||||||
assert.Equal(t, r.Key, "rtt", "RTT rule key is wrong")
|
|
||||||
assert.Equal(t, r.Value.(float64), float64(100), "RTT rule value is wrong")
|
|
||||||
if r.Comparison != "<" {
|
|
||||||
t.Error("RTT rule comparison is wrong")
|
|
||||||
}
|
|
||||||
if j.Type != "ping" {
|
|
||||||
t.Error("Jobtype is wrong")
|
|
||||||
}
|
|
||||||
if j.Regions[0] != "lga" {
|
|
||||||
t.Error("First region is not lga")
|
|
||||||
}
|
|
||||||
if !j.Active {
|
|
||||||
t.Error("Job is not active")
|
|
||||||
}
|
|
||||||
if j.Frequency != 60 {
|
|
||||||
t.Error("Job frequency != 60")
|
|
||||||
}
|
|
||||||
if j.Policy != "quorum" {
|
|
||||||
t.Error("Job policy is not quorum")
|
|
||||||
}
|
|
||||||
if j.RegionScope != "fixed" {
|
|
||||||
t.Error("Job region scope is not fixed")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,6 +3,7 @@ package rest
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"gopkg.in/ns1/ns1-go.v2/rest/model/monitor"
|
"gopkg.in/ns1/ns1-go.v2/rest/model/monitor"
|
||||||
)
|
)
|
||||||
|
@ -106,3 +107,28 @@ func (s *JobsService) Delete(id string) (*http.Response, error) {
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// History takes an ID and returns status log history for a specific monitoring job.
|
||||||
|
//
|
||||||
|
// NS1 API docs: https://ns1.com/api/#history-get
|
||||||
|
func (s *JobsService) History(id string, opts ...func(*url.Values)) ([]*monitor.StatusLog, *http.Response, error) {
|
||||||
|
v := url.Values{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&v)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := fmt.Sprintf("%s/%s?%s", "monitoring/history", id, v.Encode())
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest("GET", path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var slgs []*monitor.StatusLog
|
||||||
|
resp, err := s.client.Do(req, &slgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return slgs, resp, nil
|
||||||
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ func (s *NotificationsService) Delete(listID string) (*http.Response, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrListExists bundles PUT create error.
|
// ErrListExists bundles PUT create error.
|
||||||
ErrListExists = errors.New("Notify List already exists.")
|
ErrListExists = errors.New("notify List already exists")
|
||||||
// ErrListMissing bundles GET/POST/DELETE error.
|
// ErrListMissing bundles GET/POST/DELETE error.
|
||||||
ErrListMissing = errors.New("Notify List does not exist.")
|
ErrListMissing = errors.New("notify List does not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -128,7 +128,7 @@ func (s *RecordsService) Delete(zone string, domain string, t string) (*http.Res
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrRecordExists bundles PUT create error.
|
// ErrRecordExists bundles PUT create error.
|
||||||
ErrRecordExists = errors.New("Record already exists.")
|
ErrRecordExists = errors.New("record already exists")
|
||||||
// ErrRecordMissing bundles GET/POST/DELETE error.
|
// ErrRecordMissing bundles GET/POST/DELETE error.
|
||||||
ErrRecordMissing = errors.New("Record does not exist.")
|
ErrRecordMissing = errors.New("record does not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -138,7 +138,7 @@ func (s *ZonesService) Delete(zone string) (*http.Response, error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrZoneExists bundles PUT create error.
|
// ErrZoneExists bundles PUT create error.
|
||||||
ErrZoneExists = errors.New("Zone already exists.")
|
ErrZoneExists = errors.New("zone already exists")
|
||||||
// ErrZoneMissing bundles GET/POST/DELETE error.
|
// ErrZoneMissing bundles GET/POST/DELETE error.
|
||||||
ErrZoneMissing = errors.New("Zone does not exist.")
|
ErrZoneMissing = errors.New("zone does not exist")
|
||||||
)
|
)
|
||||||
|
|
|
@ -3270,10 +3270,52 @@
|
||||||
"revisionTime": "2017-01-17T13:00:17Z"
|
"revisionTime": "2017-01-17T13:00:17Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "U0s6Vq/AxUhEEsnORw2DnZ4cw1c=",
|
"checksumSHA1": "IOhjrvLMN5Mw8PeiRF/xAfSxvew=",
|
||||||
"path": "gopkg.in/ns1/ns1-go.v2",
|
"path": "gopkg.in/ns1/ns1-go.v2",
|
||||||
"revision": "d8d10b7f448291ddbdce48d4594fb1b667014c8b",
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
"revisionTime": "2016-11-05T01:14:08Z"
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "t20/HSVruhTb/TVwgc9mpw/oMTA=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "euh1cYwe0t2erigdvOMueyniPH0=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest/model",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "tdMxXKsUHn3yZpur14ZNLMVyQJM=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest/model/account",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "gBVND8veklEQV0gxF3lERV6mSZk=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest/model/data",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "GbL7ThrBZfKs1lhzguxzscIynac=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest/model/dns",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "CuurmNep8iMdYFodxRxAeewowsQ=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest/model/filter",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "B0C8F5th11AHl1fo8k0I8+DvrjE=",
|
||||||
|
"path": "gopkg.in/ns1/ns1-go.v2/rest/model/monitor",
|
||||||
|
"revision": "49e3a8a0b594e847e01cdac77810ba49f9564ccf",
|
||||||
|
"revisionTime": "2017-03-02T13:56:36Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "mkLQOQwQwoUc9Kr9+PaVGrKUzI4=",
|
"checksumSHA1": "mkLQOQwQwoUc9Kr9+PaVGrKUzI4=",
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
---
|
||||||
|
layout: "ns1"
|
||||||
|
page_title: "NS1: ns1_notifylist"
|
||||||
|
sidebar_current: "docs-ns1-resource-notifylist"
|
||||||
|
description: |-
|
||||||
|
Provides a NS1 Notify List resource.
|
||||||
|
---
|
||||||
|
|
||||||
|
# ns1\_notifylist
|
||||||
|
|
||||||
|
Provides a NS1 Notify List resource. This can be used to create, modify, and delete notify lists.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "ns1_notifylist" "nl" {
|
||||||
|
name = "my notify list"
|
||||||
|
notifications = {
|
||||||
|
type = "webhook"
|
||||||
|
config = {
|
||||||
|
url = "http://www.mywebhook.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifications = {
|
||||||
|
type = "email"
|
||||||
|
config = {
|
||||||
|
email = "test@test.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `name` - (Required) The free-form display name for the notify list.
|
||||||
|
* `notifications` - (Optional) A list of notifiers. All notifiers in a notification list will receive notifications whenever an event is send to the list (e.g., when a monitoring job fails). Notifiers are documented below.
|
||||||
|
|
||||||
|
Notify List Notifiers (`notifications`) support the following:
|
||||||
|
|
||||||
|
* `type` - (Required) The type of notifier. Available notifiers are indicated in /notifytypes endpoint.
|
||||||
|
* `config` - (Required) Configuration details for the given notifier type.
|
||||||
|
|
|
@ -24,11 +24,11 @@ resource "ns1_record" "www" {
|
||||||
ttl = 60
|
ttl = 60
|
||||||
|
|
||||||
answers = {
|
answers = {
|
||||||
answer = ["sub1.${ns1_zone.tld.zone}"]
|
answer = "sub1.${ns1_zone.tld.zone}"
|
||||||
}
|
}
|
||||||
|
|
||||||
answer = {
|
answers = {
|
||||||
answer = ["sub2.${ns1_zone.tld.zone}"]
|
answer = "sub2.${ns1_zone.tld.zone}"
|
||||||
}
|
}
|
||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
<li<%= sidebar_current("docs-ns1-resource-monitoringjob") %>>
|
<li<%= sidebar_current("docs-ns1-resource-monitoringjob") %>>
|
||||||
<a href="/docs/providers/ns1/r/monitoringjob.html">ns1_monitoringjob</a>
|
<a href="/docs/providers/ns1/r/monitoringjob.html">ns1_monitoringjob</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-ns1-resource-notifylist") %>>
|
||||||
|
<a href="/docs/providers/ns1/r/notifylist.html">ns1_notifylist</a>
|
||||||
|
</li>
|
||||||
<li<%= sidebar_current("docs-ns1-resource-datasource") %>>
|
<li<%= sidebar_current("docs-ns1-resource-datasource") %>>
|
||||||
<a href="/docs/providers/ns1/r/datasource.html">ns1_datasource</a>
|
<a href="/docs/providers/ns1/r/datasource.html">ns1_datasource</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue