Packet bare metal cloud hosting platform provider

This commit is contained in:
Aaron Welch 2015-05-31 15:58:14 +01:00
parent 5f129f1b9d
commit 07ad320960
13 changed files with 1038 additions and 0 deletions

View File

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

View File

@ -0,0 +1,18 @@
package packet
import (
"github.com/packethost/packngo"
)
const (
consumerToken = "aZ9GmqHTPtxevvFq9SK3Pi2yr9YCbRzduCSXF2SNem5sjB91mDq7Th3ZwTtRqMWZ"
)
type Config struct {
AuthToken string
}
// Client() returns a new client for accessing packet.
func (c *Config) Client() *packngo.Client {
return packngo.NewClient(consumerToken, c.AuthToken)
}

View File

@ -0,0 +1,36 @@
package packet
import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
// Provider returns a schema.Provider for Packet.
func Provider() terraform.ResourceProvider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"auth_token": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("PACKET_AUTH_TOKEN", nil),
Description: "The API auth key for API operations.",
},
},
ResourcesMap: map[string]*schema.Resource{
"packet_device": resourcePacketDevice(),
"packet_ssh_key": resourcePacketSSHKey(),
"packet_project": resourcePacketProject(),
},
ConfigureFunc: providerConfigure,
}
}
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
config := Config{
AuthToken: d.Get("auth_token").(string),
}
return config.Client(), nil
}

View File

@ -0,0 +1,35 @@
package packet
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{
"packet": testAccProvider,
}
}
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 testAccPreCheck(t *testing.T) {
if v := os.Getenv("PACKET_AUTH_TOKEN"); v == "" {
t.Fatal("PACKET_AUTH_TOKEN must be set for acceptance tests")
}
}

View File

