provider/cobbler: Cobbler Provider

This introduces a provider for Cobbler. Cobbler manages bare-metal
deployments and, to some extent, virtual machines. This initial
commit supports the following resources: distros, profiles, systems,
kickstart files, and snippets.
This commit is contained in:
Joe Topjian 2016-03-23 05:00:34 +00:00 committed by Paul Hinze
parent 12118b6189
commit 831bae8624
23 changed files with 3190 additions and 1 deletions

View File

@ -0,0 +1,12 @@
package main
import (
"github.com/hashicorp/terraform/builtin/providers/cobbler"
"github.com/hashicorp/terraform/plugin"
)
func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: cobbler.Provider,
})
}

View File

@ -0,0 +1,86 @@
#!/bin/bash
# This script assumes Ubuntu 14.04 is being used.
# It will create a standard Cobbler environment that can be used for acceptance testing.
sudo apt-get update
sudo apt-get install -y git make mercurial
cd
echo 'export PATH=$PATH:$HOME/terraform:$HOME/go/bin' >> ~/.bashrc
export PATH=$PATH:$HOME/terraform:$HOME/go/bin
sudo wget -O /usr/local/bin/gimme https://raw.githubusercontent.com/travis-ci/gimme/master/gimme
sudo chmod +x /usr/local/bin/gimme
/usr/local/bin/gimme 1.6 >> ~/.bashrc
eval "$(/usr/local/bin/gimme 1.6)"
mkdir ~/go
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export GO15VENDOREXPERIMENT=1' >> ~/.bashrc
export GOPATH=$HOME/go
source ~/.bashrc
go get github.com/tools/godep
go get github.com/hashicorp/terraform
cd $GOPATH/src/github.com/hashicorp/terraform
godep restore
# Cobbler
sudo apt-get install -y cobbler cobbler-web debmirror dnsmasq
sudo tee /etc/cobbler/modules.conf <<EOF
[authentication]
module = authn_configfile
[authorization]
module = authz_allowall
[dns]
module = manage_dnsmasq
[dhcp]
module = manage_dnsmasq
[tftpd]
module = manage_in_tftpd
EOF
sudo tee /etc/cobbler/dnsmasq.template <<EOF
dhcp-range = 192.168.255.200,192.168.255.250
server = 8.8.8.8
read-ethers
addn-hosts = /var/lib/cobbler/cobbler_hosts
dhcp-option=3,\$next_server
dhcp-lease-max=1000
dhcp-authoritative
dhcp-boot=pxelinux.0
dhcp-boot=net:normalarch,pxelinux.0
dhcp-boot=net:ia64,\$elilo
\$insert_cobbler_system_definitions
EOF
sudo sed -i -e 's/^manage_dhcp: 0/manage_dhcp: 1/' /etc/cobbler/settings
sudo sed -i -e 's/^manage_dns: 0/manage_dns: 1/' /etc/cobbler/settings
sudo sed -i -e 's/^next_server:.*/next_server: 127.0.0.1/' /etc/cobbler/settings
sudo sed -i -e 's/^server:.*/server: 127.0.0.1/' /etc/cobbler/settings
sudo tee /etc/cobbler/users.digets <<EOF
cobbler:Cobbler:8e9c0aa3ae45bb39347866c41cb4d293
EOF
# The stock version of Cobbler in the Ubuntu repository still has the old cobbler homepage URL
sudo sed -i -e 's#content_server = "http://www.cobblerd.org/loaders"#content_server = "http://cobbler.github.com/loaders"#' /usr/lib/python2.7/dist-packages/cobbler/action_dlcontent.py
sudo rm /usr/lib/python2.7/dist-packages/cobbler/action_dlcontent.pyc
sudo /etc/init.d/apache2 restart
sudo stop cobbler
sleep 2
sudo start cobbler
sleep 10
sudo cobbler get-loaders
sudo cobbler sync
# Import an Ubuntu 1404 distro
cd /tmp
wget http://old-releases.ubuntu.com/releases/14.04.2/ubuntu-14.04-server-amd64.iso
sudo mount -o loop ubuntu-14.04-server-amd64.iso /mnt
sudo cobbler import --name Ubuntu-14.04 --breed ubuntu --path /mnt

View File

@ -0,0 +1,33 @@
package cobbler
import (
"net/http"
cobbler "github.com/jtopjian/cobblerclient"
)
type Config struct {
Url string
Username string
Password string
cobblerClient cobbler.Client
}
func (c *Config) loadAndValidate() error {
config := cobbler.ClientConfig{
Url: c.Url,
Username: c.Username,
Password: c.Password,
}
client := cobbler.NewClient(http.DefaultClient, config)
_, err := client.Login()
if err != nil {
return err
}
c.cobblerClient = client
return nil
}

View File

@ -0,0 +1,76 @@
package cobbler
import (
"os"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"url": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Cobbler URL",
DefaultFunc: envDefaultFunc("COBBLER_URL"),
},
"username": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "The username for accessing Cobbler.",
DefaultFunc: envDefaultFunc("COBBLER_USERNAME"),
},
"password": &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "The password for accessing Cobbler.",
DefaultFunc: envDefaultFunc("COBBLER_PASSWORD"),
},
},
ResourcesMap: map[string]*schema.Resource{
"cobbler_distro": resourceDistro(),
"cobbler_kickstart_file": resourceKickstartFile(),
"cobbler_profile": resourceProfile(),
"cobbler_snippet": resourceSnippet(),
"cobbler_system": resourceSystem(),
},
ConfigureFunc: configureProvider,
}
}
func configureProvider(d *schema.ResourceData) (interface{}, error) {
config := Config{
Url: d.Get("url").(string),
Username: d.Get("username").(string),
Password: d.Get("password").(string),
}
if err := config.loadAndValidate(); err != nil {
return nil, err
}
return &config, nil
}
func envDefaultFunc(k string) schema.SchemaDefaultFunc {
return func() (interface{}, error) {
if v := os.Getenv(k); v != "" {
return v, nil
}
return nil, nil
}
}
func envDefaultFuncAllowMissing(k string) schema.SchemaDefaultFunc {
return func() (interface{}, error) {
v := os.Getenv(k)
return v, nil
}
}

View File

