Initial check in for Icinga2 Provider/Resource (#8306)

* Initial checkin for PR request

* Added an argument to provider to allow control over whether or not TLS Certs will skip verification. Controllable via provider or env variable being set

* Initial check-in to use refactored module

* Checkin of very MVP for creating/deleting host test which works and validates basic host creation and deletion

* Check in with support for creating hosts with variables working

* Checking in work to date

* Remove code that causes travis CI to fail while I debug

* Adjust create to accept multivale

* Back on track. Working basic tests. go-icinga2-api needs more test too

* Squashing

* Back on track. Working basic tests. go-icinga2-api needs more test too

* Check in refactored hostgroup support

* Check in refactored check_command, hosts, and hsotgroup with a few test

* Checking in service code

* Add in dependency for icinga2 provider

* Add documentation. Refactor, fix and extend based on feedback from Hashicorp

* Added checking and validation around invalid URL and unavailable server
This commit is contained in:
Len Smith 2016-12-12 10:28:26 -05:00 committed by Paul Stack
parent 399614c093
commit 015e96d0dd
25 changed files with 2114 additions and 1 deletions

View File

@ -0,0 +1,108 @@
package icinga2
import (
"fmt"
"net/url"
"os"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"api_url": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ICINGA2_API_URL", nil),
Description: descriptions["api_url"],
},
"api_user": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ICINGA2_API_USER", nil),
Description: descriptions["api_user"],
},
"api_password": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("ICINGA2_API_PASSWORD", nil),
Description: descriptions["api_password"],
},
"insecure_skip_tls_verify": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
DefaultFunc: EnvBoolDefaultFunc("ICINGA2_INSECURE_SKIP_TLS_VERIFY", false),
Description: descriptions["insecure_skip_tls_verify"],
},
},
ResourcesMap: map[string]*schema.Resource{
"icinga2_host": resourceIcinga2Host(),
"icinga2_hostgroup": resourceIcinga2Hostgroup(),
"icinga2_checkcommand": resourceIcinga2Checkcommand(),
"icinga2_service": resourceIcinga2Service(),
},
ConfigureFunc: configureProvider,
}
}
func configureProvider(d *schema.ResourceData) (interface{}, error) {
config, _ := iapi.New(
d.Get("api_user").(string),
d.Get("api_password").(string),
d.Get("api_url").(string),
d.Get("insecure_skip_tls_verify").(bool),
)
err := validateURL(d.Get("api_url").(string))
if err := config.Connect(); err != nil {
return nil, err
}
return config, err
}
var descriptions map[string]string
func init() {
descriptions = map[string]string{
"api_url": "The address of the Icinga2 server.\n",
"api_user": "The user to authenticate to the Icinga2 Server as.\n",
"api_password": "The password for authenticating to the Icinga2 server.\n",
"insecure_skip_tls_verify": "Disable TLS verify when connecting to Icinga2 Server\n",
}
}
func validateURL(urlString string) error {
//ICINGA2_API_URL=https://127.0.0.1:4665/v1
tokens, err := url.Parse(urlString)
if err != nil {
return err
}
if tokens.Scheme != "https" {
return fmt.Errorf("Error : Requests are only allowed to use the HTTPS protocol so that traffic remains encrypted.")
}
if tokens.Path != "/v1" {
return fmt.Errorf("Error : Invalid API version %s specified. Only v1 is currently supported.", tokens.Path)
}
return nil
}
// EnvBoolDefaultFunc is a helper function that returns
func EnvBoolDefaultFunc(k string, dv interface{}) schema.SchemaDefaultFunc {
return func() (interface{}, error) {
if v := os.Getenv(k); v == "true" {
return true, nil
}
return false, nil
}
}

View File

@ -0,0 +1,48 @@
package icinga2
import (
"os"
"testing"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider
func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"icinga2": testAccProvider,
}
}
func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestProviderImpl(t *testing.T) {
var _ terraform.ResourceProvider = Provider()
}
func testAccPreCheck(t *testing.T) {
v := os.Getenv("ICINGA2_API_URL")
if v == "" {
t.Fatal("ICINGA2_API_URL must be set for acceptance tests")
}
v = os.Getenv("ICINGA2_API_USER")
if v == "" {
t.Fatal("ICINGA2_API_USER must be set for acceptance tests")
}
v = os.Getenv("ICINGA2_API_PASSWORD")
if v == "" {
t.Fatal("ICINGA2_API_PASSWORD must be set for acceptance tests")
}
}

View File

@ -0,0 +1,118 @@
package icinga2
import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func resourceIcinga2Checkcommand() *schema.Resource {
return &schema.Resource{
Create: resourceIcinga2CheckcommandCreate,
Read: resourceIcinga2CheckcommandRead,
Delete: resourceIcinga2CheckcommandDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name",
ForceNew: true,
},
"command": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"templates": &schema.Schema{
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"arguments": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},
},
}
}
func resourceIcinga2CheckcommandCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
name := d.Get("name").(string)
command := d.Get("command").(string)
arguments := make(map[string]string)
iterator := d.Get("arguments").(map[string]interface{})
for key, value := range iterator {
arguments[key] = value.(string)
}
checkcommands, err := client.CreateCheckcommand(name, command, arguments)
if err != nil {
return err
}
found := false
for _, checkcommand := range checkcommands {
if checkcommand.Name == name {
d.SetId(name)
found = true
}
}
if !found {
return fmt.Errorf("Failed to create Checkcommand %s : %s", name, err)
}
return nil
}
func resourceIcinga2CheckcommandRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
name := d.Get("name").(string)
checkcommands, err := client.GetCheckcommand(name)
if err != nil {
return err
}
found := false
for _, checkcommand := range checkcommands {
if checkcommand.Name == name {
d.SetId(name)
d.Set("command", checkcommand.Attrs.Command[0])
d.Set("Templates", checkcommand.Attrs.Templates)
d.Set("arguments", checkcommand.Attrs.Arguments)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Read Checkcommand %s : %s", name, err)
}
return nil
}
func resourceIcinga2CheckcommandDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
name := d.Get("name").(string)
err := client.DeleteCheckcommand(name)
if err != nil {
return fmt.Errorf("Failed to Delete Checkcommand %s : %s", name, err)
}
return nil
}

View File