@ -0,0 +1,302 @@
package packet
import (
"fmt"
"log"
"time"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/packethost/packngo"
)
func resourcePacketDevice() *schema.Resource {
return &schema.Resource{
Create: resourcePacketDeviceCreate,
Read: resourcePacketDeviceRead,
Update: resourcePacketDeviceUpdate,
Delete: resourcePacketDeviceDelete,
Schema: map[string]*schema.Schema{
"project_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"hostname": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"operating_system": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"facility": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"plan": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"billing_cycle": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"state": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"locked": &schema.Schema{
Type: schema.TypeBool,
Computed: true,
},
"network": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"address": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"gateway": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"family": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
},
"cidr": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
},
"public": &schema.Schema{
Type: schema.TypeBool,
Computed: true,
},
},
},
},
"created": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"updated": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"user_data": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"tags": &schema.Schema{
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}
func resourcePacketDeviceCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
createRequest := &packngo.DeviceCreateRequest{
HostName: d.Get("hostname").(string),
Plan: d.Get("plan").(string),
Facility: d.Get("facility").(string),
OS: d.Get("operating_system").(string),
BillingCycle: d.Get("billing_cycle").(string),
ProjectID: d.Get("project_id").(string),
}
if attr, ok := d.GetOk("user_data"); ok {
createRequest.UserData = attr.(string)
}
tags := d.Get("tags.#").(int)
if tags > 0 {
createRequest.Tags = make([]string, 0, tags)
for i := 0; i < tags; i++ {
key := fmt.Sprintf("tags.%d", i)
createRequest.Tags = append(createRequest.Tags, d.Get(key).(string))
}
}
log.Printf("[DEBUG] Device create configuration: %#v", createRequest)
newDevice, _, err := client.Devices.Create(createRequest)
if err != nil {
return fmt.Errorf("Error creating device: %s", err)
}
// Assign the device id
d.SetId(newDevice.ID)
log.Printf("[INFO] Device ID: %s", d.Id())
_, err = WaitForDeviceAttribute(d, "active", []string{"provisioning"}, "state", meta)
if err != nil {
return fmt.Errorf(
"Error waiting for device (%s) to become ready: %s", d.Id(), err)
}
return resourcePacketDeviceRead(d, meta)
}
func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
// Retrieve the device properties for updating the state
device, _, err := client.Devices.Get(d.Id())
if err != nil {
return fmt.Errorf("Error retrieving device: %s", err)
}
d.Set("name", device.Hostname)
d.Set("plan", device.Plan.Slug)
d.Set("facility", device.Facility.Code)
d.Set("operating_system", device.OS.Slug)
d.Set("state", device.State)
d.Set("billing_cycle", device.BillingCycle)
d.Set("locked", device.Locked)
d.Set("created", device.Created)
d.Set("udpated", device.Updated)
tags := make([]string, 0)
for _, tag := range device.Tags {
tags = append(tags, tag)
}
d.Set("tags", tags)
networks := make([]map[string]interface{}, 0, 1)
for _, ip := range device.Network {
network := make(map[string]interface{})
network["address"] = ip.Address
network["gateway"] = ip.Gateway
network["family"] = ip.Family
network["cidr"] = ip.Cidr
network["public"] = ip.Public
networks = append(networks, network)
}
d.Set("network", networks)
return nil
}
func resourcePacketDeviceUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
if d.HasChange("locked") && d.Get("locked").(bool) {
_, err := client.Devices.Lock(d.Id())
if err != nil {
return fmt.Errorf(
"Error locking device (%s): %s", d.Id(), err)
}
} else if d.HasChange("locked") {
_, err := client.Devices.Unlock(d.Id())
if err != nil {
return fmt.Errorf(
"Error unlocking device (%s): %s", d.Id(), err)
}
}
return resourcePacketDeviceRead(d, meta)
}
func resourcePacketDeviceDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
log.Printf("[INFO] Deleting device: %s", d.Id())
if _, err := client.Devices.Delete(d.Id()); err != nil {
return fmt.Errorf("Error deleting device: %s", err)
}
return nil
}
func WaitForDeviceAttribute(
d *schema.ResourceData, target string, pending []string, attribute string, meta interface{}) (interface{}, error) {
// Wait for the device so we can get the networking attributes
// that show up after a while
log.Printf(
"[INFO] Waiting for device (%s) to have %s of %s",
d.Id(), attribute, target)
stateConf := &resource.StateChangeConf{
Pending: pending,
Target: target,
Refresh: newDeviceStateRefreshFunc(d, attribute, meta),
Timeout: 60 * time.Minute,
Delay: 10 * time.Second,
MinTimeout: 3 * time.Second,
}
return stateConf.WaitForState()
}
func newDeviceStateRefreshFunc(
d *schema.ResourceData, attribute string, meta interface{}) resource.StateRefreshFunc {
client := meta.(*packngo.Client)
return func() (interface{}, string, error) {
err := resourcePacketDeviceRead(d, meta)
if err != nil {
return nil, "", err
}
// See if we can access our attribute
if attr, ok := d.GetOk(attribute); ok {
// Retrieve the device properties
device, _, err := client.Devices.Get(d.Id())
if err != nil {
return nil, "", fmt.Errorf("Error retrieving device: %s", err)
}
return &device, attr.(string), nil
}
return nil, "", nil
}
}
// Powers on the device and waits for it to be active
func powerOnAndWait(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
_, err := client.Devices.PowerOn(d.Id())
if err != nil {
return err
}
// Wait for power on
_, err = WaitForDeviceAttribute(d, "active", []string{"off"}, "state", client)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,123 @@
package packet
import (
"fmt"
"log"
"strings"
"github.com/hashicorp/terraform/helper/schema"
"github.com/packethost/packngo"
)
func resourcePacketProject() *schema.Resource {
return &schema.Resource{
Create: resourcePacketProjectCreate,
Read: resourcePacketProjectRead,
Update: resourcePacketProjectUpdate,
Delete: resourcePacketProjectDelete,
Schema: map[string]*schema.Schema{
"id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"payment_method": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"created": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"updated": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourcePacketProjectCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
createRequest := &packngo.ProjectCreateRequest{
Name: d.Get("name").(string),
PaymentMethod: d.Get("payment_method").(string),
}
log.Printf("[DEBUG] Project create configuration: %#v", createRequest)
project, _, err := client.Projects.Create(createRequest)
if err != nil {
return fmt.Errorf("Error creating Project: %s", err)
}
d.SetId(project.ID)
log.Printf("[INFO] Project created: %s", project.ID)
return resourcePacketProjectRead(d, meta)
}
func resourcePacketProjectRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
key, _, err := client.Projects.Get(d.Id())
if err != nil {
// If the project somehow already destroyed, mark as
// succesfully gone
if strings.Contains(err.Error(), "404") {
d.SetId("")
return nil
}
return fmt.Errorf("Error retrieving Project: %s", err)
}
d.Set("id", key.ID)
d.Set("name", key.Name)
d.Set("created", key.Created)
d.Set("updated", key.Updated)
return nil
}
func resourcePacketProjectUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
updateRequest := &packngo.ProjectUpdateRequest{
ID: d.Get("id").(string),
Name: d.Get("name").(string),
}
if attr, ok := d.GetOk("payment_method"); ok {
updateRequest.PaymentMethod = attr.(string)
}
log.Printf("[DEBUG] Project update: %#v", d.Get("id"))
_, _, err := client.Projects.Update(updateRequest)
if err != nil {
return fmt.Errorf("Failed to update Project: %s", err)
}
return resourcePacketProjectRead(d, meta)
}
func resourcePacketProjectDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
log.Printf("[INFO] Deleting Project: %s", d.Id())
_, err := client.Projects.Delete(d.Id())
if err != nil {
return fmt.Errorf("Error deleting SSH key: %s", err)
}
d.SetId("")
return nil
}