@ -0,0 +1,46 @@
package cobbler
import (
"os"
"testing"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
var testAccCobblerProviders map[string]terraform.ResourceProvider
var testAccCobblerProvider *schema.Provider
func init() {
testAccCobblerProvider = Provider().(*schema.Provider)
testAccCobblerProviders = map[string]terraform.ResourceProvider{
"cobbler": testAccCobblerProvider,
}
}
func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestProvider_impl(t *testing.T) {
var _ terraform.ResourceProvider = Provider()
}
func testAccCobblerPreCheck(t *testing.T) {
v := os.Getenv("COBBLER_USERNAME")
if v == "" {
t.Fatal("COBBLER_USERNAME must be set for acceptance tests.")
}
v = os.Getenv("COBBLER_PASSWORD")
if v == "" {
t.Fatal("COBBLER_PASSWORD must be set for acceptance tests.")
}
v = os.Getenv("COBBLER_URL")
if v == "" {
t.Fatal("COBBLER_URL must be set for acceptance tests.")
}
}

View File

@ -0,0 +1,224 @@
package cobbler
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/schema"
cobbler "github.com/jtopjian/cobblerclient"
)
func resourceDistro() *schema.Resource {
return &schema.Resource{
Create: resourceDistroCreate,
Read: resourceDistroRead,
Update: resourceDistroUpdate,
Delete: resourceDistroDelete,
Schema: map[string]*schema.Schema{
"arch": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"breed": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"boot_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"comment": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"fetchable_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kernel": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"kernel_options": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kernel_options_post": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"initrd": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"mgmt_classes": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"os_version": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"owners": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Computed: true,
},
"redhat_management_key": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"redhat_management_server": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"template_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}
func resourceDistroCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Create a cobblerclient.Distro
distro := buildDistro(d, config)
// Attempte to create the Distro
log.Printf("[DEBUG] Cobbler Distro: Create Options: %#v", distro)
newDistro, err := config.cobblerClient.CreateDistro(distro)
if err != nil {
return fmt.Errorf("Cobbler Distro: Error Creating: %s", err)
}
d.SetId(newDistro.Name)
return resourceDistroRead(d, meta)
}
func resourceDistroRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Retrieve the distro from cobbler
distro, err := config.cobblerClient.GetDistro(d.Id())
if err != nil {
return fmt.Errorf("Cobbler Distro: Error Reading (%s): %s", d.Id(), err)
}
// Set all fields
d.Set("arch", distro.Arch)
d.Set("breed", distro.Breed)
d.Set("boot_files", distro.BootFiles)
d.Set("comment", distro.Comment)
d.Set("fetchable_files", distro.FetchableFiles)
d.Set("kernel", distro.Kernel)
d.Set("kernel_options", distro.KernelOptions)
d.Set("kernel_options_post", distro.KernelOptionsPost)
d.Set("initrd", distro.Initrd)
d.Set("mgmt_classes", distro.MGMTClasses)
d.Set("os_version", distro.OSVersion)
d.Set("owners", distro.Owners)
d.Set("redhat_management_key", distro.RedHatManagementKey)
d.Set("redhat_management_server", distro.RedHatManagementServer)
d.Set("template_files", distro.TemplateFiles)
return nil
}
func resourceDistroUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// create a cobblerclient.Distro
distro := buildDistro(d, config)
// Attempt to updateh the distro with new information
log.Printf("[DEBUG] Cobbler Distro: Updating Distro (%s) with options: %+v", d.Id(), distro)
err := config.cobblerClient.UpdateDistro(&distro)
if err != nil {
return fmt.Errorf("Cobbler Distro: Error Updating (%s): %s", d.Id(), err)
}
return resourceDistroRead(d, meta)
}
func resourceDistroDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Attempt to delete the distro
if err := config.cobblerClient.DeleteDistro(d.Id()); err != nil {
return fmt.Errorf("Cobbler Distro: Error Deleting (%s): %s", d.Id(), err)
}
return nil
}
// buildDistro builds a cobbler.Distro from the Terraform attributes
func buildDistro(d *schema.ResourceData, meta interface{}) cobbler.Distro {
mgmtClasses := []string{}
for _, i := range d.Get("mgmt_classes").([]interface{}) {
mgmtClasses = append(mgmtClasses, i.(string))
}
owners := []string{}
for _, i := range d.Get("owners").([]interface{}) {
owners = append(owners, i.(string))
}
distro := cobbler.Distro{
Arch: d.Get("arch").(string),
Breed: d.Get("breed").(string),
BootFiles: d.Get("boot_files").(string),
Comment: d.Get("comment").(string),
FetchableFiles: d.Get("fetchable_files").(string),
Kernel: d.Get("kernel").(string),
KernelOptions: d.Get("kernel_options").(string),
KernelOptionsPost: d.Get("kernel_options_post").(string),
Initrd: d.Get("initrd").(string),
MGMTClasses: mgmtClasses,
Name: d.Get("name").(string),
OSVersion: d.Get("os_version").(string),
Owners: owners,
RedHatManagementKey: d.Get("redhat_management_key").(string),
RedHatManagementServer: d.Get("redhat_management_server").(string),
TemplateFiles: d.Get("template_files").(string),
}
return distro
}

View File