@ -0,0 +1,62 @@
package icinga2
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func TestAccCreateCheckcommand(t *testing.T) {
var testAccCreateCheckcommand = fmt.Sprintf(`
resource "icinga2_checkcommand" "checkcommand" {
name = "terraform-test-checkcommand-1"
templates = [ "plugin-check-command" ]
command = "/usr/local/bin/check_command"
arguments = {
"-I" = "$IARG$"
"-J" = "$JARG$" }
}`)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCreateCheckcommand,
Check: resource.ComposeTestCheckFunc(
testAccCheckCheckcommandExists("icinga2_checkcommand.checkcommand"),
testAccCheckResourceState("icinga2_checkcommand.checkcommand", "name", "terraform-test-checkcommand-1"),
testAccCheckResourceState("icinga2_checkcommand.checkcommand", "command", "/usr/local/bin/check_command"),
testAccCheckResourceState("icinga2_checkcommand.checkcommand", "arguments.%", "2"),
testAccCheckResourceState("icinga2_checkcommand.checkcommand", "arguments.-I", "$IARG$"),
testAccCheckResourceState("icinga2_checkcommand.checkcommand", "arguments.-J", "$JARG$"),
),
},
},
})
}
func testAccCheckCheckcommandExists(rn string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources[rn]
if !ok {
return fmt.Errorf("Checkcommand resource not found: %s", rn)
}
if resource.Primary.ID == "" {
return fmt.Errorf("Checkcommand resource id not set")
}
client := testAccProvider.Meta().(*iapi.Server)
_, err := client.GetCheckcommand(resource.Primary.ID)
if err != nil {
return fmt.Errorf("Error getting getting Checkcommand: %s", err)
}
return nil
}
}

View File

@ -0,0 +1,121 @@
package icinga2
import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func resourceIcinga2Host() *schema.Resource {
return &schema.Resource{
Create: resourceIcinga2HostCreate,
Read: resourceIcinga2HostRead,
Delete: resourceIcinga2HostDelete,
Schema: map[string]*schema.Schema{
"hostname": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Hostname",
ForceNew: true,
},
"address": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"check_command": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"vars": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},
},
}
}
func resourceIcinga2HostCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
hostname := d.Get("hostname").(string)
address := d.Get("address").(string)
checkCommand := d.Get("check_command").(string)
vars := make(map[string]string)
// Normalize from map[string]interface{} to map[string]string
iterator := d.Get("vars").(map[string]interface{})
for key, value := range iterator {
vars[key] = value.(string)
}
// Call CreateHost with normalized data
hosts, err := client.CreateHost(hostname, address, checkCommand, vars)
if err != nil {
return err
}
found := false
for _, host := range hosts {
if host.Name == hostname {
d.SetId(hostname)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Create Host %s : %s", hostname, err)
}
return nil
}
func resourceIcinga2HostRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
hostname := d.Get("hostname").(string)
hosts, err := client.GetHost(hostname)
if err != nil {
return err
}
found := false
for _, host := range hosts {
if host.Name == hostname {
d.SetId(hostname)
d.Set("hostname", host.Name)
d.Set("address", host.Attrs.Address)
d.Set("check_command", host.Attrs.CheckCommand)
d.Set("vars", host.Attrs.Vars)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Read Host %s : %s", hostname, err)
}
return nil
}
func resourceIcinga2HostDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
hostname := d.Get("hostname").(string)
err := client.DeleteHost(hostname)
if err != nil {
return fmt.Errorf("Failed to Delete Host %s : %s", hostname, err)
}
return nil
}

View File

@ -0,0 +1,92 @@
package icinga2
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func TestAccCreateBasicHost(t *testing.T) {
var testAccCreateBasicHost = fmt.Sprintf(`
resource "icinga2_host" "tf-1" {
hostname = "terraform-host-1"
address = "10.10.10.1"
check_command = "hostalive"
}`)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCreateBasicHost,
Check: resource.ComposeTestCheckFunc(
testAccCheckHostExists("icinga2_host.tf-1"),
testAccCheckResourceState("icinga2_host.tf-1", "hostname", "terraform-host-1"),
testAccCheckResourceState("icinga2_host.tf-1", "address", "10.10.10.1"),
testAccCheckResourceState("icinga2_host.tf-1", "check_command", "hostalive"),
),
},
},
})
}
func TestAccCreateVariableHost(t *testing.T) {
var testAccCreateVariableHost = fmt.Sprintf(`
resource "icinga2_host" "tf-3" {
hostname = "terraform-host-3"
address = "10.10.10.3"
check_command = "hostalive"
vars {
os = "linux"
osver = "1"
allowance = "none" }
}`)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCreateVariableHost,
Check: resource.ComposeTestCheckFunc(
testAccCheckHostExists("icinga2_host.tf-3"),
testAccCheckResourceState("icinga2_host.tf-3", "hostname", "terraform-host-3"),
testAccCheckResourceState("icinga2_host.tf-3", "address", "10.10.10.3"),
testAccCheckResourceState("icinga2_host.tf-3", "check_command", "hostalive"),
testAccCheckResourceState("icinga2_host.tf-3", "vars.%", "3"),
testAccCheckResourceState("icinga2_host.tf-3", "vars.allowance", "none"),
testAccCheckResourceState("icinga2_host.tf-3", "vars.os", "linux"),
testAccCheckResourceState("icinga2_host.tf-3", "vars.osver", "1"),
),
},
},
})
}
func testAccCheckHostExists(rn string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources[rn]
if !ok {
return fmt.Errorf("Host resource not found: %s", rn)
}
if resource.Primary.ID == "" {
return fmt.Errorf("resource id not set")
}
client := testAccProvider.Meta().(*iapi.Server)
_, err := client.GetHost(resource.Primary.ID)
if err != nil {
return fmt.Errorf("error getting getting host: %s", err)
}
return nil
}
}

View File

@ -0,0 +1,98 @@
package icinga2
import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func resourceIcinga2Hostgroup() *schema.Resource {
return &schema.Resource{
Create: resourceIcinga2HostgroupCreate,
Read: resourceIcinga2HostgroupRead,
Delete: resourceIcinga2HostgroupDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "name",
ForceNew: true,
},
"display_name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Display name of Host Group",
ForceNew: true,
},
},
}
}
func resourceIcinga2HostgroupCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
name := d.Get("name").(string)
displayName := d.Get("display_name").(string)
hostgroups, err := client.CreateHostgroup(name, displayName)
if err != nil {
return err
}
found := false
for _, hostgroup := range hostgroups {
if hostgroup.Name == name {
d.SetId(name)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Create Hostgroup %s : %s", name, err)
}
return nil
}
func resourceIcinga2HostgroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
name := d.Get("name").(string)
hostgroups, err := client.GetHostgroup(name)
if err != nil {
return err
}
found := false
for _, hostgroup := range hostgroups {
if hostgroup.Name == name {
d.SetId(name)
d.Set("display_name", hostgroup.Attrs.DisplayName)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Read Hostgroup %s : %s", name, err)
}
return nil
}
func resourceIcinga2HostgroupDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
name := d.Get("name").(string)
err := client.DeleteHostgroup(name)
if err != nil {
return fmt.Errorf("Failed to Delete Hostgroup %s : %s", name, err)
}
return nil
}

