mirror of
https://github.com/letic/terraform-provider-proxmox.git
synced 2024-10-03 01:01:05 +00:00
Add support for a provisioner to support post-processing actions like unplugging the ssh-forwarding, fake net1, adapter.
This commit is contained in:
parent
c2eed29132
commit
2f2c5dff98
13
README.md
13
README.md
@ -12,8 +12,11 @@ Requires https://github.com/Telmate/proxmox-api-go
|
||||
```
|
||||
go build -o terraform-provider-proxmox
|
||||
cp terraform-provider-proxmox $GOPATH/bin
|
||||
cp terraform-provider-proxmox $GOPATH/bin/terraform-provisioner-proxmox
|
||||
```
|
||||
|
||||
Note: this plugin is both a provider and provisioner in one, which is why it needs to be in the $GOPATH/bin/ twice.
|
||||
|
||||
Recommended ISO builder https://github.com/Telmate/terraform-ubuntu-proxmox-iso
|
||||
|
||||
|
||||
@ -56,6 +59,16 @@ EOF
|
||||
auto eth0
|
||||
iface eth0 inet dhcp
|
||||
EOF
|
||||
|
||||
provisioner "remote-exec" {
|
||||
inline = [
|
||||
"ip a"
|
||||
]
|
||||
}
|
||||
|
||||
provisioner "proxmox" {
|
||||
action = "sshbackward"
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
3
main.go
3
main.go
@ -11,5 +11,8 @@ func main() {
|
||||
ProviderFunc: func() terraform.ResourceProvider {
|
||||
return proxmox.Provider()
|
||||
},
|
||||
ProvisionerFunc: func() terraform.ResourceProvisioner {
|
||||
return proxmox.Provisioner()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
pxapi "github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -47,8 +50,7 @@ func Provider() *schema.Provider {
|
||||
}
|
||||
|
||||
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||
client, _ := pxapi.NewClient(d.Get("pm_api_url").(string), nil, nil)
|
||||
err := client.Login(d.Get("pm_user").(string), d.Get("pm_password").(string))
|
||||
client, err := getClient(d.Get("pm_api_url").(string), d.Get("pm_user").(string), d.Get("pm_password").(string))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -57,6 +59,15 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getClient(pm_api_url string, pm_user string, pm_password string) (*pxapi.Client, error) {
|
||||
client, _ := pxapi.NewClient(pm_api_url, nil, nil)
|
||||
err := client.Login(pm_user, pm_password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
var mutex = &sync.Mutex{}
|
||||
var maxVmId = 0
|
||||
|
||||
@ -73,3 +84,20 @@ func nextVmId(client *pxapi.Client) (nextId int, err error) {
|
||||
mutex.Unlock()
|
||||
return nextId, nil
|
||||
}
|
||||
|
||||
func resourceId(targetNode string, resType string, vmId int) string {
|
||||
return fmt.Sprintf("%s/%s/%d", targetNode, resType, vmId)
|
||||
}
|
||||
|
||||
var rxRsId = regexp.MustCompile("([^/]+)/([^/]+)/(\\d+)")
|
||||
|
||||
func parseResourceId(resId string) (targetNode string, resType string, vmId int, err error) {
|
||||
idMatch := rxRsId.FindStringSubmatch(resId)
|
||||
if idMatch == nil {
|
||||
err = fmt.Errorf("Invalid resource id: %s", resId)
|
||||
}
|
||||
targetNode = idMatch[1]
|
||||
resType = idMatch[2]
|
||||
vmId, err = strconv.Atoi(idMatch[3])
|
||||
return
|
||||
}
|
||||
|
58
proxmox/provisioner.go
Normal file
58
proxmox/provisioner.go
Normal file
@ -0,0 +1,58 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
pxapi "github.com/Telmate/proxmox-api-go/proxmox"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func Provisioner() terraform.ResourceProvisioner {
|
||||
return &schema.Provisioner{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"action": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
"net1": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
|
||||
ApplyFunc: applyFn,
|
||||
}
|
||||
}
|
||||
|
||||
var currentClient *pxapi.Client = nil
|
||||
|
||||
func applyFn(ctx context.Context) error {
|
||||
data := ctx.Value(schema.ProvConfigDataKey).(*schema.ResourceData)
|
||||
state := ctx.Value(schema.ProvRawStateKey).(*terraform.InstanceState)
|
||||
|
||||
connInfo := state.Ephemeral.ConnInfo
|
||||
|
||||
act := data.Get("action").(string)
|
||||
targetNode, _, vmId, err := parseResourceId(state.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
vmr := pxapi.NewVmRef(vmId)
|
||||
vmr.SetNode(targetNode)
|
||||
client := currentClient
|
||||
if client == nil {
|
||||
client, err = getClient(connInfo["pm_api_url"], connInfo["pm_user"], connInfo["pm_password"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentClient = client
|
||||
}
|
||||
switch act {
|
||||
case "sshbackward":
|
||||
return pxapi.RemoveSshForwardUsernet(vmr, client)
|
||||
default:
|
||||
return fmt.Errorf("Unkown action: %s", act)
|
||||
}
|
||||
return nil
|
||||
}
|
@ -18,6 +18,9 @@ func resourceVmQemu() *schema.Resource {
|
||||
Read: resourceVmQemuRead,
|
||||
Update: resourceVmQemuUpdate,
|
||||
Delete: resourceVmQemuDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: resourceVmQemuImport,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
@ -197,7 +200,7 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
d.SetId(resourceId(targetNode, vmr.VmId()))
|
||||
d.SetId(resourceId(targetNode, "qemu", vmr.VmId()))
|
||||
|
||||
log.Print("[DEBUG] starting VM")
|
||||
_, err := client.StartVm(vmr)
|
||||
@ -216,6 +219,9 @@ func resourceVmQemuCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
"port": sshPort,
|
||||
"user": d.Get("ssh_user").(string),
|
||||
"private_key": d.Get("ssh_private_key").(string),
|
||||
"pm_api_url": client.ApiUrl,
|
||||
"pm_user": client.Username,
|
||||
"pm_password": client.Password,
|
||||
})
|
||||
|
||||
switch d.Get("os_type").(string) {
|
||||
@ -292,7 +298,7 @@ func resourceVmQemuRead(d *schema.ResourceData, meta interface{}) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.SetId(resourceId(vmr.Node(), vmr.VmId()))
|
||||
d.SetId(resourceId(vmr.Node(), "qemu", vmr.VmId()))
|
||||
d.Set("target_node", vmr.Node())
|
||||
d.Set("name", config.Name)
|
||||
d.Set("desc", config.Description)
|
||||
@ -308,6 +314,11 @@ func resourceVmQemuRead(d *schema.ResourceData, meta interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceVmQemuImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
||||
err := resourceVmQemuRead(d, meta)
|
||||
return []*schema.ResourceData{d}, err
|
||||
}
|
||||
|
||||
func resourceVmQemuDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*providerConfiguration).Client
|
||||
vmId, _ := strconv.Atoi(path.Base(d.Id()))
|
||||
@ -320,10 +331,6 @@ func resourceVmQemuDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func resourceId(targetNode string, vmId int) string {
|
||||
return fmt.Sprintf("%s/qemu/%d", targetNode, vmId)
|
||||
}
|
||||
|
||||
func prepareDiskSize(client *pxapi.Client, vmr *pxapi.VmRef, disk_gb float64) error {
|
||||
clonedConfig, err := pxapi.NewConfigQemuFromApi(vmr, client)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user