View File

@ -0,0 +1,95 @@
package packet
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/packethost/packngo"
)
func TestAccPacketProject_Basic(t *testing.T) {
var project packngo.Project
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPacketProjectDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckPacketProjectConfig_basic,
Check: resource.ComposeTestCheckFunc(
testAccCheckPacketProjectExists("packet_project.foobar", &project),
testAccCheckPacketProjectAttributes(&project),
resource.TestCheckResourceAttr(
"packet_project.foobar", "name", "foobar"),
),
},
},
})
}
func testAccCheckPacketProjectDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*packngo.Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "packet_project" {
continue
}
_, _, err := client.Projects.Get(rs.Primary.ID)
if err == nil {
fmt.Errorf("Project cstill exists")
}
}
return nil
}
func testAccCheckPacketProjectAttributes(project *packngo.Project) resource.TestCheckFunc {
return func(s *terraform.State) error {
if project.Name != "foobar" {
return fmt.Errorf("Bad name: %s", project.Name)
}
return nil
}
}
func testAccCheckPacketProjectExists(n string, project *packngo.Project) 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 Record ID is set")
}
client := testAccProvider.Meta().(*packngo.Client)
foundProject, _, err := client.Projects.Get(rs.Primary.ID)
if err != nil {
return err
}
if foundProject.ID != rs.Primary.ID {
return fmt.Errorf("Record not found: %v - %v", rs.Primary.ID, foundProject)
}
*project = *foundProject
return nil
}
}
var testAccCheckPacketProjectConfig_basic = fmt.Sprintf(`
resource "packet_project" "foobar" {
name = "foobar"
}`)

View File

@ -0,0 +1,128 @@
package packet
import (
"fmt"
"log"
"strings"
"github.com/hashicorp/terraform/helper/schema"
"github.com/packethost/packngo"
)
func resourcePacketSSHKey() *schema.Resource {
return &schema.Resource{
Create: resourcePacketSSHKeyCreate,
Read: resourcePacketSSHKeyRead,
Update: resourcePacketSSHKeyUpdate,
Delete: resourcePacketSSHKeyDelete,
Schema: map[string]*schema.Schema{
"id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"public_key": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"fingerprint": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"created": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"updated": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourcePacketSSHKeyCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
createRequest := &packngo.SSHKeyCreateRequest{
Label: d.Get("name").(string),
Key: d.Get("public_key").(string),
}
log.Printf("[DEBUG] SSH Key create configuration: %#v", createRequest)
key, _, err := client.SSHKeys.Create(createRequest)
if err != nil {
return fmt.Errorf("Error creating SSH Key: %s", err)
}
d.SetId(key.ID)
log.Printf("[INFO] SSH Key: %s", key.ID)
return resourcePacketSSHKeyRead(d, meta)
}
func resourcePacketSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
key, _, err := client.SSHKeys.Get(d.Id())
if err != nil {
// If the key is somehow already destroyed, mark as
// succesfully gone
if strings.Contains(err.Error(), "404") {
d.SetId("")
return nil
}
return fmt.Errorf("Error retrieving SSH key: %s", err)
}
d.Set("id", key.ID)
d.Set("name", key.Label)
d.Set("public_key", key.Key)
d.Set("fingerprint", key.FingerPrint)
d.Set("created", key.Created)
d.Set("updated", key.Updated)
return nil
}
func resourcePacketSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
updateRequest := &packngo.SSHKeyUpdateRequest{
ID: d.Get("id").(string),
Label: d.Get("name").(string),
Key: d.Get("public_key").(string),
}
log.Printf("[DEBUG] SSH key update: %#v", d.Get("id"))
_, _, err := client.SSHKeys.Update(updateRequest)
if err != nil {
return fmt.Errorf("Failed to update SSH key: %s", err)
}
return resourcePacketSSHKeyRead(d, meta)
}
func resourcePacketSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*packngo.Client)
log.Printf("[INFO] Deleting SSH key: %s", d.Id())
_, err := client.SSHKeys.Delete(d.Id())
if err != nil {
return fmt.Errorf("Error deleting SSH key: %s", err)
}
d.SetId("")
return nil
}