View File

@ -0,0 +1,55 @@
package icinga2
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func TestAccCreateBasicHostGroup(t *testing.T) {
var testAccCreateBasicHostGroup = fmt.Sprintf(`
resource "icinga2_hostgroup" "tf-hg-1" {
name = "terraform-hostgroup-1"
display_name = "Terraform Test HostGroup"
}`)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCreateBasicHostGroup,
Check: resource.ComposeTestCheckFunc(
testAccCheckHostgroupExists("icinga2_hostgroup.tf-hg-1"),
testAccCheckResourceState("icinga2_hostgroup.tf-hg-1", "name", "terraform-hostgroup-1"),
testAccCheckResourceState("icinga2_hostgroup.tf-hg-1", "display_name", "Terraform Test HostGroup"),
),
},
},
})
}
func testAccCheckHostgroupExists(rn string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources[rn]
if !ok {
return fmt.Errorf("Hostgroup resource not found: %s", rn)
}
if resource.Primary.ID == "" {
return fmt.Errorf("Hostgroup resource id not set")
}
client := testAccProvider.Meta().(*iapi.Server)
_, err := client.GetHostgroup(resource.Primary.ID)
if err != nil {
return fmt.Errorf("Error getting getting hostgroup: %s", err)
}
return nil
}
}

View File

@ -0,0 +1,111 @@
package icinga2
import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func resourceIcinga2Service() *schema.Resource {
return &schema.Resource{
Create: resourceIcinga2ServiceCreate,
Read: resourceIcinga2ServiceRead,
Delete: resourceIcinga2ServiceDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "ServiceName",
ForceNew: true,
},
"hostname": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Hostname",
ForceNew: true,
},
"check_command": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "CheckCommand",
ForceNew: true,
},
},
}
}
func resourceIcinga2ServiceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
hostname := d.Get("hostname").(string)
name := d.Get("name").(string)
checkcommand := d.Get("check_command").(string)
services, err := client.CreateService(name, hostname, checkcommand)
if err != nil {
return err
}
found := false
for _, service := range services {
if service.Name == hostname+"!"+name {
d.SetId(hostname + "!" + name)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Create Service %s!%s : %s", hostname, name, err)
}
return nil
}
func resourceIcinga2ServiceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
hostname := d.Get("hostname").(string)
name := d.Get("name").(string)
services, err := client.GetService(name, hostname)
if err != nil {
return err
}
found := false
for _, service := range services {
if service.Name == hostname+"!"+name {
d.SetId(hostname + "!" + name)
d.Set("hostname", hostname)
d.Set("check_command", service.Attrs.CheckCommand)
found = true
}
}
if !found {
return fmt.Errorf("Failed to Read Service %s!%s : %s", hostname, name, err)
}
return nil
}
func resourceIcinga2ServiceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*iapi.Server)
hostname := d.Get("hostname").(string)
name := d.Get("name").(string)
err := client.DeleteService(name, hostname)
if err != nil {
return fmt.Errorf("Failed to Delete Service %s!%s : %s", hostname, name, err)
}
return nil
}

View File

@ -0,0 +1,61 @@
package icinga2
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/lrsmith/go-icinga2-api/iapi"
)
func TestAccCreateService(t *testing.T) {
var testAccCreateService = fmt.Sprintf(`
resource "icinga2_service" "tf-service-1" {
hostname = "docker-icinga2"
name = "ssh3"
check_command = "ssh"
}`)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCreateService,
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists("icinga2_service.tf-service-1"),
testAccCheckResourceState("icinga2_service.tf-service-1", "hostname", "docker-icinga2"),
testAccCheckResourceState("icinga2_service.tf-service-1", "name", "ssh3"),
testAccCheckResourceState("icinga2_service.tf-service-1", "check_command", "ssh"),
),
},
},
})
}
func testAccCheckServiceExists(rn string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources[rn]
if !ok {
return fmt.Errorf("Service resource not found: %s", rn)
}
if resource.Primary.ID == "" {
return fmt.Errorf("resource id not set")
}
client := testAccProvider.Meta().(*iapi.Server)
tokens := strings.Split(resource.Primary.ID, "!")
_, err := client.GetService(tokens[1], tokens[0])
if err != nil {
return fmt.Errorf("error getting getting Service: %s", err)
}
return nil
}
}

View File

@ -0,0 +1,30 @@
package icinga2
import (
"fmt"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func testAccCheckResourceState(resourceName, key, value string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Not found: %s", resourceName)
}
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
}
}

View File