@ -0,0 +1,129 @@
package cobbler
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
cobbler "github.com/jtopjian/cobblerclient"
)
func TestAccCobblerDistro_basic(t *testing.T) {
var distro cobbler.Distro
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckDistroDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerDistro_basic,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
),
},
},
})
}
func TestAccCobblerDistro_change(t *testing.T) {
var distro cobbler.Distro
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckDistroDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerDistro_change_1,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
),
},
resource.TestStep{
Config: testAccCobblerDistro_change_2,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
),
},
},
})
}
func testAccCobblerCheckDistroDestroy(s *terraform.State) error {
config := testAccCobblerProvider.Meta().(*Config)
for _, rs := range s.RootModule().Resources {
if rs.Type != "cobbler_distro" {
continue
}
if _, err := config.cobblerClient.GetDistro(rs.Primary.ID); err == nil {
return fmt.Errorf("Distro still exists")
}
}
return nil
}
func testAccCobblerCheckDistroExists(t *testing.T, n string, distro *cobbler.Distro) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
config := testAccCobblerProvider.Meta().(*Config)
found, err := config.cobblerClient.GetDistro(rs.Primary.ID)
if err != nil {
return err
}
if found.Name != rs.Primary.ID {
return fmt.Errorf("Distro not found")
}
*distro = *found
return nil
}
}
var testAccCobblerDistro_basic = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}`
var testAccCobblerDistro_change_1 = `
resource "cobbler_distro" "foo" {
name = "foo"
comment = "I am a distro"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}`
var testAccCobblerDistro_change_2 = `
resource "cobbler_distro" "foo" {
name = "foo"
comment = "I am a distro again"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}`

View File

@ -0,0 +1,83 @@
package cobbler
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/schema"
cobbler "github.com/jtopjian/cobblerclient"
)
func resourceKickstartFile() *schema.Resource {
return &schema.Resource{
Create: resourceKickstartFileCreate,
Read: resourceKickstartFileRead,
Update: resourceKickstartFileUpdate,
Delete: resourceKickstartFileDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"body": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
}
}
func resourceKickstartFileCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
ks := cobbler.KickstartFile{
Name: d.Get("name").(string),
Body: d.Get("body").(string),
}
log.Printf("[DEBUG] Cobbler KickstartFile: Create Options: %#v", ks)
if err := config.cobblerClient.CreateKickstartFile(ks); err != nil {
return fmt.Errorf("Cobbler KickstartFile: Error Creating: %s", err)
}
d.SetId(ks.Name)
return resourceKickstartFileRead(d, meta)
}
func resourceKickstartFileRead(d *schema.ResourceData, meta interface{}) error {
// Since all attributes are required and not computed,
// there's no reason to read.
return nil
}
func resourceKickstartFileUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
ks := cobbler.KickstartFile{
Name: d.Id(),
Body: d.Get("body").(string),
}
log.Printf("[DEBUG] Cobbler KickstartFile: Updating Kickstart (%s) with options: %+v", d.Id(), ks)
if err := config.cobblerClient.CreateKickstartFile(ks); err != nil {
return fmt.Errorf("Cobbler KickstartFile: Error Updating (%s): %s", d.Id(), err)
}
return resourceKickstartFileRead(d, meta)
}
func resourceKickstartFileDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
if err := config.cobblerClient.DeleteKickstartFile(d.Id()); err != nil {
return fmt.Errorf("Cobbler KickstartFile: Error Deleting (%s): %s", d.Id(), err)
}
return nil
}

View File

@ -0,0 +1,79 @@
package cobbler
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
cobbler "github.com/jtopjian/cobblerclient"
)
func TestAccCobblerKickstartFile_basic(t *testing.T) {
var ks cobbler.KickstartFile
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckKickstartFileDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerKickstartFile_basic,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckKickstartFileExists(t, "cobbler_kickstart_file.foo", &ks),
),
},
},
})
}
func testAccCobblerCheckKickstartFileDestroy(s *terraform.State) error {
config := testAccCobblerProvider.Meta().(*Config)
for _, rs := range s.RootModule().Resources {
if rs.Type != "cobbler_kickstart_file" {
continue
}
if _, err := config.cobblerClient.GetKickstartFile(rs.Primary.ID); err == nil {
return fmt.Errorf("Kickstart File still exists")
}
}
return nil
}
func testAccCobblerCheckKickstartFileExists(t *testing.T, n string, ks *cobbler.KickstartFile) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
config := testAccCobblerProvider.Meta().(*Config)
found, err := config.cobblerClient.GetKickstartFile(rs.Primary.ID)
if err != nil {
return err
}
if found.Name != rs.Primary.ID {
return fmt.Errorf("Kickstart File not found")
}
*ks = *found
return nil
}
}
var testAccCobblerKickstartFile_basic = `
resource "cobbler_kickstart_file" "foo" {
name = "/var/lib/cobbler/kickstarts/foo.ks"
body = "I'm a kickstart file."
}`

View File

@ -0,0 +1,369 @@
package cobbler
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/schema"
cobbler "github.com/jtopjian/cobblerclient"
)
func resourceProfile() *schema.Resource {
return &schema.Resource{
Create: resourceProfileCreate,
Read: resourceProfileRead,
Update: resourceProfileUpdate,
Delete: resourceProfileDelete,
Schema: map[string]*schema.Schema{
"boot_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"comment": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"distro": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"enable_gpxe": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"enable_menu": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"fetchable_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kernel_options": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kernel_options_post": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kickstart": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ks_meta": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"mgmt_classes": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"mgmt_parameters": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name_servers_search": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"name_servers": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"owners": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"parent": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"proxy": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"redhat_management_key": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"redhat_management_server": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"repos": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"server": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"template_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"template_remote_kickstarts": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"virt_auto_boot": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_bridge": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_cpus": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_disk_driver": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_file_size": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_ram": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}
func resourceProfileCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Create a cobblerclient.Profile struct
profile := buildProfile(d, config)
// Attempt to create the Profile
log.Printf("[DEBUG] Cobbler Profile: Create Options: %#v", profile)
newProfile, err := config.cobblerClient.CreateProfile(profile)
if err != nil {
return fmt.Errorf("Cobbler Profile: Error Creating: %s", err)
}
d.SetId(newProfile.Name)
return resourceProfileRead(d, meta)
}
func resourceProfileRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Retrieve the profile entry from Cobbler
profile, err := config.cobblerClient.GetProfile(d.Id())
if err != nil {
return fmt.Errorf("Cobbler Profile: Error Reading (%s): %s", d.Id(), err)
}
// Set all fields
d.Set("boot_files", profile.BootFiles)
d.Set("comment", profile.Comment)
d.Set("distro", profile.Distro)
d.Set("enable_gpxe", profile.EnableGPXE)
d.Set("enable_menu", profile.EnableMenu)
d.Set("fetchable_files", profile.FetchableFiles)
d.Set("kernel_options", profile.KernelOptions)
d.Set("kernel_options_post", profile.KernelOptionsPost)
d.Set("kickstart", profile.Kickstart)
d.Set("ks_meta", profile.KSMeta)
d.Set("mgmt_classes", profile.MGMTClasses)
d.Set("mgmt_parameters", profile.MGMTParameters)
d.Set("name_servers_search", profile.NameServersSearch)
d.Set("name_servers", profile.NameServers)
d.Set("owners", profile.Owners)
d.Set("proxy", profile.Proxy)
d.Set("redhat_management_key", profile.RedHatManagementKey)
d.Set("redhat_management_server", profile.RedHatManagementServer)
d.Set("repos", profile.Repos)
d.Set("template_files", profile.TemplateFiles)
d.Set("template_remote_kickstarts", profile.TemplateRemoteKickstarts)
d.Set("virt_auto_boot", profile.VirtAutoBoot)
d.Set("virt_bridge", profile.VirtBridge)
d.Set("virt_cpus", profile.VirtCPUs)
d.Set("virt_disk_driver", profile.VirtDiskDriver)
d.Set("virt_file_size", profile.VirtFileSize)
d.Set("virt_path", profile.VirtPath)
d.Set("virt_ram", profile.VirtRam)
d.Set("virt_type", profile.VirtType)
return nil
}
func resourceProfileUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Create a cobblerclient.Profile struct
profile := buildProfile(d, config)
// Attempt to update the profile with new information
log.Printf("[DEBUG] Cobbler Profile: Updating Profile (%s) with options: %+v", d.Id(), profile)
err := config.cobblerClient.UpdateProfile(&profile)
if err != nil {
return fmt.Errorf("Cobbler Profile: Error Updating (%s): %s", d.Id(), err)
}
return resourceProfileRead(d, meta)
}
func resourceProfileDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Attempt to delete the profile
if err := config.cobblerClient.DeleteProfile(d.Id()); err != nil {
return fmt.Errorf("Cobbler Profile: Error Deleting (%s): %s", d.Id(), err)
}
return nil
}
// buildProfile builds a cobblerclient.Profile out of the Terraform attributes
func buildProfile(d *schema.ResourceData, meta interface{}) cobbler.Profile {
mgmtClasses := []string{}
for _, i := range d.Get("mgmt_classes").([]interface{}) {
mgmtClasses = append(mgmtClasses, i.(string))
}
nameServersSearch := []string{}
for _, i := range d.Get("name_servers_search").([]interface{}) {
nameServersSearch = append(nameServersSearch, i.(string))
}
nameServers := []string{}
for _, i := range d.Get("name_servers").([]interface{}) {
nameServers = append(nameServers, i.(string))
}
owners := []string{}
for _, i := range d.Get("owners").([]interface{}) {
owners = append(owners, i.(string))
}
repos := []string{}
for _, i := range d.Get("repos").([]interface{}) {
repos = append(repos, i.(string))
}
profile := cobbler.Profile{
BootFiles: d.Get("boot_files").(string),
Comment: d.Get("comment").(string),
Distro: d.Get("distro").(string),
EnableGPXE: d.Get("enable_gpxe").(bool),
EnableMenu: d.Get("enable_menu").(bool),
FetchableFiles: d.Get("fetchable_files").(string),
KernelOptions: d.Get("kernel_options").(string),
KernelOptionsPost: d.Get("kernel_options_post").(string),
Kickstart: d.Get("kickstart").(string),
KSMeta: d.Get("ks_meta").(string),
MGMTClasses: mgmtClasses,
MGMTParameters: d.Get("mgmt_parameters").(string),
Name: d.Get("name").(string),
NameServersSearch: nameServersSearch,
NameServers: nameServers,
Owners: owners,
Parent: d.Get("parent").(string),
Proxy: d.Get("proxy").(string),
RedHatManagementKey: d.Get("redhat_management_key").(string),
RedHatManagementServer: d.Get("redhat_management_server").(string),
Repos: repos,
Server: d.Get("server").(string),
TemplateFiles: d.Get("template_files").(string),
TemplateRemoteKickstarts: d.Get("template_remote_kickstarts").(int),
VirtAutoBoot: d.Get("virt_auto_boot").(string),
VirtBridge: d.Get("virt_bridge").(string),
VirtCPUs: d.Get("virt_cpus").(string),
VirtDiskDriver: d.Get("virt_disk_driver").(string),
VirtFileSize: d.Get("virt_file_size").(string),
VirtPath: d.Get("virt_path").(string),
VirtRam: d.Get("virt_ram").(string),
VirtType: d.Get("virt_type").(string),
}
return profile
}

View File

@ -0,0 +1,149 @@
package cobbler
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
cobbler "github.com/jtopjian/cobblerclient"
)
func TestAccCobblerProfile_basic(t *testing.T) {
var distro cobbler.Distro
var profile cobbler.Profile
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckProfileDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerProfile_basic,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
),
},
},
})
}
func TestAccCobblerProfile_change(t *testing.T) {
var distro cobbler.Distro
var profile cobbler.Profile
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckProfileDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerProfile_change_1,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
),
},
resource.TestStep{
Config: testAccCobblerProfile_change_2,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
),
},
},
})
}
func testAccCobblerCheckProfileDestroy(s *terraform.State) error {
config := testAccCobblerProvider.Meta().(*Config)
for _, rs := range s.RootModule().Resources {
if rs.Type != "cobbler_profile" {
continue
}
if _, err := config.cobblerClient.GetProfile(rs.Primary.ID); err == nil {
return fmt.Errorf("Profile still exists")
}
}
return nil
}
func testAccCobblerCheckProfileExists(t *testing.T, n string, profile *cobbler.Profile) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
config := testAccCobblerProvider.Meta().(*Config)
found, err := config.cobblerClient.GetProfile(rs.Primary.ID)
if err != nil {
return err
}
if found.Name != rs.Primary.ID {
return fmt.Errorf("Profile not found")
}
*profile = *found
return nil
}
}
var testAccCobblerProfile_basic = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}`
var testAccCobblerProfile_change_1 = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
comment = "I am a profile"
distro = "${cobbler_distro.foo.name}"
}`
var testAccCobblerProfile_change_2 = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
comment = "I am a profile again"
distro = "${cobbler_distro.foo.name}"
}`

View File