View File

@ -0,0 +1,104 @@
package packet
import (
"fmt"
"strings"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/packethost/packngo"
)
func TestAccPacketSSHKey_Basic(t *testing.T) {
var key packngo.SSHKey
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckPacketSSHKeyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccCheckPacketSSHKeyConfig_basic,
Check: resource.ComposeTestCheckFunc(
testAccCheckPacketSSHKeyExists("packet_ssh_key.foobar", &key),
testAccCheckPacketSSHKeyAttributes(&key),
resource.TestCheckResourceAttr(
"packet_ssh_key.foobar", "name", "foobar"),
resource.TestCheckResourceAttr(
"packet_ssh_key.foobar", "public_key", testAccValidPublicKey),
),
},
},
})
}
func testAccCheckPacketSSHKeyDestroy(s *terraform.State) error {
client := testAccProvider.Meta().(*packngo.Client)
for _, rs := range s.RootModule().Resources {
if rs.Type != "packet_ssh_key" {
continue
}
_, _, err := client.SSHKeys.Get(rs.Primary.ID)
if err == nil {
fmt.Errorf("SSH key still exists")
}
}
return nil
}
func testAccCheckPacketSSHKeyAttributes(key *packngo.SSHKey) resource.TestCheckFunc {
return func(s *terraform.State) error {
if key.Label != "foobar" {
return fmt.Errorf("Bad name: %s", key.Label)
}
return nil
}
}
func testAccCheckPacketSSHKeyExists(n string, key *packngo.SSHKey) 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 Record ID is set")
}
client := testAccProvider.Meta().(*packngo.Client)
foundKey, _, err := client.SSHKeys.Get(rs.Primary.ID)
if err != nil {
return err
}
if foundKey.ID != rs.Primary.ID {
return fmt.Errorf("SSh Key not found: %v - %v", rs.Primary.ID, foundKey)
}
*key = *foundKey
fmt.Printf("key: %v", key)
return nil
}
}
var testAccCheckPacketSSHKeyConfig_basic = fmt.Sprintf(`
resource "packet_ssh_key" "foobar" {
name = "foobar"
public_key = "%s"
}`, testAccValidPublicKey)
var testAccValidPublicKey = strings.TrimSpace(`
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCKVmnMOlHKcZK8tpt3MP1lqOLAcqcJzhsvJcjscgVERRN7/9484SOBJ3HSKxxNG5JN8owAjy5f9yYwcUg+JaUVuytn5Pv3aeYROHGGg+5G346xaq3DAwX6Y5ykr2fvjObgncQBnuU5KHWCECO/4h8uWuwh/kfniXPVjFToc+gnkqA+3RKpAecZhFXwfalQ9mMuYGFxn+fwn8cYEApsJbsEmb0iJwPiZ5hjFC8wREuiTlhPHDgkBLOiycd20op2nXzDbHfCHInquEe/gYxEitALONxm0swBOwJZwlTDOB7C6y2dzlrtxr1L59m7pCkWI4EtTRLvleehBoj3u7jB4usR
`)

View File