@ -30,6 +30,7 @@ import (
googleprovider "github.com/hashicorp/terraform/builtin/providers/google"
grafanaprovider "github.com/hashicorp/terraform/builtin/providers/grafana"
herokuprovider "github.com/hashicorp/terraform/builtin/providers/heroku"
icinga2provider "github.com/hashicorp/terraform/builtin/providers/icinga2"
influxdbprovider "github.com/hashicorp/terraform/builtin/providers/influxdb"
libratoprovider "github.com/hashicorp/terraform/builtin/providers/librato"
logentriesprovider "github.com/hashicorp/terraform/builtin/providers/logentries"
@ -92,6 +93,7 @@ var InternalProviders = map[string]plugin.ProviderFunc{
"google": googleprovider.Provider,
"grafana": grafanaprovider.Provider,
"heroku": herokuprovider.Provider,
"icinga2": icinga2provider.Provider,
"influxdb": influxdbprovider.Provider,
"librato": libratoprovider.Provider,
"logentries": logentriesprovider.Provider,

354
vendor/github.com/lrsmith/go-icinga2-api/LICENSE generated vendored Normal file
View File

@ -0,0 +1,354 @@
Mozilla Public License, version 2.0
1. Definitions
1.1. “Contributor”
means each individual or legal entity that creates, contributes to the
creation of, or owns Covered Software.
1.2. “Contributor Version”
means the combination of the Contributions of others (if any) used by a
Contributor and that particular Contributors Contribution.
1.3. “Contribution”
means Covered Software of a particular Contributor.
1.4. “Covered Software”
means Source Code Form to which the initial Contributor has attached the
notice in Exhibit A, the Executable Form of such Source Code Form, and
Modifications of such Source Code Form, in each case including portions
thereof.
1.5. “Incompatible With Secondary Licenses”
means
a. that the initial Contributor has attached the notice described in
Exhibit B to the Covered Software; or
b. that the Covered Software was made available under the terms of version
1.1 or earlier of the License, but not also under the terms of a
Secondary License.
1.6. “Executable Form”
means any form of the work other than Source Code Form.
1.7. “Larger Work”
means a work that combines Covered Software with other material, in a separate
file or files, that is not Covered Software.
1.8. “License”
means this document.
1.9. “Licensable”
means having the right to grant, to the maximum extent possible, whether at the
time of the initial grant or subsequently, any and all of the rights conveyed by
this License.
1.10. “Modifications”
means any of the following:
a. any file in Source Code Form that results from an addition to, deletion
from, or modification of the contents of Covered Software; or
b. any new file in Source Code Form that contains any Covered Software.
1.11. “Patent Claims” of a Contributor
means any patent claim(s), including without limitation, method, process,
and apparatus claims, in any patent Licensable by such Contributor that
would be infringed, but for the grant of the License, by the making,
using, selling, offering for sale, having made, import, or transfer of
either its Contributions or its Contributor Version.
1.12. “Secondary License”
means either the GNU General Public License, Version 2.0, the GNU Lesser
General Public License, Version 2.1, the GNU Affero General Public
License, Version 3.0, or any later versions of those licenses.
1.13. “Source Code Form”
means the form of the work preferred for making modifications.
1.14. “You” (or “Your”)
means an individual or a legal entity exercising rights under this
License. For legal entities, “You” includes any entity that controls, is
controlled by, or is under common control with You. For purposes of this
definition, “control” means (a) the power, direct or indirect, to cause
the direction or management of such entity, whether by contract or
otherwise, or (b) ownership of more than fifty percent (50%) of the
outstanding shares or beneficial ownership of such entity.
2. License Grants and Conditions
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
a. under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or as
part of a Larger Work; and
b. under Patent Claims of such Contributor to make, use, sell, offer for
sale, have made, import, and otherwise transfer either its Contributions
or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution become
effective for each Contribution on the date the Contributor first distributes
such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under this
License. No additional rights or licenses will be implied from the distribution
or licensing of Covered Software under this License. Notwithstanding Section
2.1(b) above, no patent license is granted by a Contributor:
a. for any code that a Contributor has removed from Covered Software; or
b. for infringements caused by: (i) Your and any other third partys
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
c. under Patent Claims infringed by Covered Software in the absence of its
Contributions.
This License does not grant any rights in the trademarks, service marks, or
logos of any Contributor (except as may be necessary to comply with the
notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this License
(see Section 10.2) or under the terms of a Secondary License (if permitted
under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its Contributions
are its original creation(s) or it has sufficient rights to grant the
rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under applicable
copyright doctrines of fair use, fair dealing, or other equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
Section 2.1.
3. Responsibilities
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under the
terms of this License. You must inform recipients that the Source Code Form
of the Covered Software is governed by the terms of this License, and how
they can obtain a copy of this License. You may not attempt to alter or
restrict the recipients rights in the Source Code Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
a. such Covered Software must also be made available in Source Code Form,
as described in Section 3.1, and You must inform recipients of the
Executable Form how they can obtain a copy of such Source Code Form by
reasonable means in a timely manner, at a charge no more than the cost
of distribution to the recipient; and
b. You may distribute such Executable Form under the terms of this License,
or sublicense it under different terms, provided that the license for
the Executable Form does not attempt to limit or alter the recipients
rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for the
Covered Software. If the Larger Work is a combination of Covered Software
with a work governed by one or more Secondary Licenses, and the Covered
Software is not Incompatible With Secondary Licenses, this License permits
You to additionally distribute such Covered Software under the terms of
such Secondary License(s), so that the recipient of the Larger Work may, at
their option, further distribute the Covered Software under the terms of
either this License or such Secondary License(s).
3.4. Notices
You may not remove or alter the substance of any license notices (including
copyright notices, patent notices, disclaimers of warranty, or limitations
of liability) contained within the Source Code Form of the Covered
Software, except that You may alter any license notices to the extent
required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on behalf
of any Contributor. You must make it absolutely clear that any such
warranty, support, indemnity, or liability obligation is offered by You
alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
If it is impossible for You to comply with any of the terms of this License
with respect to some or all of the Covered Software due to statute, judicial
order, or regulation then You must: (a) comply with the terms of this License
to the maximum extent possible; and (b) describe the limitations and the code
they affect. Such description must be placed in a text file included with all
distributions of the Covered Software under this License. Except to the
extent prohibited by statute or regulation, such description must be
sufficiently detailed for a recipient of ordinary skill to be able to
understand it.
5. Termination
5.1. The rights granted under this License will terminate automatically if You
fail to comply with any of its terms. However, if You become compliant,
then the rights granted under this License from a particular Contributor
are reinstated (a) provisionally, unless and until such Contributor
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
if such Contributor fails to notify You of the non-compliance by some
reasonable means prior to 60 days after You have come back into compliance.
Moreover, Your grants from a particular Contributor are reinstated on an
ongoing basis if such Contributor notifies You of the non-compliance by
some reasonable means, this is the first time You have received notice of
non-compliance with this License from such Contributor, and You become
compliant prior to 30 days after Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions, counter-claims,
and cross-claims) alleging that a Contributor Version directly or
indirectly infringes any patent, then the rights granted to You by any and
all Contributors for the Covered Software under Section 2.1 of this License
shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
license agreements (excluding distributors and resellers) which have been
validly granted by You or Your distributors under this License prior to
termination shall survive termination.
6. Disclaimer of Warranty
Covered Software is provided under this License on an “as is” basis, without
warranty of any kind, either expressed, implied, or statutory, including,
without limitation, warranties that the Covered Software is free of defects,
merchantable, fit for a particular purpose or non-infringing. The entire
risk as to the quality and performance of the Covered Software is with You.
Should any Covered Software prove defective in any respect, You (not any
Contributor) assume the cost of any necessary servicing, repair, or
correction. This disclaimer of warranty constitutes an essential part of this
License. No use of any Covered Software is authorized under this License
except under this disclaimer.
7. Limitation of Liability
Under no circumstances and under no legal theory, whether tort (including
negligence), contract, or otherwise, shall any Contributor, or anyone who
distributes Covered Software as permitted above, be liable to You for any
direct, indirect, special, incidental, or consequential damages of any
character including, without limitation, damages for lost profits, loss of
goodwill, work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses, even if such party shall have been
informed of the possibility of such damages. This limitation of liability
shall not apply to liability for death or personal injury resulting from such
partys negligence to the extent applicable law prohibits such limitation.
Some jurisdictions do not allow the exclusion or limitation of incidental or
consequential damages, so this exclusion and limitation may not apply to You.
8. Litigation
Any litigation relating to this License may be brought only in the courts of
a jurisdiction where the defendant maintains its principal place of business
and such litigation shall be governed by laws of that jurisdiction, without
reference to its conflict-of-law provisions. Nothing in this Section shall
prevent a partys ability to bring cross-claims or counter-claims.
9. Miscellaneous
This License represents the complete agreement concerning the subject matter
hereof. If any provision of this License is held to be unenforceable, such
provision shall be reformed only to the extent necessary to make it
enforceable. Any law or regulation which provides that the language of a
contract shall be construed against the drafter shall not be used to construe
this License against a Contributor.
10. Versions of the License
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version of
the License under which You originally received the Covered Software, or
under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a modified
version of this License if you rename the license and remove any
references to the name of the license steward (except to note that such
modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
This Source Code Form is subject to the
terms of the Mozilla Public License, v.
2.0. If a copy of the MPL was not
distributed with this file, You can
obtain one at
http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular file, then
You may include the notice in a location (such as a LICENSE file in a relevant
directory) where a recipient would be likely to look for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - “Incompatible With Secondary Licenses” Notice
This Source Code Form is “Incompatible
With Secondary Licenses”, as defined by
the Mozilla Public License, v. 2.0.

View File

@ -0,0 +1,83 @@
package iapi
import (
"encoding/json"
"fmt"
)
// GetCheckcommand ...
func (server *Server) GetCheckcommand(name string) ([]CheckcommandStruct, error) {
var checkcommands []CheckcommandStruct
results, err := server.NewAPIRequest("GET", "/objects/checkcommands/"+name, nil)
if err != nil {
return nil, err
}
// Contents of the results is an interface object. Need to convert it to json first.
jsonStr, marshalErr := json.Marshal(results.Results)
if marshalErr != nil {
return nil, marshalErr
}
// then the JSON can be pushed into the appropriate struct.
// Note : Results is a slice so much push into a slice.
if unmarshalErr := json.Unmarshal(jsonStr, &checkcommands); unmarshalErr != nil {
return nil, unmarshalErr
}
return checkcommands, err
}
// CreateCheckcommand ...
func (server *Server) CreateCheckcommand(name, command string, command_arguments map[string]string) ([]CheckcommandStruct, error) {
var newAttrs CheckcommandAttrs
newAttrs.Command = []string{command}
newAttrs.Arguments = command_arguments
var newCheckcommand CheckcommandStruct
newCheckcommand.Name = name
newCheckcommand.Type = "CheckCommand"
newCheckcommand.Attrs = newAttrs
// Create JSON from completed struct
payloadJSON, marshalErr := json.Marshal(newCheckcommand)
if marshalErr != nil {
return nil, marshalErr
}
//fmt.Printf("<payload> %s\n", payloadJSON)
// Make the API request to create the hosts.
results, err := server.NewAPIRequest("PUT", "/objects/checkcommands/"+name, []byte(payloadJSON))
if err != nil {
return nil, err
}
if results.Code == 200 {
theCheckcommand, err := server.GetCheckcommand(name)
return theCheckcommand, err
}
return nil, fmt.Errorf("%s", results.ErrorString)
}
// DeleteCheckcommand ...
func (server *Server) DeleteCheckcommand(name string) error {
results, err := server.NewAPIRequest("DELETE", "/objects/checkcommands/"+name+"?cascade=1", nil)
if err != nil {
return err
}
if results.Code == 200 {
return nil
} else {
return fmt.Errorf("%s", results.ErrorString)
}
}

134
vendor/github.com/lrsmith/go-icinga2-api/iapi/client.go generated vendored Normal file
View File

@ -0,0 +1,134 @@
// Package iapi provides a client for interacting with an Icinga2 Server
package iapi
import (
"bytes"
"crypto/tls"
"encoding/json"
"net/http"
"strings"
"time"
)
// Server ... Use to be ClientConfig
type Server struct {
Username string
Password string
BaseURL string
AllowUnverifiedSSL bool
httpClient *http.Client
}
// func New ...
func New(username, password, url string, allowUnverifiedSSL bool) (*Server, error) {
return &Server{username, password, url, allowUnverifiedSSL, nil}, nil
}
// func Config ...
func (server *Server) Config(username, password, url string, allowUnverifiedSSL bool) (*Server, error) {
// TODO : Add code to verify parameters
return &Server{username, password, url, allowUnverifiedSSL, nil}, nil
}
func (server *Server) Connect() error {
t := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: server.AllowUnverifiedSSL,
},
}
server.httpClient = &http.Client{
Transport: t,
Timeout: time.Second * 60,
}
request, err := http.NewRequest("GET", server.BaseURL, nil)
if err != nil {
server.httpClient = nil
}
request.SetBasicAuth(server.Username, server.Password)
request.Header.Set("Accept", "application/json")
request.Header.Set("Content-Type", "application/json")
response, err := server.httpClient.Do(request)
if (err != nil) || (response == nil) {
server.httpClient = nil
return err
}
defer response.Body.Close()
return nil
}
// NewAPIRequest ...
func (server *Server) NewAPIRequest(method, APICall string, jsonString []byte) (*APIResult, error) {
var results APIResult
fullURL := server.BaseURL + APICall
t := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: server.AllowUnverifiedSSL,
},
}
server.httpClient = &http.Client{
Transport: t,
Timeout: time.Second * 60,
}
request, requestErr := http.NewRequest(method, fullURL, bytes.NewBuffer(jsonString))
if requestErr != nil {
return nil, requestErr
}
request.SetBasicAuth(server.Username, server.Password)
request.Header.Set("Accept", "application/json")
request.Header.Set("Content-Type", "application/json")
response, doErr := server.httpClient.Do(request)
if doErr != nil {
results.Code = 0
results.Status = "Error : Request to server failed : " + doErr.Error()
results.ErrorString = doErr.Error()
return &results, doErr
}
defer response.Body.Close()
if decodeErr := json.NewDecoder(response.Body).Decode(&results); decodeErr != nil {
return nil, decodeErr
}
if results.Code == 0 { // results.Code has default value so set it.
results.Code = response.StatusCode
}
if results.Status == "" { // results.Status has default value, so set it.
results.Status = response.Status
}
switch results.Code {
case 0:
results.ErrorString = "Did not get a response code."
case 404:
results.ErrorString = results.Status
case 200:
results.ErrorString = results.Status
default:
theError := strings.Replace(results.Results.([]interface{})[0].(map[string]interface{})["errors"].([]interface{})[0].(string), "\n", " ", -1)
results.ErrorString = strings.Replace(theError, "Error: ", "", -1)
}
return &results, nil
}