@ -0,0 +1,83 @@
package cobbler
import (
"fmt"
"log"
"github.com/hashicorp/terraform/helper/schema"
cobbler "github.com/jtopjian/cobblerclient"
)
func resourceSnippet() *schema.Resource {
return &schema.Resource{
Create: resourceSnippetCreate,
Read: resourceSnippetRead,
Update: resourceSnippetUpdate,
Delete: resourceSnippetDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"body": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
}
}
func resourceSnippetCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
snippet := cobbler.Snippet{
Name: d.Get("name").(string),
Body: d.Get("body").(string),
}
log.Printf("[DEBUG] Cobbler Snippet: Create Options: %#v", snippet)
if err := config.cobblerClient.CreateSnippet(snippet); err != nil {
return fmt.Errorf("Cobbler Snippet: Error Creating: %s", err)
}
d.SetId(snippet.Name)
return resourceSnippetRead(d, meta)
}
func resourceSnippetRead(d *schema.ResourceData, meta interface{}) error {
// Since all attributes are required and not computed,
// there's no reason to read.
return nil
}
func resourceSnippetUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
snippet := cobbler.Snippet{
Name: d.Id(),
Body: d.Get("body").(string),
}
log.Printf("[DEBUG] Cobbler Snippet: Updating Snippet (%s) with options: %+v", d.Id(), snippet)
if err := config.cobblerClient.CreateSnippet(snippet); err != nil {
return fmt.Errorf("Cobbler Snippet: Error Updating (%s): %s", d.Id(), err)
}
return resourceSnippetRead(d, meta)
}
func resourceSnippetDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
if err := config.cobblerClient.DeleteSnippet(d.Id()); err != nil {
return fmt.Errorf("Cobbler Snippet: Error Deleting (%s): %s", d.Id(), err)
}
return nil
}

View File

@ -0,0 +1,79 @@
package cobbler
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
cobbler "github.com/jtopjian/cobblerclient"
)
func TestAccCobblerSnippet_basic(t *testing.T) {
var snippet cobbler.Snippet
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckSnippetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerSnippet_basic,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckSnippetExists(t, "cobbler_snippet.foo", &snippet),
),
},
},
})
}
func testAccCobblerCheckSnippetDestroy(s *terraform.State) error {
config := testAccCobblerProvider.Meta().(*Config)
for _, rs := range s.RootModule().Resources {
if rs.Type != "cobbler_snippet" {
continue
}
if _, err := config.cobblerClient.GetSnippet(rs.Primary.ID); err == nil {
return fmt.Errorf("Snippet still exists")
}
}
return nil
}
func testAccCobblerCheckSnippetExists(t *testing.T, n string, snippet *cobbler.Snippet) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
config := testAccCobblerProvider.Meta().(*Config)
found, err := config.cobblerClient.GetSnippet(rs.Primary.ID)
if err != nil {
return err
}
if found.Name != rs.Primary.ID {
return fmt.Errorf("Snippet not found")
}
*snippet = *found
return nil
}
}
var testAccCobblerSnippet_basic = `
resource "cobbler_snippet" "foo" {
name = "/var/lib/cobbler/snippets/foo"
body = "I'm a Snippet."
}`

View File