@ -0,0 +1,47 @@
---
layout: "packet"
page_title: "Provider: Packet"
sidebar_current: "docs-packet-index"
description: |-
The Packet provider is used to interact with the resources supported by Packet. The provider needs to be configured with the proper credentials before it can be used.
---
# Packet Provider
The Packet provider is used to interact with the resources supported by Packet.
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 Packet Provider
provider "packet" {
auth_token = "${var.auth_token}"
}
# Create a project
resource "packet_project" "tf_project_1" {
name = "My First Terraform Project"
payment_method = "PAYMENT_METHOD_ID"
}
# Create a device and add it to tf_project_1
resource "packet_device" "web1" {
hostname = "tf.coreos2"
plan = "baremetal_1"
facility = "ewr1"
operating_system = "coreos_stable"
billing_cycle = "hourly"
project_id = "${packet_project.tf_project_1.id}"
}
```
## Argument Reference
The following arguments are supported:
* `auth_token` - (Required) This is your Packet API Auth token. This can also be specified
with the `PACKET_AUTH_TOKEN` shell environment variable.

View File

@ -0,0 +1,55 @@
---
layout: "packet"
page_title: "Packet: packet_device"
sidebar_current: "docs-packet-resource-device"
description: |-
Provides a Packet device resource. This can be used to create, modify, and delete devices.
---
# packet\_device
Provides a Packet device resource. This can be used to create,
modify, and delete devices.
## Example Usage
```
# Create a device and add it to tf_project_1
resource "packet_device" "web1" {
hostname = "tf.coreos2"
plan = "baremetal_1"
facility = "ewr1"
operating_system = "coreos_stable"
billing_cycle = "hourly"
project_id = "${packet_project.tf_project_1.id}"
}
```
## Argument Reference
The following arguments are supported:
* `hostname` - (Required) The device name
* `project_id` - (Required) The id of the project in which to create the device
* `operating_system` - (Required) The operating system slug
* `facility` - (Required) The facility in which to create the device
* `plan` - (Required) The config type slug
* `billing_cycle` - (Required) monthly or hourly
* `user_data` (Optional) - A string of the desired User Data for the device.
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the device
* `hostname`- The hostname of the device
* `project_id`- The Id of the project the device belonds to
* `facility` - The facility the device is in
* `plan` - The config type of the device
* `network` - The private and public v4 and v6 IPs assigned to the device
* `locked` - Is the device locked
* `billing_cycle` - The billing cycle of the device (monthly or hourly)
* `operating_system` - The operating system running on the device
* `status` - The status of the device
* `created` - The timestamp for when the device was created
* `updated` - The timestamp for the last time the device was udpated

View File

@ -0,0 +1,40 @@
---
layout: "packet"
page_title: "Packet: packet_ssh_key"
sidebar_current: "docs-packet-resource-project"
description: |-
Provides a Packet Project resource.
---
# packet\_project
Provides a Packet Project resource to allow you manage devices
in your projects.
## Example Usage
```
# Create a new Project
resource "packet_project" "tf_project_1" {
name = "Terraform Fun"
payment_method = "payment-method-id"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name of the SSH key for identification
* `payment_method` - (Required) The id of the payment method on file to use for services created
on this project.
## Attributes Reference
The following attributes are exported:
* `id` - The unique ID of the key
* `payment_method` - The id of the payment method on file to use for services created
on this project.
* `created` - The timestamp for when the SSH key was created
* `updated` - The timestamp for the last time the SSH key was udpated

View File

@ -0,0 +1,43 @@
---
layout: "packet"
page_title: "Packet: packet_ssh_key"
sidebar_current: "docs-packet-resource-ssh-key"
description: |-
Provides a Packet SSH key resource.
---
# packet\_ssh_key
Provides a Packet SSH key resource to allow you manage SSH
keys on your account. All ssh keys on your account are loaded on
all new devices, they do not have to be explicitly declared on
device creation.
## Example Usage
```
# Create a new SSH key
resource "packet_ssh_key" "key1" {
name = "terraform-1"
public_key = "${file("/home/terraform/.ssh/id_rsa.pub")}"
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name of the SSH key for identification
* `public_key` - (Required) The public key. If this is a file, it
can be read using the file interpolation function
## Attributes Reference
The following attributes are exported:
* `id` - The unique ID of the key
* `name` - The name of the SSH key
* `public_key` - The text of the public key
* `fingerprint` - The fingerprint of the SSH key
* `created` - The timestamp for when the SSH key was created
* `updated` - The timestamp for the last time the SSH key was udpated