View File

@ -0,0 +1,88 @@
package iapi
import (
"encoding/json"
"errors"
"fmt"
)
// GetHostgroup ...
//
func (server *Server) GetHostgroup(name string) ([]HostgroupStruct, error) {
var hostgroups []HostgroupStruct
results, err := server.NewAPIRequest("GET", "/objects/hostgroups/"+name, nil)
if err != nil {
return nil, err
}
// Contents of the results is an interface object. Need to convert it to json first.
jsonStr, marshalErr := json.Marshal(results.Results)
if marshalErr != nil {
return nil, marshalErr
}
// then the JSON can be pushed into the appropriate struct.
// Note : Results is a slice so much push into a slice.
if unmarshalErr := json.Unmarshal(jsonStr, &hostgroups); unmarshalErr != nil {
return nil, unmarshalErr
}
if len(hostgroups) == 0 {
return nil, nil
}
if len(hostgroups) != 1 {
return nil, errors.New("Found more than one matching hostgroup.")
}
return hostgroups, err
}
// CreateHostgroup ...
func (server *Server) CreateHostgroup(name, displayName string) ([]HostgroupStruct, error) {
var newAttrs HostgroupAttrs
newAttrs.DisplayName = displayName
var newHostgroup HostgroupStruct
newHostgroup.Name = name
newHostgroup.Type = "Hostgroup"
newHostgroup.Attrs = newAttrs
payloadJSON, marshalErr := json.Marshal(newHostgroup)
if marshalErr != nil {
return nil, marshalErr
}
results, err := server.NewAPIRequest("PUT", "/objects/hostgroups/"+name, []byte(payloadJSON))
if err != nil {
return nil, err
}
if results.Code == 200 {
hostgroups, err := server.GetHostgroup(name)
return hostgroups, err
}
return nil, fmt.Errorf("%s", results.ErrorString)
}
// DeleteHostgroup ...
func (server *Server) DeleteHostgroup(name string) error {
results, err := server.NewAPIRequest("DELETE", "/objects/hostgroups/"+name, nil)
if err != nil {
return err
}
if results.Code == 200 {
return nil
} else {
return fmt.Errorf("%s", results.ErrorString)
}
}