@ -0,0 +1,851 @@
package cobbler
import (
"bytes"
"fmt"
"log"
"sync"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
cobbler "github.com/jtopjian/cobblerclient"
)
var systemSyncLock sync.Mutex
func resourceSystem() *schema.Resource {
return &schema.Resource{
Create: resourceSystemCreate,
Read: resourceSystemRead,
Update: resourceSystemUpdate,
Delete: resourceSystemDelete,
Schema: map[string]*schema.Schema{
"boot_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"comment": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"enable_gpxe": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"fetchable_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"gateway": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"hostname": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"image": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"interface": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"cnames": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"dhcp_tag": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"dns_name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"bonding_opts": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"bridge_opts": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"gateway": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"interface_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"interface_master": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ip_address": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ipv6_address": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ipv6_secondaries": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"ipv6_mtu": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ipv6_static_routes": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"ipv6_default_gateway": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"mac_address": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"management": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"netmask": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"static": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"static_routes": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"virt_bridge": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
},
Set: resourceSystemInterfaceHash,
},
"ipv6_default_device": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kernel_options": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kernel_options_post": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kickstart": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ks_meta": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ldap_enabled": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"ldap_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"mgmt_classes": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"mgmt_parameters": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"monit_enabled": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"name_servers_search": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"name_servers": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"netboot_enabled": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"owners": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"power_address": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"power_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"power_pass": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"power_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"power_user": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"profile": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"proxy": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"redhat_management_key": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"redhat_management_server": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"status": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"template_files": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"template_remote_kickstarts": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"virt_auto_boot": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_file_size": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_cpus": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_type": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_path": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_pxe_boot": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"virt_ram": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"virt_disk_driver": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}
func resourceSystemCreate(d *schema.ResourceData, meta interface{}) error {
systemSyncLock.Lock()
defer systemSyncLock.Unlock()
config := meta.(*Config)
// Create a cobblerclient.System struct
system := buildSystem(d)
// Attempt to create the System
log.Printf("[DEBUG] Cobbler System: Create Options: %#v", system)
newSystem, err := config.cobblerClient.CreateSystem(system)
if err != nil {
return fmt.Errorf("Cobbler System: Error Creating: %s", err)
}
// Build cobblerclient.Interface structs
interfaces := buildSystemInterfaces(d.Get("interface").(*schema.Set))
// Add each interface to the system
for interfaceName, interfaceInfo := range interfaces {
log.Printf("[DEBUG] Cobbler System Interface %#v: %#v", interfaceName, interfaceInfo)
if err := newSystem.CreateInterface(interfaceName, interfaceInfo); err != nil {
return fmt.Errorf("Cobbler System: Error adding Interface %s to %s: %s", interfaceName, newSystem.Name, err)
}
}
log.Printf("[DEBUG] Cobbler System: Created System: %#v", newSystem)
d.SetId(newSystem.Name)
log.Printf("[DEBUG] Cobbler System: syncing system")
if err := config.cobblerClient.Sync(); err != nil {
return fmt.Errorf("Cobbler System: Error syncing system: %s", err)
}
return resourceSystemRead(d, meta)
}
func resourceSystemRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Retrieve the system entry from Cobbler
system, err := config.cobblerClient.GetSystem(d.Id())
if err != nil {
return fmt.Errorf("Cobbler System: Error Reading (%s): %s", d.Id(), err)
}
// Set all fields
d.Set("boot_files", system.BootFiles)
d.Set("comment", system.Comment)
d.Set("enable_gpxe", system.EnableGPXE)
d.Set("fetchable_files", system.FetchableFiles)
d.Set("gateway", system.Gateway)
d.Set("hostname", system.Hostname)
d.Set("image", system.Image)
d.Set("ipv6_default_device", system.IPv6DefaultDevice)
d.Set("kernel_options", system.KernelOptions)
d.Set("kernel_options_post", system.KernelOptionsPost)
d.Set("kickstart", system.Kickstart)
d.Set("ks_meta", system.KSMeta)
d.Set("ldap_enabled", system.LDAPEnabled)
d.Set("ldap_type", system.LDAPType)
d.Set("mgmt_classes", system.MGMTClasses)
d.Set("mgmt_parameters", system.MGMTParameters)
d.Set("monit_enabled", system.MonitEnabled)
d.Set("name_servers_search", system.NameServersSearch)
d.Set("name_servers", system.NameServers)
d.Set("netboot_enabled", system.NetbootEnabled)
d.Set("owners", system.Owners)
d.Set("power_address", system.PowerAddress)
d.Set("power_id", system.PowerID)
d.Set("power_pass", system.PowerPass)
d.Set("power_type", system.PowerType)
d.Set("power_user", system.PowerUser)
d.Set("profile", system.Profile)
d.Set("proxy", system.Proxy)
d.Set("redhat_management_key", system.RedHatManagementKey)
d.Set("redhat_management_server", system.RedHatManagementServer)
d.Set("status", system.Status)
d.Set("template_files", system.TemplateFiles)
d.Set("template_remote_kickstarts", system.TemplateRemoteKickstarts)
d.Set("virt_auto_boot", system.VirtAutoBoot)
d.Set("virt_file_size", system.VirtFileSize)
d.Set("virt_cpus", system.VirtCPUs)
d.Set("virt_type", system.VirtType)
d.Set("virt_path", system.VirtPath)
d.Set("virt_pxe_boot", system.VirtPXEBoot)
d.Set("virt_ram", system.VirtRam)
d.Set("virt_disk_driver", system.VirtDiskDriver)
// Get all interfaces that the System has
allInterfaces, err := system.GetInterfaces()
if err != nil {
return fmt.Errorf("Cobbler System %s: Error getting interfaces: %s", system.Name, err)
}
// Build a generic map array with the interface attributes
var systemInterfaces []map[string]interface{}
for interfaceName, interfaceInfo := range allInterfaces {
iface := make(map[string]interface{})
iface["name"] = interfaceName
iface["cnames"] = interfaceInfo.CNAMEs
iface["dhcp_tag"] = interfaceInfo.DHCPTag
iface["dns_name"] = interfaceInfo.DNSName
iface["bonding_opts"] = interfaceInfo.BondingOpts
iface["bridge_opts"] = interfaceInfo.BridgeOpts
iface["gateway"] = interfaceInfo.Gateway
iface["interface_type"] = interfaceInfo.InterfaceType
iface["interface_master"] = interfaceInfo.InterfaceMaster
iface["ip_address"] = interfaceInfo.IPAddress
iface["ipv6_address"] = interfaceInfo.IPv6Address
iface["ipv6_secondaries"] = interfaceInfo.IPv6Secondaries
iface["ipv6_mtu"] = interfaceInfo.IPv6MTU
iface["ipv6_static_routes"] = interfaceInfo.IPv6StaticRoutes
iface["ipv6_default_gateway"] = interfaceInfo.IPv6DefaultGateway
iface["mac_address"] = interfaceInfo.MACAddress
iface["management"] = interfaceInfo.Management
iface["netmask"] = interfaceInfo.Netmask
iface["static"] = interfaceInfo.Static
iface["static_Routes"] = interfaceInfo.StaticRoutes
iface["virt_bridge"] = interfaceInfo.VirtBridge
systemInterfaces = append(systemInterfaces, iface)
}
d.Set("interface", systemInterfaces)
return nil
}
func resourceSystemUpdate(d *schema.ResourceData, meta interface{}) error {
systemSyncLock.Lock()
defer systemSyncLock.Unlock()
config := meta.(*Config)
// Retrieve the existing system entry from Cobbler
system, err := config.cobblerClient.GetSystem(d.Id())
if err != nil {
return fmt.Errorf("Cobbler System: Error Reading (%s): %s", d.Id(), err)
}
// Get a list of the old interfaces
currentInterfaces, err := system.GetInterfaces()
if err != nil {
return fmt.Errorf("Error getting interfaces: %s", err)
}
log.Printf("[DEBUG] Cobbler System Interfaces: %#v", currentInterfaces)
// Create a new cobblerclient.System struct with the new information
newSystem := buildSystem(d)
// Attempt to update the system with new information
log.Printf("[DEBUG] Cobbler System: Updating System (%s) with options: %+v", d.Id(), system)
err = config.cobblerClient.UpdateSystem(&newSystem)
if err != nil {
return fmt.Errorf("Cobbler System: Error Updating (%s): %s", d.Id(), err)
}
if d.HasChange("interface") {
oldInterfaces, newInterfaces := d.GetChange("interface")
oldInterfacesSet := oldInterfaces.(*schema.Set)
newInterfacesSet := newInterfaces.(*schema.Set)
interfacesToRemove := oldInterfacesSet.Difference(newInterfacesSet)
oldIfaces := buildSystemInterfaces(interfacesToRemove)
newIfaces := buildSystemInterfaces(newInterfacesSet)
for interfaceName, interfaceInfo := range oldIfaces {
if _, ok := newIfaces[interfaceName]; !ok {
// Interface does not exist in the new set,
// so it has been removed from terraform.
log.Printf("[DEBUG] Cobbler System: Deleting Interface %#v: %#v", interfaceName, interfaceInfo)
if err := system.DeleteInterface(interfaceName); err != nil {
return fmt.Errorf("Cobbler System: Error deleting Interface %s to %s: %s", interfaceName, system.Name, err)
}
}
}
// Modify interfaces that have changed
for interfaceName, interfaceInfo := range newIfaces {
log.Printf("[DEBUG] Cobbler System: New Interface %#v: %#v", interfaceName, interfaceInfo)
if err := system.CreateInterface(interfaceName, interfaceInfo); err != nil {
return fmt.Errorf("Cobbler System: Error adding Interface %s to %s: %s", interfaceName, system.Name, err)
}
}
}
log.Printf("[DEBUG] Cobbler System: syncing system")
if err := config.cobblerClient.Sync(); err != nil {
return fmt.Errorf("Cobbler System: Error syncing system: %s", err)
}
return resourceSystemRead(d, meta)
}
func resourceSystemDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
// Attempt to delete the system
if err := config.cobblerClient.DeleteSystem(d.Id()); err != nil {
return fmt.Errorf("Cobbler System: Error Deleting (%s): %s", d.Id(), err)
}
return nil
}
// buildSystem builds a cobblerclient.System out of the Terraform attributes
func buildSystem(d *schema.ResourceData) cobbler.System {
mgmtClasses := []string{}
for _, i := range d.Get("mgmt_classes").([]interface{}) {
mgmtClasses = append(mgmtClasses, i.(string))
}
nameServersSearch := []string{}
for _, i := range d.Get("name_servers_search").([]interface{}) {
nameServersSearch = append(nameServersSearch, i.(string))
}
nameServers := []string{}
for _, i := range d.Get("name_servers").([]interface{}) {
nameServers = append(nameServers, i.(string))
}
owners := []string{}
for _, i := range d.Get("owners").([]interface{}) {
owners = append(owners, i.(string))
}
system := cobbler.System{
BootFiles: d.Get("boot_files").(string),
Comment: d.Get("comment").(string),
EnableGPXE: d.Get("enable_gpxe").(bool),
FetchableFiles: d.Get("fetchable_files").(string),
Gateway: d.Get("gateway").(string),
Hostname: d.Get("hostname").(string),
Image: d.Get("image").(string),
IPv6DefaultDevice: d.Get("ipv6_default_device").(string),
KernelOptions: d.Get("kernel_options").(string),
KernelOptionsPost: d.Get("kernel_options_post").(string),
Kickstart: d.Get("kickstart").(string),
KSMeta: d.Get("ks_meta").(string),
LDAPEnabled: d.Get("ldap_enabled").(bool),
LDAPType: d.Get("ldap_type").(string),
MGMTClasses: mgmtClasses,
MGMTParameters: d.Get("mgmt_parameters").(string),
MonitEnabled: d.Get("monit_enabled").(bool),
Name: d.Get("name").(string),
NameServersSearch: nameServersSearch,
NameServers: nameServers,
NetbootEnabled: d.Get("netboot_enabled").(bool),
Owners: owners,
PowerAddress: d.Get("power_address").(string),
PowerID: d.Get("power_id").(string),
PowerPass: d.Get("power_pass").(string),
PowerType: d.Get("power_type").(string),
PowerUser: d.Get("power_user").(string),
Profile: d.Get("profile").(string),
Proxy: d.Get("proxy").(string),
RedHatManagementKey: d.Get("redhat_management_key").(string),
RedHatManagementServer: d.Get("redhat_management_server").(string),
Status: d.Get("status").(string),
TemplateFiles: d.Get("template_files").(string),
TemplateRemoteKickstarts: d.Get("template_remote_kickstarts").(int),
VirtAutoBoot: d.Get("virt_auto_boot").(string),
VirtFileSize: d.Get("virt_file_size").(string),
VirtCPUs: d.Get("virt_cpus").(string),
VirtType: d.Get("virt_type").(string),
VirtPath: d.Get("virt_path").(string),
VirtPXEBoot: d.Get("virt_pxe_boot").(int),
VirtRam: d.Get("virt_ram").(string),
VirtDiskDriver: d.Get("virt_disk_driver").(string),
}
return system
}
// buildSystemInterface builds a cobblerclient.Interface out of the Terraform attributes
func buildSystemInterfaces(systemInterfaces *schema.Set) cobbler.Interfaces {
interfaces := make(cobbler.Interfaces)
rawInterfaces := systemInterfaces.List()
for _, rawInterface := range rawInterfaces {
rawInterfaceMap := rawInterface.(map[string]interface{})
cnames := []string{}
for _, i := range rawInterfaceMap["cnames"].([]interface{}) {
cnames = append(cnames, i.(string))
}
ipv6Secondaries := []string{}
for _, i := range rawInterfaceMap["ipv6_secondaries"].([]interface{}) {
ipv6Secondaries = append(ipv6Secondaries, i.(string))
}
ipv6StaticRoutes := []string{}
for _, i := range rawInterfaceMap["ipv6_static_routes"].([]interface{}) {
ipv6StaticRoutes = append(ipv6StaticRoutes, i.(string))
}
staticRoutes := []string{}
for _, i := range rawInterfaceMap["static_routes"].([]interface{}) {
staticRoutes = append(staticRoutes, i.(string))
}
interfaceName := rawInterfaceMap["name"].(string)
interfaces[interfaceName] = cobbler.Interface{
CNAMEs: cnames,
DHCPTag: rawInterfaceMap["dhcp_tag"].(string),
DNSName: rawInterfaceMap["dns_name"].(string),
BondingOpts: rawInterfaceMap["bonding_opts"].(string),
BridgeOpts: rawInterfaceMap["bridge_opts"].(string),
Gateway: rawInterfaceMap["gateway"].(string),
InterfaceType: rawInterfaceMap["interface_type"].(string),
InterfaceMaster: rawInterfaceMap["interface_master"].(string),
IPAddress: rawInterfaceMap["ip_address"].(string),
IPv6Address: rawInterfaceMap["ipv6_address"].(string),
IPv6Secondaries: ipv6Secondaries,
IPv6MTU: rawInterfaceMap["ipv6_mtu"].(string),
IPv6StaticRoutes: ipv6StaticRoutes,
IPv6DefaultGateway: rawInterfaceMap["ipv6_default_gateway"].(string),
MACAddress: rawInterfaceMap["mac_address"].(string),
Management: rawInterfaceMap["management"].(bool),
Netmask: rawInterfaceMap["netmask"].(string),
Static: rawInterfaceMap["static"].(bool),
StaticRoutes: staticRoutes,
VirtBridge: rawInterfaceMap["virt_bridge"].(string),
}
}
return interfaces
}
func resourceSystemInterfaceHash(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s", m["name"].(string)))
if v, ok := m["cnames"]; ok {
for _, x := range v.([]interface{}) {
buf.WriteString(fmt.Sprintf("%v-", x.(string)))
}
}
if v, ok := m["dhcp_tag"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["dns_name"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["bonding_opts"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["bridge_opts"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["gateway"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["interface_type"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["interface_master"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["ip_address"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["ipv6_address"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["ipv6_secondaries"]; ok {
for _, x := range v.([]interface{}) {
buf.WriteString(fmt.Sprintf("%v-", x.(string)))
}
}
if v, ok := m["ipv6_mtu"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["ipv6_static_routes"]; ok {
for _, x := range v.([]interface{}) {
buf.WriteString(fmt.Sprintf("%v-", x.(string)))
}
}
if v, ok := m["ipv6_default_gateway"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["mac_address"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["management"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(bool)))
}
if v, ok := m["netmask"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
if v, ok := m["static"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(bool)))
}
if v, ok := m["static_Routes"]; ok {
for _, x := range v.([]interface{}) {
buf.WriteString(fmt.Sprintf("%v-", x.(string)))
}
}
if v, ok := m["virt_bridge"]; ok {
buf.WriteString(fmt.Sprintf("%v-", v.(string)))
}
return hashcode.String(buf.String())
}

View File

@ -0,0 +1,380 @@
package cobbler
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
cobbler "github.com/jtopjian/cobblerclient"
)
func TestAccCobblerSystem_basic(t *testing.T) {
var distro cobbler.Distro
var profile cobbler.Profile
var system cobbler.System
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckSystemDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerSystem_basic,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
testAccCobblerCheckSystemExists(t, "cobbler_system.foo", &system),
),
},
},
})
}
func TestAccCobblerSystem_multi(t *testing.T) {
var distro cobbler.Distro
var profile cobbler.Profile
var system cobbler.System
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckSystemDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerSystem_multi,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
testAccCobblerCheckSystemExists(t, "cobbler_system.foo.45", &system),
),
},
},
})
}
func TestAccCobblerSystem_change(t *testing.T) {
var distro cobbler.Distro
var profile cobbler.Profile
var system cobbler.System
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckSystemDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerSystem_change_1,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
testAccCobblerCheckSystemExists(t, "cobbler_system.foo", &system),
),
},
resource.TestStep{
Config: testAccCobblerSystem_change_2,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
testAccCobblerCheckSystemExists(t, "cobbler_system.foo", &system),
),
},
},
})
}
func TestAccCobblerSystem_removeInterface(t *testing.T) {
var distro cobbler.Distro
var profile cobbler.Profile
var system cobbler.System
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccCobblerPreCheck(t) },
Providers: testAccCobblerProviders,
CheckDestroy: testAccCobblerCheckSystemDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCobblerSystem_removeInterface_1,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
testAccCobblerCheckSystemExists(t, "cobbler_system.foo", &system),
),
},
resource.TestStep{
Config: testAccCobblerSystem_removeInterface_2,
Check: resource.ComposeTestCheckFunc(
testAccCobblerCheckDistroExists(t, "cobbler_distro.foo", &distro),
testAccCobblerCheckProfileExists(t, "cobbler_profile.foo", &profile),
testAccCobblerCheckSystemExists(t, "cobbler_system.foo", &system),
),
},
},
})
}
func testAccCobblerCheckSystemDestroy(s *terraform.State) error {
config := testAccCobblerProvider.Meta().(*Config)
for _, rs := range s.RootModule().Resources {
if rs.Type != "cobbler_system" {
continue
}
if _, err := config.cobblerClient.GetSystem(rs.Primary.ID); err == nil {
return fmt.Errorf("System still exists")
}
}
return nil
}
func testAccCobblerCheckSystemExists(t *testing.T, n string, system *cobbler.System) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
config := testAccCobblerProvider.Meta().(*Config)
found, err := config.cobblerClient.GetSystem(rs.Primary.ID)
if err != nil {
return err
}
if found.Name != rs.Primary.ID {
return fmt.Errorf("System not found")
}
*system = *found
return nil
}
}
var testAccCobblerSystem_basic = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}
resource "cobbler_system" "foo" {
name = "foo"
profile = "${cobbler_profile.foo.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
comment = "I'm a system"
power_id = "foo"
interface {
name = "eth0"
mac_address = "aa:bb:cc:dd:ee:ff"
static = true
ip_address = "1.2.3.4"
netmask = "255.255.255.0"
}
interface {
name = "eth1"
mac_address = "aa:bb:cc:dd:ee:fa"
static = true
ip_address = "1.2.3.5"
netmask = "255.255.255.0"
}
}`
var testAccCobblerSystem_multi = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}
resource "cobbler_system" "foo" {
count = 50
name = "${format("foo-%d", count.index)}"
profile = "${cobbler_profile.foo.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
comment = "I'm a system"
power_id = "foo"
interface {
name = "eth0"
}
interface {
name = "eth1"
}
}`
var testAccCobblerSystem_change_1 = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}
resource "cobbler_system" "foo" {
name = "foo"
profile = "${cobbler_profile.foo.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
comment = "I'm a system"
power_id = "foo"
interface {
name = "eth0"
mac_address = "aa:bb:cc:dd:ee:ff"
static = true
ip_address = "1.2.3.4"
netmask = "255.255.255.0"
}
interface {
name = "eth1"
mac_address = "aa:bb:cc:dd:ee:fa"
static = true
ip_address = "1.2.3.5"
netmask = "255.255.255.0"
}
}`
var testAccCobblerSystem_change_2 = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}
resource "cobbler_system" "foo" {
name = "foo"
profile = "${cobbler_profile.foo.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
comment = "I'm a system again"
power_id = "foo"
interface {
name = "eth0"
mac_address = "aa:bb:cc:dd:ee:ff"
static = true
ip_address = "1.2.3.6"
netmask = "255.255.255.0"
}
interface {
name = "eth1"
mac_address = "aa:bb:cc:dd:ee:fa"
static = true
ip_address = "1.2.3.5"
netmask = "255.255.255.0"
}
}`
var testAccCobblerSystem_removeInterface_1 = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}
resource "cobbler_system" "foo" {
name = "foo"
profile = "${cobbler_profile.foo.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
power_id = "foo"
interface {
name = "eth0"
mac_address = "aa:bb:cc:dd:ee:ff"
static = true
ip_address = "1.2.3.4"
netmask = "255.255.255.0"
}
interface {
name = "eth1"
mac_address = "aa:bb:cc:dd:ee:fa"
static = true
ip_address = "1.2.3.5"
netmask = "255.255.255.0"
}
}`
var testAccCobblerSystem_removeInterface_2 = `
resource "cobbler_distro" "foo" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
resource "cobbler_profile" "foo" {
name = "foo"
distro = "${cobbler_distro.foo.name}"
}
resource "cobbler_system" "foo" {
name = "foo"
profile = "${cobbler_profile.foo.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
power_id = "foo"
interface {
name = "eth0"
mac_address = "aa:bb:cc:dd:ee:ff"
static = true
ip_address = "1.2.3.4"
netmask = "255.255.255.0"
}
}`

View File

@ -0,0 +1,45 @@
---
layout: "cobbler"
page_title: "Provider: Cobbler"
sidebar_current: "docs-cobbler-index"
description: |-
The Cobbler provider is used to interact with a locally installed,
Cobbler service.
---
# Cobbler Provider
The Cobbler provider is used to interact with a locally installed
[Cobbler](http://cobbler.github.io) service. The provider needs
to be configured with the proper credentials before it can be used.
Use the navigation to the left to read about the available resources.
## Example Usage
```
# Configure the Cobbler provider
provider "cobbler" {
username = "${var.cobbler_username}"
password = "${var.cobbler_password}"
url = "${var.cobbler_url}"
}
# Create a Cobbler Distro
resource "cobbler_distro" "ubuntu-1404-x86_64" {
...
}
```
## Argument Reference
The following arguments are supported:
* `username` - (Required) The username to the Cobbler service. This can
also be specified with the `COBBLER_USERNAME` shell environment variable.
* `password` - (Required) The password to the Cobbler service. This can
also be specified with the `COBBLER_PASSWORD` shell environment variable.
* `url` - (Required) The url to the Cobbler service. This can
also be specified with the `COBBLER_URL` shell environment variable.

View File

@ -0,0 +1,84 @@
---
layout: "cobbler"
page_title: "Cobbler: cobbler_distro"
sidebar_current: "docs-cobbler-resource-distro"
description: |-
Manages a distribution within Cobbler.
---
# cobbler\_distro
Manages a distribution within Cobbler.
## Example Usage
```
resource "cobbler_distro" "ubuntu-1404-x86_64" {
name = "foo"
breed = "ubuntu"
os_version = "trusty"
arch = "x86_64"
kernel = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/linux"
initrd = "/var/www/cobbler/ks_mirror/Ubuntu-14.04/install/netboot/ubuntu-installer/amd64/initrd.gz"
}
```
## Argument Reference
The following arguments are supported:
* `arch` - (Required) The architecture of the distro. Valid options
are: i386, x86_64, ia64, ppc, ppc64, s390, arm.
* `breed` - (Required) The "breed" of distribution. Valid options
are: redhat, fedora, centos, scientific linux, suse, debian, and
ubuntu. These choices may vary depending on the version of Cobbler
in use.
* `boot_files` - (Optional) Files copied into tftpboot beyond the
kernel/initrd.
* `comment` - (Optional) Free form text description.
* `fetchable_files` - (Optional) Templates for tftp or wget.
* `kernel` - (Required) Absolute path to kernel on filesystem. This
must already exist prior to creating the distro.
* `kernel_options` - (Optional) Kernel options to use with the
kernel.
* `kernel_options_post` - (Optional) Post install Kernel options to
use with the kernel after installation.
* `initrd` - (Required) Absolute path to initrd on filesystem. This
must already exist prior to creating the distro.
* `mgmt_classes` - (Optional) Management classes for external config
management.
* `name` - (Required) A name for the distro.
* `os_version` - (Required) The version of the distro you are
creating. This varies with the version of Cobbler you are using.
An updated signature list may need to be obtained in order to
support a newer version. Example: `trusty`.
* `owners` - (Optional) Owners list for authz_ownership.
* `redhat_management_key` - (Optional) Red Hat Management key.
* `redhat_management_server` - (Optional) Red Hat Management server.
* `template_files` - (Optional) File mappings for built-in config
management.
## Attributes Reference
All of the above Optional attributes are also exported.
## Notes
The path to the `kernel` and `initrd` files must exist before
creating a Distro. Usually this involves running `cobbler import ...`
prior to creating the Distro.

View File

@ -0,0 +1,29 @@
---
layout: "cobbler"
page_title: "Cobbler: cobbler_kickstart_file"
sidebar_current: "docs-cobbler-resource-kickstart_file"
description: |-
Manages a Kickstart File within Cobbler.
---
# cobbler\_kickstart\_file
Manages a Kickstart File within Cobbler.
## Example Usage
```
resource "cobbler_kickstart_file" "my_kickstart" {
name = "/var/lib/cobbler/kickstarts/my_kickstart.ks"
body = "<content of kickstart file>"
}
```
## Argument Reference
The following arguments are supported:
* `body` - (Required) The body of the kickstart file.
* `name` - (Required) The name of the kickstart file. This must be
the full path, including `/var/lib/cobbler/kickstarts`.

View File

@ -0,0 +1,92 @@
---
layout: "cobbler"
page_title: "Cobbler: cobbler_profile"
sidebar_current: "docs-cobbler-resource-profile"
description: |-
Manages a Profile within Cobbler.
---
# cobbler\_profile
Manages a Profile within Cobbler.
## Example Usage
```
resource "cobbler_profile" "my_profile" {
name = "/var/lib/cobbler/snippets/my_snippet"
distro = "ubuntu-1404-x86_64"
}
```
## Argument Reference
The following arguments are supported:
* `boot_files` - (Optional) Files copied into tftpboot beyond the
kernel/initrd.
* `comment` - (Optional) Free form text description.
* `distro` - (Optional) Parent distribution.
* `enable_gpxe` - (Optional) Use gPXE instead of PXELINUX for
advanced booting options.
* `enable_menu` - (Optional) Enable a boot menu.
* `fetchable_files` - (Optional) Templates for tftp or wget.
* `kernel_options` - (Optional) Kernel options for the profile.
* `kernel_options_post` - (Optional) Post install kernel options.
* `kickstart` - (Optional) The kickstart file to use.
* `ks_meta` - (Optional) Kickstart metadata.
* `mgmt_classes` - (Optional) For external configuration management.
* `mgmt_parameters` - (Optional) Parameters which will be handed to
your management application (Must be a valid YAML dictionary).
* `name_servers_search` - (Optional) Name server search settings.
* `name_servers` - (Optional) Name servers.
* `name` - (Required) The name of the profile.
* `owners` - (Optional) Owners list for authz_ownership.
* `proxy` - (Optional) Proxy URL.
* `redhat_management_key` - (Optional) Red Hat Management Key.
* `redhat_management_server` - (Optional) RedHat Management Server.
* `repos` - (Optional) Repos to auto-assign to this profile.
* `template_files` - (Optional) File mappings for built-in config
management.
* `template_remote_kickstarts` - (Optional) remote kickstart
templates.
* `virt_auto_boot` - (Optional) Auto boot virtual machines.
* `virt_bridge` - (Optional) The bridge for virtual machines.
* `virt_cpus` - (Optional) The number of virtual CPUs.
* `virt_file_size` - (Optional) The virtual machine file size.
* `virt_path` - (Optional) The virtual machine path.
* `virt_ram` - (Optional) The amount of RAM for the virtual machine.
* `virt_type` - (Optional) The type of virtual machine. Valid options
are: xenpv, xenfv, qemu, kvm, vmware, openvz.
## Attributes Reference
All of the above Optional attributes are also exported.

View File

@ -0,0 +1,29 @@
---
layout: "cobbler"
page_title: "Cobbler: cobbler_snippet"
sidebar_current: "docs-cobbler-resource-snippet"
description: |-
Manages a Snippet within Cobbler.
---
# cobbler\_snippet
Manages a Snippet within Cobbler.
## Example Usage
```
resource "cobbler_snippet" "my_snippet" {
name = "/var/lib/cobbler/snippets/my_snippet"
body = "<content of snippet>"
}
```
## Argument Reference
The following arguments are supported:
* `body` - (Required) The body of the snippet.
* `name` - (Required) The name of the snippet. This must be the full
path, including `/var/lib/cobbler/snippets`.

View File

@ -0,0 +1,189 @@
---
layout: "cobbler"
page_title: "Cobbler: cobbler_system"
sidebar_current: "docs-cobbler-resource-system"
description: |-
Manages a System within Cobbler.
---
# cobbler\_system
Manages a System within Cobbler.
## Example Usage
```
resource "cobbler_system" "my_system" {
name = "my_system"
profile = "${cobbler_profile.my_profile.name}"
name_servers = ["8.8.8.8", "8.8.4.4"]
comment = "I'm a system"
interface {
name = "eth0"
mac_address = "aa:bb:cc:dd:ee:ff"
static = true
ip_address = "1.2.3.4"
netmask = "255.255.255.0"
}
interface {
name = "eth1"
mac_address = "aa:bb:cc:dd:ee:fa"
static = true
ip_address = "1.2.3.5"
netmask = "255.255.255.0"
}
}
```
## Argument Reference
The following arguments are supported:
* `boot_files` - (Optional) TFTP boot files copied into tftpboot.
* `comment` - (Optional) Free form text description
* `enable_gpxe` - (Optional) Use gPXE instead of PXELINUX.
* `fetchable_files` - (Optional) Templates for tftp or wget.
* `gateway` - (Optional) Network gateway.
* `hostname` - (Optional) Hostname of the system.
* `image` - (Optional) Parent image (if no profile is used).
* `interface` - (Optional)
* `ipv6_default_device` - (Optional) IPv6 default device.
* `kernel_options` - (Optional) Kernel options.
ex: selinux=permissive.
* `kernel_options_post` - (Optional) Kernel options (post install).
* `kickstart` - (Optional) Path to kickstart template.
* `ks_meta` - (Optional) Kickstart metadata.
* `ldap_enabled` - (Optional) Configure LDAP at next config update.
* `ldap_type` - (Optional) LDAP management type.
* `mgmt_classes` - (Optional) Management classes for external config
management.
* `mgmt_parameters` - (Optional) Parameters which will be handed to
your management application. Must be a valid YAML dictionary.
* `monit_enabled` - (Optional) Configure monit on this machine at
next config update.
* `name_servers_search` - (Optional) Name servers search path.
* `name_servers` - (Optional) Name servers.
* `name` - (Required) The name of the system.
* `netboot_enabled` - (Optional) (re)Install this machine at next
boot.
* `owners` - (Optional) Owners list for authz_ownership.
* `power_address` - (Optional) Power management address.
* `power_id` - (Optional) Usually a plug number or blade name if
power type requires it.
* `power_pass` - (Optional) Power management password.
* `power_type` - (Optional) Power management type.
* `power_user` - (Optional) Power management user.
* `profile` - (Required) Parent profile.
* `proxy` - (Optional) Proxy URL.
* `redhat_management_key` - (Optional) Red Hat management key.
* `redhat_management_server` - (Optional) Red Hat management server.
* `status` - (Optional) System status (development, testing,
acceptance, production).
* `template_files` - (Optional) File mappings for built-in
configuration management.
* `template_remote_kickstarts` - (Optional) template remote
kickstarts.
* `virt_auto_boot` - (Optional) Auto boot the VM.
* `virt_cpus` - (Optional) Number of virtual CPUs in the VM.
* `virt_disk_driver` - (Optional) The on-disk format for the
virtualization disk.
* `virt_file_size` - (Optional) Virt file size.
* `virt_path` - (Optional) Path to the VM.
* `virt_pxe_boot` - (Optional) Use PXE to build this VM?
* `virt_ram` - (Optional) The amount of RAM for the VM.
* `virt_type` - (Optional) Virtualization technology to use: xenpv,
xenfv, qemu, kvm, vmware, openvz.
The `interface` block supports:
* `name` - (Required) The device name of the interface. ex: eth0.
* `cnames` - (Optional) Canonical name records.
* `dhcp_tag` - (Optional) DHCP tag.
* `dns_name` - (Optional) DNS name.
* `bonding_opts` - (Optional) Options for bonded interfaces.
* `bridge_opts` - (Optional) Options for bridge interfaces.
* `gateway` - (Optional) Per-interface gateway.
* `interface_type` - (Optional) The type of interface: na, master,
slave, bond, bond_slave, bridge, bridge_slave, bonded_bridge_slave.
* `interface_master` - (Optional) The master interface when slave.
* `ip_address` - (Optional) The IP address of the interface.
* `ipv6_address` - (Optional) The IPv6 address of the interface.
* `ipv6_mtu` - (Optional) The MTU of the IPv6 adress.
* `ipv6_static_routes` - (Optional) Static routes for the IPv6
interface.
* `ipv6_default_gateway` - (Optional) The default gateawy for the
IPv6 address / interface.
* `mac_address` - (Optional) The MAC address of the interface.
* `management` - (Optional) Whether this interface is a management
interface.
* `netmask` - (Optional) The IPv4 netmask of the interface.
* `static` - (Optional) Whether the interface should be static or
DHCP.
* `static_routes` - (Optional) Static routes for the interface.
* `virt_bridge` - (Optional) The virtual bridge to attach to.
## Attribute Reference
All optional attributes listed above are also exported.

View File

@ -0,0 +1,38 @@
<% wrap_layout :inner do %>
<% content_for :sidebar do %>
<div class="docs-sidebar hidden-print affix-top" role="complementary">
<ul class="nav docs-sidenav">
<li<%= sidebar_current("docs-home") %>>
<a href="/docs/providers/index.html">&laquo; Documentation Home</a>
</li>
<li<%= sidebar_current("docs-cobbler-index") %>>
<a href="/docs/providers/cobbler/index.html">Cobbler Provider</a>
</li>
<li<%= sidebar_current(/^docs-cobbler-resource/) %>>
<a href="#">Resources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-cobbler-resource-distro") %>>
<a href="/docs/providers/cobbler/r/distro.html">cobbler_distro</a>
</li>
<li<%= sidebar_current("docs-cobbler-resource-kickstart_file") %>>
<a href="/docs/providers/cobbler/r/kickstart_file.html">cobbler_kickstart_file</a>
</li>
<li<%= sidebar_current("docs-cobbler-resource-profile") %>>
<a href="/docs/providers/cobbler/r/profile.html">cobbler_profile</a>
</li>
<li<%= sidebar_current("docs-cobbler-resource-snippet") %>>
<a href="/docs/providers/cobbler/r/snippet.html">cobbler_snippet</a>
</li>
<li<%= sidebar_current("docs-cobbler-resource-system") %>>
<a href="/docs/providers/cobbler/r/system.html">cobbler_system</a>
</li>
</ul>
</li>
</ul>
</div>
<% end %>
<%= yield %>
<% end %>

View File

@ -165,6 +165,10 @@
<a href="/docs/providers/cloudstack/index.html">CloudStack</a>
</li>
<li<%= sidebar_current("docs-providers-cobbler") %>>
<a href="/docs/providers/cobbler/index.html">Cobbler</a>
</li>
<li<%= sidebar_current("docs-providers-consul") %>>
<a href="/docs/providers/consul/index.html">Consul</a>
</li>
@ -256,7 +260,7 @@
<li<%= sidebar_current("docs-providers-tls") %>>
<a href="/docs/providers/tls/index.html">TLS</a>
</li>
<li<%= sidebar_current("docs-providers-triton") %>>
<a href="/docs/providers/triton/index.html">Triton</a>
</li>