85
vendor/github.com/lrsmith/go-icinga2-api/iapi/hosts.go generated vendored Normal file
View File

@ -0,0 +1,85 @@
package iapi
import (
"encoding/json"
"fmt"
)
// GetHost ...
func (server *Server) GetHost(hostname string) ([]HostStruct, error) {
var hosts []HostStruct
results, err := server.NewAPIRequest("GET", "/objects/hosts/"+hostname, nil)
if err != nil {
return nil, err
}
// Contents of the results is an interface object. Need to convert it to json first.
jsonStr, marshalErr := json.Marshal(results.Results)
if marshalErr != nil {
return nil, marshalErr
}
// then the JSON can be pushed into the appropriate struct.
// Note : Results is a slice so much push into a slice.
if unmarshalErr := json.Unmarshal(jsonStr, &hosts); unmarshalErr != nil {
return nil, unmarshalErr
}
return hosts, err
}
// CreateHost ...
func (server *Server) CreateHost(hostname, address, checkCommand string, variables map[string]string) ([]HostStruct, error) {
var newAttrs HostAttrs
newAttrs.Address = address
newAttrs.CheckCommand = "hostalive"
newAttrs.Vars = variables
var newHost HostStruct
newHost.Name = hostname
newHost.Type = "Host"
newHost.Attrs = newAttrs
// Create JSON from completed struct
payloadJSON, marshalErr := json.Marshal(newHost)
if marshalErr != nil {
return nil, marshalErr
}
//fmt.Printf("<payload> %s\n", payloadJSON)
// Make the API request to create the hosts.
results, err := server.NewAPIRequest("PUT", "/objects/hosts/"+hostname, []byte(payloadJSON))
if err != nil {
return nil, err
}
if results.Code == 200 {
hosts, err := server.GetHost(hostname)
return hosts, err
}
return nil, fmt.Errorf("%s", results.ErrorString)
}
// DeleteHost ...
func (server *Server) DeleteHost(hostname string) error {
results, err := server.NewAPIRequest("DELETE", "/objects/hosts/"+hostname+"?cascade=1", nil)
if err != nil {
return err
}
if results.Code == 200 {
return nil
} else {
return fmt.Errorf("%s", results.ErrorString)
}
}

View File

@ -0,0 +1,80 @@
package iapi
import (
"encoding/json"
"fmt"
)
// GetService ...
func (server *Server) GetService(servicename, hostname string) ([]ServiceStruct, error) {
var services []ServiceStruct
results, err := server.NewAPIRequest("GET", "/objects/services/"+hostname+"!"+servicename, nil)
if err != nil {
return nil, err
}
// Contents of the results is an interface object. Need to convert it to json first.
jsonStr, marshalErr := json.Marshal(results.Results)
if marshalErr != nil {
return nil, marshalErr
}
// then the JSON can be pushed into the appropriate struct.
// Note : Results is a slice so much push into a slice.
if unmarshalErr := json.Unmarshal(jsonStr, &services); unmarshalErr != nil {
return nil, unmarshalErr
}
return services, err
}
// CreateService ...
func (server *Server) CreateService(servicename, hostname, checkCommand string) ([]ServiceStruct, error) {
var newAttrs ServiceAttrs
newAttrs.CheckCommand = checkCommand
var newService ServiceStruct
newService.Attrs = newAttrs
// Create JSON from completed struct
payloadJSON, marshalErr := json.Marshal(newService)
if marshalErr != nil {
return nil, marshalErr
}
//fmt.Printf("<payload> %s\n", payloadJSON)
// Make the API request to create the hosts.
results, err := server.NewAPIRequest("PUT", "/objects/services/"+hostname+"!"+servicename, []byte(payloadJSON))
if err != nil {
return nil, err
}
if results.Code == 200 {
services, err := server.GetService(servicename, hostname)
return services, err
}
return nil, fmt.Errorf("%s", results.ErrorString)
}
// DeleteService ...
func (server *Server) DeleteService(servicename, hostname string) error {
results, err := server.NewAPIRequest("DELETE", "/objects/services/"+hostname+"!"+servicename+"?cascade=1", nil)
if err != nil {
return err
}
if results.Code == 200 {
return nil
} else {
return fmt.Errorf("%s", results.ErrorString)
}
}

View File

@ -0,0 +1,127 @@
package iapi
/*
Currently to get something working and that can be refactored there is a lot of duplicate and overlapping decleration. In
part this is because when a variable is defined it is set to a default value. This has been problematic with having an attrs
struct that has all the variables. That struct then cannot be used to create the JSON for the create, without modification,
because it would try and set values that are not configurable via the API. i.e. for hosts "LastCheck" So to keep things moving
duplicate or near duplicate defintions of structs are being defined but can be revisted and refactored later and test will
be in place to ensure everything still works.
*/
//ServiceStruct stores service results
type ServiceStruct struct {
Attrs ServiceAttrs `json:"attrs"`
Joins struct{} `json:"joins"`
// Meta struct{} `json:"meta"`
Name string `json:"name"`
Type string `json:"type"`
}
type ServiceAttrs struct {
CheckCommand string `json:"check_command"`
// CheckInterval float64 `json:"check_interval"`
// DisplayName string `json:"display_name"`
// Groups []interface{} `json:"groups"`
//Name string `json:"name"`
// Templates []string `json:"templates"`
// Type string `json:"type"`
// Vars interface{} `json:"vars"`
}
// CheckcommandStruct is a struct used to store results from an Icinga2 Checkcommand API call.
type CheckcommandStruct struct {
Name string `json:"name"`
Type string `json:"type"`
Attrs CheckcommandAttrs `json:"attrs"`
Joins struct{} `json:"joins"`
Meta struct{} `json:"meta"`
}
type CheckcommandAttrs struct {
Arguments interface{} `json:"arguments"`
Command []string `json:"command"`
Templates []string `json:"templates"`
// Env interface{} `json:"env"` // Available to be set but not supported yet
// Package string `json:"package"` // Available to be set but not supported yet
// Timeout float64 `json:"timeout"` // Available to be set but not supported yet
// Vars interface{} `json:"vars"` // Available to be set but not supported yet
// Zone string `json:"zone"` // Available to be set but not supported yet
}
// HostgroupStruct is a struct used to store results from an Icinga2 HostGroup API Call. The content are also used to generate the JSON for the CreateHost call
type HostgroupStruct struct {
Name string `json:"name"`
Type string `json:"type"`
Attrs HostgroupAttrs `json:"attrs"`
Meta struct{} `json:"meta"`
Joins struct{} `json:"stuct"`
}
// HostgroupAttrs ...
type HostgroupAttrs struct {
ActionURL string `json:"action_url"`
DisplayName string `json:"display_name"`
Groups []string `json:"groups"`
Notes string `json:"notes"`
NotesURL string `json:"notes_url"`
Templates []string `json:"templates"`
}
// HostStruct is a struct used to store results from an Icinga2 Host API Call. The content are also used to generate the JSON for the CreateHost call
type HostStruct struct {
Name string `json:"name"`
Type string `json:"type"`
Attrs HostAttrs `json:"attrs"`
Meta struct{} `json:"meta"`
Joins struct{} `json:"stuct"`
}
// HostAttrs This is struct lists the attributes that can be set during a CreateHost call. The contents of the struct is converted into JSON
type HostAttrs struct {
ActionURL string `json:"action_url"`
Address string `json:"address"`
Address6 string `json:"address6"`
CheckCommand string `json:"check_command"`
DisplayName string `json:"display_name"`
Groups []string `json:"groups"`
Notes string `json:"notes"`
NotesURL string `json:"notes_url"`
Templates []string `json:"templates"`
Vars interface{} `json:"vars"`
}
// APIResult Stores the results from NewApiRequest
type APIResult struct {
Error float64 `json:"error"`
ErrorString string
Status string `json:"Status"`
Code int `json:"Code"`
Results interface{} `json:"results"`
}
// APIStatus stores the results of an Icinga2 API Status Call
type APIStatus struct {
Results []struct {
Name string `json:"name"`
Perfdata []string `json:"perfdata"`
Status struct {
API struct {
ConnEndpoints []interface{} `json:"conn_endpoints"`
Identity string `json:"identity"`
NotConnEndpoints []interface{} `json:"not_conn_endpoints"`
NumConnEndpoints int `json:"num_conn_endpoints"`
NumEndpoints int `json:"num_endpoints"`
NumNotConnEndpoints int `json:"num_not_conn_endpoints"`
Zones struct {
Master struct {
ClientLogLag int `json:"client_log_lag"`
Connected bool `json:"connected"`
Endpoints []string `json:"endpoints"`
ParentZone string `json:"parent_zone"`
} `json:"master"`
} `json:"zones"`
} `json:"api"`
} `json:"status"`
} `json:"results"`
}

8
vendor/vendor.json vendored
View File

@ -1972,6 +1972,12 @@
"revision": "f6d02e2fca401d3550e08a292f54b0efb6a578f0",
"revisionTime": "2016-07-04T14:48:39Z"
},
{
"checksumSHA1": "8fIVetxvijD+9nPT5TEl2OeDHxg=",
"path": "github.com/lrsmith/go-icinga2-api/iapi",
"revision": "ba9eccb088d652b05154765828ad78345bc36f14",
"revisionTime": "2016-12-10T04:55:21Z"
},
{
"path": "github.com/lusis/go-artifactory/src/artifactory.v401",
"revision": "7e4ce345df825841661d1b3ffbb1327083d4a22f"
@ -2485,5 +2491,5 @@
"revision": "77178f22699a4ecafce485fb8d86b7afeb7e3e28"
}
],
"rootPath": "github.com/hashicorp/terraform"
"rootPath": "github.com/lrsmith/terraform"
}

View File

@ -0,0 +1,93 @@
---
layout: "icinga2"
page_title: "Provider: Icinga2"
sidebar_current: "docs-icinga2-index"
description: |-
The Icinga2 provider is used to configure hosts to be monitored by
Icinga2 servers. The provider needs to be configured with the API
URL of the Icinga2 server and credentials for an API user with the
appropriate permissions.
---
---
# Icinga2 Provider
The Icinga2 provider is used to configure hosts to be monitored by
[Icinga2](https://www.icinga.com/products/icinga-2/) servers. The provider
needs to be configured with the API URL of the Icinga2 server and credentials
for an API user with the appropriate permissions.
## Example Usage
```
# Configure the Icinga2 provider
provider "icinga2" {
api_url=https://192.168.33.5:5665/v1
api_user=root
api_password=icinga
insecure_skip_tls_verify=true
}
# Configure a host
resouce "icinga2_host" "web-server"{
...
}
```
## Authentication
### Static credentials ###
Static credentials can be provided by adding an `api_user` and `api_password` in-line in the
icinga2 provider block:
Usage:
```
provider "icinga2" {
api_url=https://192.168.33.5:5665/v1
api_user=root
api_password=icinga
}
```
###Environment variables
You can provide your credentials via `ICINGA2_API_USER` and `ICINGA2_API_PASSWORD`,
environment variables, storing your Icinga2 API user and password, respectively.
`ICINGA2_API_URL` and `ICINGA2_INSECURE_SKIP_TLS_VERIFY` are also used, if applicable:
```
provider "icinga" {}
```
Usage:
```
$ export ICINGA2_API_URL=https://192.168.33.5:5665/v1
$ export ICINGA2_API_USER=root
$ export ICINGA2_API_PASSWORD=icinga
$ export ICINGA2_INSECURE_SKIP_TLS_VERIFY=true
$ terraform plan
```
## Argument Reference
* ``api_url`` - (Required) The root API URL of an Icinga2 server. May alternatively be
set via the ``ICINGA2_API_URL`` environment variable.
* ``api_user`` - (Required) The API username to use to
authenticate to the Icinga2 server. May alternatively
be set via the ``ICINGA2_API_USER`` environment variable.
* ``api_password`` - (Required) The password to use to
authenticate to the Icinga2 server. May alternatively
be set via the ``ICINGA2_API_PASSWORD`` environment variable.
* ``insecure_skip_tls_verify`` - (optional) Defaults to false. If set to true,
verification of the Icinga2 server's SSL certificate is disabled. This is a security
risk and should be avoided. May alternatively be set via the
``ICINGA2_INSECURE_SKIP_TLS_VERIFY`` environment variable.

View File

@ -0,0 +1,41 @@
---
layout: "icinga2"
page_title: "Icinga2: host"
sidebar_current: "docs-icinga2-resource-checkcommand"
description: |-
Configures a checkcommand resource. This allows checkcommands to be configured, updated and deleted.
---
# icinga2\_checkcommand
Configures an Icinga2 checkcommand resource. This allows checkcommands to be configured, updated,
and deleted.
## Example Usage
```
# Configure a new checkcommand on an Icinga2 Server, that can be used to monitor hosts and/or services
provider "icinga2" {
api_url=https://192.168.33.5:5665/v1
}
resource "icinga2_checkcommand" "apache_status" {
name = "apache_status"
templates = [ "apache-status","plugin-check-command","plugin-check-command","ipv4-or-ipv6" ]
command = "/usr/lib64/nagios/plugins/check_apache_status.pl"
arguments = {
"-H" = "$apache_status_address$"
"-c" = "$apache_status_critical$"
"-p" = "$apache_status_port$"
}
}
```
## Argument Reference
The following arguments are supported:
* `arguments` - (Optional) A mapping of arguments to include with the command.
* `command` - (Required) Path to the command te be executed.
* `name` - (Required) Name by which to reference the checkcommand
* `templates` - (Optional) A list of Icinga2 templates to assign to the host.

View File

@ -0,0 +1,44 @@
---
layout: "icinga2"
page_title: "Icinga2: host"
sidebar_current: "docs-icinga2-resource-host"
description: |-
Configures a host resource. This allows hosts to be configured, updated and deleted.
---
# icinga2\_host
Configures an Icinga2 host resource. This allows hosts to be configured, updated,
and deleted.
## Example Usage
```
# Configure a new host to be monitored by an Icinga2 Server
provider "icinga2" {
api_url=https://192.168.33.5:5665/v1
}
resource "icinga2_host" "host" {
hostname = "terraform-host-1"
address = "10.10.10.1"
check_command = "hostalive"
templates = [ "bp-host-web" ]
vars {
os = "linux"
osver = "1"
allowance = "none"
}
}
```
## Argument Reference
The following arguments are supported:
* `address` - (Required) The address of the host.
* `check_command` - (Required) The name of an existing Icinga2 CheckCommand object that is used to determine if the host is available or not.
* `hostname` - (Required) The hostname of the host.
* `templates` - (Optional) A list of Icinga2 templates to assign to the host.
* `vars` - (Optional) A mapping of variables to assign to the host.

View File

@ -0,0 +1,36 @@
---
layout: "icinga2"
page_title: "Icinga2: hostgroup"
sidebar_current: "docs-icinga2-resource-hostgroup"
description: |-
Configures a hostgroup resource. This allows hostgroup to be configured, updated and deleted.
---
# icinga2\_hostgroup
Configures an Icinga2 hostgroup resource. This allows hostgroup to be configured, updated,
and deleted.
## Example Usage
```
# Configure a new hostgroup to be monitored by an Icinga2 Server
provider "icinga2" {
api_url=https://192.168.33.5:5665/v1
}
resource "icinga2_hostgroup" "my-hostgroup" {
name = "terraform-hostgroup-1"
display_name = "Terraform Test HostGroup"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name of the hostgroup.
* `display_name` - (Required) The name of the hostgroup to display in the Icinga2 interface.

View File

@ -0,0 +1,36 @@
---
layout: "icinga2"
page_title: "Icinga2: service"
sidebar_current: "docs-icinga2-resource-service"
description: |-
Configures a service resource. This allows service to be configured, updated and deleted.
---
# icinga2\_service
Configures an Icinga2 service resource. This allows service to be configured, updated,
and deleted.
## Example Usage
```
# Configure a new service to be monitored by an Icinga2 Server
provider "icinga2" {
api_url=https://192.168.33.5:5665/v1
}
resource "icinga2_service" "my-service" {
hostname = "c1-mysql-1"
servicename = "ssh"
check_command = "ssh"
}
```
## Argument Reference
The following arguments are supported:
* `check_command` - (Required) The name of an existing Icinga2 CheckCommand object that is used to determine if the service is available on the host.
* `hostname` - (Required) The host to check the service's status on
* `servicename` - (Required) The name of the service.