Initial Oracle Compute Cloud provider
This commit is contained in:
parent
3c296dc5d0
commit
c5d1f8f88f
|
@ -0,0 +1,47 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
User string
|
||||
Password string
|
||||
IdentityDomain string
|
||||
Endpoint string
|
||||
MaxRetryTimeout int
|
||||
}
|
||||
|
||||
type storageAttachment struct {
|
||||
index int
|
||||
instanceName *compute.InstanceName
|
||||
}
|
||||
|
||||
type OPCClient struct {
|
||||
*compute.AuthenticatedClient
|
||||
MaxRetryTimeout int
|
||||
storageAttachmentsByVolumeCache map[string][]storageAttachment
|
||||
}
|
||||
|
||||
func (c *Config) Client() (*OPCClient, error) {
|
||||
u, err := url.ParseRequestURI(c.Endpoint)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Invalid endpoint URI: %s", err)
|
||||
}
|
||||
|
||||
client := compute.NewComputeClient(c.IdentityDomain, c.User, c.Password, u)
|
||||
authenticatedClient, err := client.Authenticate()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Authentication failed: %s", err)
|
||||
}
|
||||
|
||||
opcClient := &OPCClient{
|
||||
AuthenticatedClient: authenticatedClient,
|
||||
MaxRetryTimeout: c.MaxRetryTimeout,
|
||||
storageAttachmentsByVolumeCache: make(map[string][]storageAttachment),
|
||||
}
|
||||
|
||||
return opcClient, nil
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
// Provider returns a terraform.ResourceProvider.
|
||||
func Provider() terraform.ResourceProvider {
|
||||
return &schema.Provider{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"user": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("OPC_USERNAME", nil),
|
||||
Description: "The user name for OPC API operations.",
|
||||
},
|
||||
|
||||
"password": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("OPC_PASSWORD", nil),
|
||||
Description: "The user password for OPC API operations.",
|
||||
},
|
||||
|
||||
"identityDomain": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("OPC_IDENTITY_DOMAIN", nil),
|
||||
Description: "The OPC identity domain for API operations",
|
||||
},
|
||||
|
||||
"endpoint": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("OPC_ENDPOINT", nil),
|
||||
Description: "The HTTP endpoint for OPC API operations.",
|
||||
},
|
||||
|
||||
"maxRetryTimeout": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("OPC_MAX_RETRY_TIMEOUT", 3000),
|
||||
Description: "Max num seconds to wait for successful response when operating on resources within OPC (defaults to 3000)",
|
||||
},
|
||||
},
|
||||
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"opc_compute_storage_volume": resourceStorageVolume(),
|
||||
"opc_compute_instance": resourceInstance(),
|
||||
"opc_compute_ssh_key": resourceSSHKey(),
|
||||
"opc_compute_security_application": resourceSecurityApplication(),
|
||||
"opc_compute_security_list": resourceSecurityList(),
|
||||
"opc_compute_security_ip_list": resourceSecurityIPList(),
|
||||
"opc_compute_ip_reservation": resourceIPReservation(),
|
||||
"opc_compute_ip_association": resourceIPAssociation(),
|
||||
"opc_compute_security_rule": resourceSecurityRule(),
|
||||
"opc_compute_security_association": resourceSecurityAssociation(),
|
||||
},
|
||||
|
||||
ConfigureFunc: providerConfigure,
|
||||
}
|
||||
}
|
||||
|
||||
func providerConfigure(d *schema.ResourceData) (interface{}, error) {
|
||||
config := Config{
|
||||
User: d.Get("user").(string),
|
||||
Password: d.Get("password").(string),
|
||||
IdentityDomain: d.Get("identityDomain").(string),
|
||||
Endpoint: d.Get("endpoint").(string),
|
||||
MaxRetryTimeout: d.Get("maxRetryTimeout").(int),
|
||||
}
|
||||
|
||||
return config.Client()
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"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{
|
||||
"opc": 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) {
|
||||
required := []string{"OPC_USERNAME", "OPC_PASSWORD", "OPC_IDENTITY_DOMAIN", "OPC_ENDPOINT"}
|
||||
for _, prop := range required {
|
||||
if os.Getenv(prop) == "" {
|
||||
t.Fatalf("%s must be set for acceptance test", prop)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type OPCResourceState struct {
|
||||
*OPCClient
|
||||
*terraform.InstanceState
|
||||
}
|
||||
|
||||
func opcResourceCheck(resourceName string, f func(checker *OPCResourceState) error) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[resourceName]
|
||||
if !ok {
|
||||
return fmt.Errorf("Resource not found: %s", resourceName)
|
||||
}
|
||||
|
||||
state := &OPCResourceState{
|
||||
OPCClient: testAccProvider.Meta().(*OPCClient),
|
||||
InstanceState: rs.Primary,
|
||||
}
|
||||
|
||||
return f(state)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceInstance() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceInstanceCreate,
|
||||
Read: resourceInstanceRead,
|
||||
Delete: resourceInstanceDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"shape": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"imageList": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"label": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"ip": {
|
||||
Type: schema.TypeString,
|
||||
Optional: false,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"opcId": {
|
||||
Type: schema.TypeString,
|
||||
Optional: false,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"sshKeys": {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
|
||||
"attributes": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"vcable": {
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"storage": {
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"index": {
|
||||
Type: schema.TypeInt,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"volume": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"name": {
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"bootOrder": {
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeInt},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getAttrs(d *schema.ResourceData) (*map[string]interface{}, error) {
|
||||
var attrs map[string]interface{}
|
||||
|
||||
attrString := d.Get("attributes").(string)
|
||||
if attrString == "" {
|
||||
return &attrs, nil
|
||||
}
|
||||
if err := json.Unmarshal([]byte(attrString), &attrs); err != nil {
|
||||
return &attrs, fmt.Errorf("Cannot parse '%s' as json", attrString)
|
||||
}
|
||||
return &attrs, nil
|
||||
}
|
||||
|
||||
func resourceInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d.State())
|
||||
|
||||
client := meta.(*OPCClient).Instances()
|
||||
name := d.Get("name").(string)
|
||||
shape := d.Get("shape").(string)
|
||||
imageList := d.Get("imageList").(string)
|
||||
label := d.Get("label").(string)
|
||||
storage := getStorageAttachments(d)
|
||||
sshKeys := getSSHKeys(d)
|
||||
bootOrder := getBootOrder(d)
|
||||
|
||||
attrs, err := getAttrs(d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Creating instance with name %s, shape %s, imageList %s, storage %s, bootOrder %s, label %s, sshKeys %s, attrs %#v",
|
||||
name, shape, imageList, storage, bootOrder, label, sshKeys, attrs)
|
||||
|
||||
id, err := client.LaunchInstance(name, label, shape, imageList, storage, bootOrder, sshKeys, *attrs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating instance %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for instance %s to come online", id.String())
|
||||
info, err := client.WaitForInstanceRunning(id, meta.(*OPCClient).MaxRetryTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error waiting for instance %s to come online: %s", id, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Created instance %s: %#v", id, info)
|
||||
|
||||
attachStorage(
|
||||
&compute.InstanceName{
|
||||
Name: info.Name,
|
||||
ID: info.ID,
|
||||
},
|
||||
d, meta)
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateInstanceResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func attachStorage(name *compute.InstanceName, d *schema.ResourceData, meta interface{}) error {
|
||||
storageClient := meta.(*OPCClient).StorageAttachments()
|
||||
storage := d.Get("storage").(*schema.Set)
|
||||
updatedStorage := schema.NewSet(storage.F, []interface{}{})
|
||||
|
||||
for _, i := range storage.List() {
|
||||
attrs := i.(map[string]interface{})
|
||||
attachmentInfo, err := storageClient.CreateStorageAttachment(
|
||||
attrs["index"].(int),
|
||||
name,
|
||||
attrs["volume"].(string))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for storage attachment %#v to come online", attachmentInfo)
|
||||
storageClient.WaitForStorageAttachmentCreated(attachmentInfo.Name, meta.(*OPCClient).MaxRetryTimeout)
|
||||
log.Printf("[DEBUG] Storage attachment %s: %s-%s created",
|
||||
attachmentInfo.Name, attachmentInfo.InstanceName, attachmentInfo.StorageVolumeName)
|
||||
attrs["name"] = attachmentInfo.Name
|
||||
updatedStorage.Add(attrs)
|
||||
}
|
||||
|
||||
d.Set("storage", updatedStorage)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSSHKeys(d *schema.ResourceData) []string {
|
||||
sshKeys := []string{}
|
||||
for _, i := range d.Get("sshKeys").([]interface{}) {
|
||||
sshKeys = append(sshKeys, i.(string))
|
||||
}
|
||||
return sshKeys
|
||||
}
|
||||
|
||||
func getBootOrder(d *schema.ResourceData) []int {
|
||||
bootOrder := []int{}
|
||||
for _, i := range d.Get("bootOrder").([]interface{}) {
|
||||
bootOrder = append(bootOrder, i.(int))
|
||||
}
|
||||
return bootOrder
|
||||
}
|
||||
|
||||
func getStorageAttachments(d *schema.ResourceData) []compute.LaunchPlanStorageAttachmentSpec {
|
||||
storageAttachments := []compute.LaunchPlanStorageAttachmentSpec{}
|
||||
storage := d.Get("storage").(*schema.Set)
|
||||
for _, i := range storage.List() {
|
||||
attrs := i.(map[string]interface{})
|
||||
storageAttachments = append(storageAttachments, compute.LaunchPlanStorageAttachmentSpec{
|
||||
Index: attrs["index"].(int),
|
||||
Volume: attrs["volume"].(string),
|
||||
})
|
||||
}
|
||||
return storageAttachments
|
||||
}
|
||||
|
||||
func updateInstanceResourceData(d *schema.ResourceData, info *compute.InstanceInfo) error {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("opcId", info.ID)
|
||||
d.Set("imageList", info.ImageList)
|
||||
d.Set("bootOrder", info.BootOrder)
|
||||
d.Set("sshKeys", info.SSHKeys)
|
||||
d.Set("label", info.Label)
|
||||
d.Set("ip", info.IPAddress)
|
||||
d.Set("vcable", info.VCableID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceInstanceRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d.State())
|
||||
client := meta.(*OPCClient).Instances()
|
||||
name := d.Get("name").(string)
|
||||
instanceName := &compute.InstanceName{
|
||||
Name: name,
|
||||
ID: d.Get("opcId").(string),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Reading state of instance %s", instanceName)
|
||||
result, err := client.GetInstance(instanceName)
|
||||
if err != nil {
|
||||
// Instance doesn't exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
log.Printf("[DEBUG] Instance %s not found", instanceName)
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading instance %s: %s", instanceName, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of instance %s: %#v", instanceName, result)
|
||||
|
||||
attachments, err := meta.(*OPCClient).StorageAttachments().GetStorageAttachmentsForInstance(instanceName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error reading storage attachments for instance %s: %s", instanceName, err)
|
||||
}
|
||||
updateInstanceResourceData(d, result)
|
||||
updateAttachmentResourceData(d, attachments)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateAttachmentResourceData(d *schema.ResourceData, attachments *[]compute.StorageAttachmentInfo) {
|
||||
attachmentSet := schema.NewSet(d.Get("storage").(*schema.Set).F, []interface{}{})
|
||||
for _, attachment := range *attachments {
|
||||
properties := map[string]interface{}{
|
||||
"index": attachment.Index,
|
||||
"volume": attachment.StorageVolumeName,
|
||||
"name": attachment.Name,
|
||||
}
|
||||
attachmentSet.Add(properties)
|
||||
}
|
||||
d.Set("storage", attachmentSet)
|
||||
}
|
||||
|
||||
func resourceInstanceDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d.State())
|
||||
client := meta.(*OPCClient).Instances()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
instanceName := &compute.InstanceName{
|
||||
Name: name,
|
||||
ID: d.Get("opcId").(string),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Deleting instance %s", instanceName)
|
||||
if err := client.DeleteInstance(instanceName); err != nil {
|
||||
return fmt.Errorf("Error deleting instance %s: %s", instanceName, err)
|
||||
}
|
||||
if err := client.WaitForInstanceDeleted(instanceName, meta.(*OPCClient).MaxRetryTimeout); err != nil {
|
||||
return fmt.Errorf("Error deleting instance %s: %s", instanceName, err)
|
||||
}
|
||||
|
||||
for _, attachment := range d.Get("storage").(*schema.Set).List() {
|
||||
name := attachment.(map[string]interface{})["name"].(string)
|
||||
log.Printf("[DEBUG] Deleting storage attachment %s", name)
|
||||
client.StorageAttachments().DeleteStorageAttachment(name)
|
||||
client.StorageAttachments().WaitForStorageAttachmentDeleted(name, meta.(*OPCClient).MaxRetryTimeout)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccOPCInstance_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: opcResourceCheck(
|
||||
instanceResourceName,
|
||||
testAccCheckInstanceDestroyed),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccInstanceBasic,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
opcResourceCheck(
|
||||
instanceResourceName,
|
||||
testAccCheckInstanceExists),
|
||||
opcResourceCheck(
|
||||
keyResourceName,
|
||||
testAccCheckSSHKeyExists),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: modifySSHKey,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
opcResourceCheck(
|
||||
instanceResourceName,
|
||||
testAccCheckInstanceExists),
|
||||
opcResourceCheck(
|
||||
keyResourceName,
|
||||
testAccCheckSSHKeyUpdated),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckInstanceExists(state *OPCResourceState) error {
|
||||
instanceName := getInstanceName(state)
|
||||
|
||||
if _, err := state.Instances().GetInstance(instanceName); err != nil {
|
||||
return fmt.Errorf("Error retrieving state of instance %s: %s", instanceName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckSSHKeyExists(state *OPCResourceState) error {
|
||||
keyName := state.Attributes["name"]
|
||||
|
||||
if _, err := state.SSHKeys().GetSSHKey(keyName); err != nil {
|
||||
return fmt.Errorf("Error retrieving state of key %s: %s", keyName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckSSHKeyUpdated(state *OPCResourceState) error {
|
||||
keyName := state.Attributes["name"]
|
||||
info, err := state.SSHKeys().GetSSHKey(keyName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.Key != updatedKey {
|
||||
return fmt.Errorf("Expected key\n\t%s\nbut was\n\t%s", updatedKey, info.Key)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getInstanceName(rs *OPCResourceState) *compute.InstanceName {
|
||||
return &compute.InstanceName{
|
||||
Name: rs.Attributes["name"],
|
||||
ID: rs.Attributes["opcId"],
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckInstanceDestroyed(state *OPCResourceState) error {
|
||||
instanceName := getInstanceName(state)
|
||||
if info, err := state.Instances().GetInstance(instanceName); err == nil {
|
||||
return fmt.Errorf("Instance %s still exists: %#v", instanceName, info)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const instanceName = "test_instance"
|
||||
const keyName = "test_key"
|
||||
|
||||
var instanceResourceName = fmt.Sprintf("opc_compute_instance.%s", instanceName)
|
||||
var keyResourceName = fmt.Sprintf("opc_compute_ssh_key.%s", keyName)
|
||||
|
||||
const originalKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqw6JwbjIkZEr5UcMojtxhk6Zum39NOihHNXEvRWDt5WssX8TH/ghpv3D25K1pJkf+wfAi17HwEmYwPMEyEHENS443v6RZbXvzCkUWzkJzq7Zvbdqld038km31La2QUoMMp1KL5zk1nM65xCeQDVcR/h++03EScB2CuzTpAV6khMdfgOJgxm361kfrDVRwc1HQrAOpOnzkpPfwqBrYWqN1UnKvuO77Wk8z5LBe03EPNru3bLE3s3qHI9hjO0gXMiVUi0KyNxdWfDO8esqQlKavHAeePyrRA55YF8kBB5dEl4tVNOqpY/8TRnGN1mOe0LWxa8Ytz1wbyS49knsNVTel"
|
||||
const updatedKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHvb/2OSemgzUYLNW1/T3u33r7sZy1qbWtgVWiREH4gS5TVmDVPuvN1MFLdNqiWQA53gK8Gp24jtjNm9ftcPhicv81HVWJTB69C0sJGEfF0l4mgbemJLH3i37Mb6SdWJcGof9qHVDADPgiC8jIBVUhdiJSeq4fUJ3NQA2eUExBkRglQWairkNzPNA0mi3GL9KDGnoBnSCAXNGoKgDgIOqW0dYFP6oHyGWkF7V+/TME9aIQvmMpHjVzl7brZ/wED2t5vTJxxbgogHEmWnfs7p8EP5IsN6Vnjd0VNIt1tu3TduS8kH5npkPqZz8oIP93Ypxn0l7ZNEl9MahbhPj3gJ1YY7Cygrlt1VLC1ibBbOgIS2Lj6vGG/Yjkqs3Vw6qrmTRlsJ9c6bZO2xq0xzV11XQHvjPegBOClF6AztEe1jKU/RUFnzjIF8lUmM63fTaXuVkNERkTSE3E9XL3Uq6eqYdef7wHFFhCMSGotp3ANAb30kflysA9ID0b3o5QU2tB8OBxBicXQy11lh+u204YJuvIzeTXo+JAad5TWFlJcsUlbPFppLQdhUpoWaJouBGJV36DJb9R34i9T8Ze5tnJUQgPmMkERyPvb/+v5j3s2hs1A9WO6/MqmZd70gudsX/1bqWT898vCCOdM+CspNVY7nHVUtde7C6BrHzphr/C1YBXHw=="
|
||||
|
||||
var testAccInstanceBasic = fmt.Sprintf(`
|
||||
resource "opc_compute_instance" "%s" {
|
||||
name = "test"
|
||||
label = "test"
|
||||
shape = "oc3"
|
||||
imageList = "/oracle/public/oel_6.4_2GB_v1"
|
||||
sshKeys = ["${opc_compute_ssh_key.test_key.name}"]
|
||||
attributes = "{\"foo\": \"bar\"}"
|
||||
storage = {
|
||||
index = 1
|
||||
volume = "${opc_compute_storage_volume.test_volume.name}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "opc_compute_storage_volume" "test_volume" {
|
||||
size = "3g"
|
||||
description = "My volume"
|
||||
name = "test_volume_b"
|
||||
tags = ["foo", "bar", "baz"]
|
||||
}
|
||||
|
||||
resource "opc_compute_ssh_key" "%s" {
|
||||
name = "test-key"
|
||||
key = "%s"
|
||||
enabled = true
|
||||
}
|
||||
`, instanceName, keyName, originalKey)
|
||||
|
||||
var modifySSHKey = fmt.Sprintf(`
|
||||
resource "opc_compute_instance" "%s" {
|
||||
name = "test"
|
||||
label = "test"
|
||||
shape = "oc3"
|
||||
imageList = "/oracle/public/oel_6.4_2GB_v1"
|
||||
sshKeys = ["${opc_compute_ssh_key.test_key.name}"]
|
||||
attributes = "{\"foo\": \"bar\"}"
|
||||
storage = {
|
||||
index = 1
|
||||
volume = "${opc_compute_storage_volume.test_volume.name}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "opc_compute_storage_volume" "test_volume" {
|
||||
size = "3g"
|
||||
description = "My volume"
|
||||
name = "test_volume_b"
|
||||
tags = ["foo", "bar", "baz"]
|
||||
}
|
||||
|
||||
resource "opc_compute_ssh_key" "%s" {
|
||||
name = "test-key"
|
||||
key = "%s"
|
||||
enabled = true
|
||||
}
|
||||
`, instanceName, keyName, updatedKey)
|
|
@ -0,0 +1,103 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceIPAssociation() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceIPAssociationCreate,
|
||||
Read: resourceIPAssociationRead,
|
||||
Delete: resourceIPAssociationDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"vcable": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"parentpool": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceIPAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
vcable, parentpool := getIPAssociationResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating ip association between vcable %s and parent pool %s",
|
||||
vcable, parentpool)
|
||||
|
||||
client := meta.(*OPCClient).IPAssociations()
|
||||
info, err := client.CreateIPAssociation(vcable, parentpool)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating ip association between vcable %s and parent pool %s: %s",
|
||||
vcable, parentpool, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateIPAssociationResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateIPAssociationResourceData(d *schema.ResourceData, info *compute.IPAssociationInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("parentpool", info.ParentPool)
|
||||
d.Set("vcable", info.VCable)
|
||||
}
|
||||
|
||||
func resourceIPAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).IPAssociations()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of ip association %s", name)
|
||||
result, err := client.GetIPAssociation(name)
|
||||
if err != nil {
|
||||
// IP Association does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading ip association %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of ip association %s: %#v", name, result)
|
||||
updateIPAssociationResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIPAssociationResourceData(d *schema.ResourceData) (string, string) {
|
||||
return d.Get("vcable").(string), d.Get("parentpool").(string)
|
||||
}
|
||||
|
||||
func resourceIPAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).IPAssociations()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
vcable, parentpool := getIPAssociationResourceData(d)
|
||||
log.Printf("[DEBUG] Deleting ip association %s between vcable %s and parent pool %s",
|
||||
name, vcable, parentpool)
|
||||
|
||||
if err := client.DeleteIPAssociation(name); err != nil {
|
||||
return fmt.Errorf("Error deleting ip association %s between vcable %s and parent pool %s: %s",
|
||||
name, vcable, parentpool, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccOPCResourceIPAssociation_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: opcResourceCheck(
|
||||
ipAssociationResourceName,
|
||||
testAccCheckIPAssociationDestroyed),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccIPAssociationBasic,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
opcResourceCheck(
|
||||
ipAssociationResourceName,
|
||||
testAccCheckIPAssociationExists),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckIPAssociationExists(state *OPCResourceState) error {
|
||||
associationName := getIPAssociationName(state)
|
||||
|
||||
if _, err := state.IPAssociations().GetIPAssociation(associationName); err != nil {
|
||||
return fmt.Errorf("Error retrieving state of ip assocation %s: %s", associationName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIPAssociationName(rs *OPCResourceState) string {
|
||||
return rs.Attributes["name"]
|
||||
}
|
||||
|
||||
func testAccCheckIPAssociationDestroyed(state *OPCResourceState) error {
|
||||
associationName := getAssociationName(state)
|
||||
if info, err := state.IPAssociations().GetIPAssociation(associationName); err == nil {
|
||||
return fmt.Errorf("IP association %s still exists: %#v", associationName, info)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const ipAssociationName = "test_ip_association"
|
||||
|
||||
var ipAssociationResourceName = fmt.Sprintf("opc_compute_ip_association.%s", ipAssociationName)
|
||||
|
||||
var testAccIPAssociationBasic = fmt.Sprintf(`
|
||||
resource "opc_compute_ip_reservation" "reservation1" {
|
||||
parentpool = "/oracle/public/ippool"
|
||||
permanent = true
|
||||
}
|
||||
|
||||
resource "opc_compute_ip_association" "%s" {
|
||||
vcable = "${opc_compute_instance.test-instance1.vcable}"
|
||||
parentpool = "ipreservation:${opc_compute_ip_reservation.reservation1.name}"
|
||||
}
|
||||
|
||||
resource "opc_compute_instance" "test-instance1" {
|
||||
name = "test"
|
||||
label = "test"
|
||||
shape = "oc3"
|
||||
imageList = "/oracle/public/oel_6.4_2GB_v1"
|
||||
}
|
||||
`, ipAssociationName)
|
|
@ -0,0 +1,122 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceIPReservation() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceIPReservationCreate,
|
||||
Read: resourceIPReservationRead,
|
||||
Delete: resourceIPReservationDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"permanent": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"parentpool": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"tags": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
|
||||
"ip": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: false,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceIPReservationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
parentpool, permanent, tags := getIPReservationResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating ip reservation from parentpool %s with tags=%s",
|
||||
parentpool, tags)
|
||||
|
||||
client := meta.(*OPCClient).IPReservations()
|
||||
info, err := client.CreateIPReservation(parentpool, permanent, tags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating ip reservation from parentpool %s with tags=%s: %s",
|
||||
parentpool, tags, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateIPReservationResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateIPReservationResourceData(d *schema.ResourceData, info *compute.IPReservationInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("parentpool", info.ParentPool)
|
||||
d.Set("permanent", info.Permanent)
|
||||
d.Set("tags", info.Tags)
|
||||
d.Set("ip", info.IP)
|
||||
}
|
||||
|
||||
func resourceIPReservationRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).IPReservations()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of ip reservation %s", name)
|
||||
result, err := client.GetIPReservation(name)
|
||||
if err != nil {
|
||||
// IP Reservation does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading ip reservation %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of ip reservation %s: %#v", name, result)
|
||||
updateIPReservationResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIPReservationResourceData(d *schema.ResourceData) (string, bool, []string) {
|
||||
tagdata := d.Get("tags").([]interface{})
|
||||
tags := make([]string, len(tagdata))
|
||||
for i, tag := range tagdata {
|
||||
tags[i] = tag.(string)
|
||||
}
|
||||
return d.Get("parentpool").(string),
|
||||
d.Get("permanent").(bool),
|
||||
tags
|
||||
}
|
||||
|
||||
func resourceIPReservationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).IPReservations()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Deleting ip reservation %s", name)
|
||||
|
||||
if err := client.DeleteIPReservation(name); err != nil {
|
||||
return fmt.Errorf("Error deleting ip reservation %s", name)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceSecurityApplication() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceSecurityApplicationCreate,
|
||||
Read: resourceSecurityApplicationRead,
|
||||
Delete: resourceSecurityApplicationDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"protocol": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"dport": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"icmptype": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"icmpcode": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSecurityApplicationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
name, protocol, dport, icmptype, icmpcode, description := getSecurityApplicationResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating security application %s", name)
|
||||
|
||||
client := meta.(*OPCClient).SecurityApplications()
|
||||
info, err := client.CreateSecurityApplication(name, protocol, dport, icmptype, icmpcode, description)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating security application %s: %s", name, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateSecurityApplicationResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSecurityApplicationResourceData(d *schema.ResourceData, info *compute.SecurityApplicationInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("protocol", info.Protocol)
|
||||
d.Set("dport", info.DPort)
|
||||
d.Set("icmptype", info.ICMPType)
|
||||
d.Set("icmpcode", info.ICMPCode)
|
||||
d.Set("description", info.Description)
|
||||
}
|
||||
|
||||
func resourceSecurityApplicationRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityApplications()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of security application %s", name)
|
||||
result, err := client.GetSecurityApplication(name)
|
||||
if err != nil {
|
||||
// Security Application does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading security application %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of security application %s: %#v", name, result)
|
||||
updateSecurityApplicationResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSecurityApplicationResourceData(d *schema.ResourceData) (string, string, string, string, string, string) {
|
||||
return d.Get("name").(string),
|
||||
d.Get("protocol").(string),
|
||||
d.Get("dport").(string),
|
||||
d.Get("icmptype").(string),
|
||||
d.Get("icmpcode").(string),
|
||||
d.Get("description").(string)
|
||||
}
|
||||
|
||||
func resourceSecurityApplicationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityApplications()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Deleting security application %s", name)
|
||||
|
||||
if err := client.DeleteSecurityApplication(name); err != nil {
|
||||
return fmt.Errorf("Error deleting security application %s: %s", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceSecurityAssociation() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceSecurityAssociationCreate,
|
||||
Read: resourceSecurityAssociationRead,
|
||||
Delete: resourceSecurityAssociationDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"vcable": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"seclist": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSecurityAssociationCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
vcable, seclist := getSecurityAssociationResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating security association between vcable %s and security list %s",
|
||||
vcable, seclist)
|
||||
|
||||
client := meta.(*OPCClient).SecurityAssociations()
|
||||
info, err := client.CreateSecurityAssociation(vcable, seclist)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating security association between vcable %s and security list %s: %s",
|
||||
vcable, seclist, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateSecurityAssociationResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSecurityAssociationResourceData(d *schema.ResourceData, info *compute.SecurityAssociationInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("seclist", info.SecList)
|
||||
d.Set("vcable", info.VCable)
|
||||
}
|
||||
|
||||
func resourceSecurityAssociationRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityAssociations()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of security association %s", name)
|
||||
result, err := client.GetSecurityAssociation(name)
|
||||
if err != nil {
|
||||
// Security Association does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading security association %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of security association %s: %#v", name, result)
|
||||
updateSecurityAssociationResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSecurityAssociationResourceData(d *schema.ResourceData) (string, string) {
|
||||
return d.Get("vcable").(string), d.Get("seclist").(string)
|
||||
}
|
||||
|
||||
func resourceSecurityAssociationDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityAssociations()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
vcable, seclist := getSecurityAssociationResourceData(d)
|
||||
log.Printf("[DEBUG] Deleting security association %s between vcable %s and security list %s",
|
||||
name, vcable, seclist)
|
||||
|
||||
if err := client.DeleteSecurityAssociation(name); err != nil {
|
||||
return fmt.Errorf("Error deleting security association %s between vcable %s and security list %s: %s",
|
||||
name, vcable, seclist, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccOPCResourceSecurityAssociation_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: opcResourceCheck(
|
||||
associationResourceName,
|
||||
testAccCheckAssociationDestroyed),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccSecurityAssociationBasic,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
opcResourceCheck(
|
||||
associationResourceName,
|
||||
testAccCheckAssociationExists),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckAssociationExists(state *OPCResourceState) error {
|
||||
associationName := getAssociationName(state)
|
||||
|
||||
if _, err := state.SecurityAssociations().GetSecurityAssociation(associationName); err != nil {
|
||||
return fmt.Errorf("Error retrieving state of security assocation %s: %s", associationName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAssociationName(rs *OPCResourceState) string {
|
||||
return rs.Attributes["name"]
|
||||
}
|
||||
|
||||
func testAccCheckAssociationDestroyed(state *OPCResourceState) error {
|
||||
associationName := getAssociationName(state)
|
||||
if info, err := state.SecurityAssociations().GetSecurityAssociation(associationName); err == nil {
|
||||
return fmt.Errorf("Association %s still exists: %#v", associationName, info)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const associationName = "test_rule"
|
||||
|
||||
var associationResourceName = fmt.Sprintf("opc_compute_security_association.%s", associationName)
|
||||
|
||||
var testAccSecurityAssociationBasic = fmt.Sprintf(`
|
||||
resource "opc_compute_security_list" "sec-list1" {
|
||||
name = "sec-list-1"
|
||||
policy = "PERMIT"
|
||||
outbound_cidr_policy = "DENY"
|
||||
}
|
||||
|
||||
resource "opc_compute_security_association" "%s" {
|
||||
vcable = "${opc_compute_instance.test-instance1.vcable}"
|
||||
seclist = "${opc_compute_security_list.sec-list1.name}"
|
||||
}
|
||||
|
||||
resource "opc_compute_instance" "test-instance1" {
|
||||
name = "test"
|
||||
label = "test"
|
||||
shape = "oc3"
|
||||
imageList = "/oracle/public/oel_6.4_2GB_v1"
|
||||
}
|
||||
`, ruleName)
|
|
@ -0,0 +1,117 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceSecurityIPList() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceSecurityIPListCreate,
|
||||
Read: resourceSecurityIPListRead,
|
||||
Update: resourceSecurityIPListUpdate,
|
||||
Delete: resourceSecurityIPListDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"ip_entries": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSecurityIPListCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
name, ipEntries := getSecurityIPListResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating security IP list with name %s, entries %s",
|
||||
name, ipEntries)
|
||||
|
||||
client := meta.(*OPCClient).SecurityIPLists()
|
||||
info, err := client.CreateSecurityIPList(name, ipEntries)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating security IP list %s: %s", name, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateSecurityIPListResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSecurityIPListResourceData(d *schema.ResourceData, info *compute.SecurityIPListInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("entries", info.SecIPEntries)
|
||||
}
|
||||
|
||||
func resourceSecurityIPListRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityIPLists()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of security IP list %s", name)
|
||||
result, err := client.GetSecurityIPList(name)
|
||||
if err != nil {
|
||||
// Security IP List does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading security IP list %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of security IP list %s: %#v", name, result)
|
||||
updateSecurityIPListResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSecurityIPListResourceData(d *schema.ResourceData) (string, []string) {
|
||||
name := d.Get("name").(string)
|
||||
ipEntries := d.Get("ip_entries").([]interface{})
|
||||
ipEntryStrings := []string{}
|
||||
for _, entry := range ipEntries {
|
||||
ipEntryStrings = append(ipEntryStrings, entry.(string))
|
||||
}
|
||||
return name, ipEntryStrings
|
||||
}
|
||||
|
||||
func resourceSecurityIPListUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
client := meta.(*OPCClient).SecurityIPLists()
|
||||
name, entries := getSecurityIPListResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Updating security IP list %s with ip entries %s",
|
||||
name, entries)
|
||||
|
||||
info, err := client.UpdateSecurityIPList(name, entries)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating security IP list %s: %s", name, err)
|
||||
}
|
||||
|
||||
updateSecurityIPListResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSecurityIPListDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityIPLists()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Deleting security IP list %s", name)
|
||||
if err := client.DeleteSecurityIPList(name); err != nil {
|
||||
return fmt.Errorf("Error deleting security IP list %s: %s", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceSecurityList() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceSecurityListCreate,
|
||||
Read: resourceSecurityListRead,
|
||||
Update: resourceSecurityListUpdate,
|
||||
Delete: resourceSecurityListDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"policy": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
|
||||
"outbound_cidr_policy": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSecurityListCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
name, policy, outboundCIDRPolicy := getSecurityListResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating security list with name %s, policy %s, outbound CIDR policy %s",
|
||||
name, policy, outboundCIDRPolicy)
|
||||
|
||||
client := meta.(*OPCClient).SecurityLists()
|
||||
info, err := client.CreateSecurityList(name, policy, outboundCIDRPolicy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating security list %s: %s", name, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateSecurityListResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSecurityListResourceData(d *schema.ResourceData, info *compute.SecurityListInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("policy", info.Policy)
|
||||
d.Set("outbound_cidr_policy", info.OutboundCIDRPolicy)
|
||||
}
|
||||
|
||||
func resourceSecurityListRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityLists()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of security list %s", name)
|
||||
result, err := client.GetSecurityList(name)
|
||||
if err != nil {
|
||||
// Security List does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading security list %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of ssh key %s: %#v", name, result)
|
||||
updateSecurityListResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSecurityListResourceData(d *schema.ResourceData) (string, string, string) {
|
||||
return d.Get("name").(string),
|
||||
d.Get("policy").(string),
|
||||
d.Get("outbound_cidr_policy").(string)
|
||||
}
|
||||
|
||||
func resourceSecurityListUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
client := meta.(*OPCClient).SecurityLists()
|
||||
name, policy, outboundCIDRPolicy := getSecurityListResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Updating security list %s with policy %s, outbound_cidr_policy %s",
|
||||
name, policy, outboundCIDRPolicy)
|
||||
|
||||
info, err := client.UpdateSecurityList(name, policy, outboundCIDRPolicy)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating security list %s: %s", name, err)
|
||||
}
|
||||
|
||||
updateSecurityListResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSecurityListDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityLists()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Deleting ssh key volume %s", name)
|
||||
if err := client.DeleteSecurityList(name); err != nil {
|
||||
return fmt.Errorf("Error deleting security list %s: %s", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceSecurityRule() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceSecurityRuleCreate,
|
||||
Read: resourceSecurityRuleRead,
|
||||
Update: resourceSecurityRuleUpdate,
|
||||
Delete: resourceSecurityRuleDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"source_list": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"destination_list": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"application": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"action": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
|
||||
"disabled": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSecurityRuleCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
name, sourceList, destinationList, application, action, disabled := getSecurityRuleResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Creating security list with name %s, sourceList %s, destinationList %s, application %s, action %s, disabled %s",
|
||||
name, sourceList, destinationList, application, action, disabled)
|
||||
|
||||
client := meta.(*OPCClient).SecurityRules()
|
||||
info, err := client.CreateSecurityRule(name, sourceList, destinationList, application, action, disabled)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating security rule %s: %s", name, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateSecurityRuleResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSecurityRuleResourceData(d *schema.ResourceData, info *compute.SecurityRuleInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("source_list", info.SourceList)
|
||||
d.Set("destination_list", info.DestinationList)
|
||||
d.Set("application", info.Application)
|
||||
d.Set("action", info.Action)
|
||||
d.Set("disabled", info.Disabled)
|
||||
}
|
||||
|
||||
func resourceSecurityRuleRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityRules()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of security rule %s", name)
|
||||
result, err := client.GetSecurityRule(name)
|
||||
if err != nil {
|
||||
// Security Rule does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading security list %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of ssh key %s: %#v", name, result)
|
||||
updateSecurityRuleResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSecurityRuleResourceData(d *schema.ResourceData) (string, string, string, string, string, bool) {
|
||||
return d.Get("name").(string),
|
||||
d.Get("source_list").(string),
|
||||
d.Get("destination_list").(string),
|
||||
d.Get("application").(string),
|
||||
d.Get("action").(string),
|
||||
d.Get("disabled").(bool)
|
||||
}
|
||||
|
||||
func resourceSecurityRuleUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
|
||||
client := meta.(*OPCClient).SecurityRules()
|
||||
name, sourceList, destinationList, application, action, disabled := getSecurityRuleResourceData(d)
|
||||
|
||||
log.Printf("[DEBUG] Updating security list %s with sourceList %s, destinationList %s, application %s, action %s, disabled %s",
|
||||
name, sourceList, destinationList, application, action, disabled)
|
||||
|
||||
info, err := client.UpdateSecurityRule(name, sourceList, destinationList, application, action, disabled)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating security rule %s: %s", name, err)
|
||||
}
|
||||
|
||||
updateSecurityRuleResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSecurityRuleDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource state: %#v", d.State())
|
||||
client := meta.(*OPCClient).SecurityRules()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Deleting ssh key volume %s", name)
|
||||
if err := client.DeleteSecurityRule(name); err != nil {
|
||||
return fmt.Errorf("Error deleting security rule %s: %s", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccOPCResourceSecurityRule_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: opcResourceCheck(
|
||||
ruleResourceName,
|
||||
testAccCheckRuleDestroyed),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccSecurityRuleBasic,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
opcResourceCheck(
|
||||
ruleResourceName,
|
||||
testAccCheckRuleExists),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckRuleExists(state *OPCResourceState) error {
|
||||
ruleName := getRuleName(state)
|
||||
|
||||
if _, err := state.SecurityRules().GetSecurityRule(ruleName); err != nil {
|
||||
return fmt.Errorf("Error retrieving state of security rule %s: %s", ruleName, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getRuleName(rs *OPCResourceState) string {
|
||||
return rs.Attributes["name"]
|
||||
}
|
||||
|
||||
func testAccCheckRuleDestroyed(state *OPCResourceState) error {
|
||||
ruleName := getRuleName(state)
|
||||
if info, err := state.SecurityRules().GetSecurityRule(ruleName); err == nil {
|
||||
return fmt.Errorf("Rule %s still exists: %#v", ruleName, info)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const ruleName = "test_rule"
|
||||
const secListName = "sec-list1"
|
||||
const secIpListName = "sec-ip-list1"
|
||||
|
||||
var ruleResourceName = fmt.Sprintf("opc_compute_security_rule.%s", ruleName)
|
||||
|
||||
var testAccSecurityRuleBasic = fmt.Sprintf(`
|
||||
resource "opc_compute_security_rule" "%s" {
|
||||
name = "test"
|
||||
source_list = "seclist:${opc_compute_security_list.sec-list1.name}"
|
||||
destination_list = "seciplist:${opc_compute_security_ip_list.sec-ip-list1.name}"
|
||||
action = "PERMIT"
|
||||
application = "${opc_compute_security_application.spring-boot.name}"
|
||||
disabled = false
|
||||
}
|
||||
|
||||
resource "opc_compute_security_list" "%s" {
|
||||
name = "sec-list-1"
|
||||
policy = "PERMIT"
|
||||
outbound_cidr_policy = "DENY"
|
||||
}
|
||||
|
||||
resource "opc_compute_security_application" "spring-boot" {
|
||||
name = "spring-boot"
|
||||
protocol = "tcp"
|
||||
dport = "8080"
|
||||
}
|
||||
|
||||
resource "opc_compute_security_ip_list" "%s" {
|
||||
name = "sec-ip-list1"
|
||||
ip_entries = ["217.138.34.4"]
|
||||
}
|
||||
`, ruleName, secListName, secIpListName)
|
|
@ -0,0 +1,117 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceSSHKey() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceSSHKeyCreate,
|
||||
Read: resourceSSHKeyRead,
|
||||
Update: resourceSSHKeyUpdate,
|
||||
Delete: resourceSSHKeyDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"key": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
|
||||
"enabled": &schema.Schema{
|
||||
Type: schema.TypeBool,
|
||||
Required: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceSSHKeyCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d)
|
||||
|
||||
client := meta.(*OPCClient).SSHKeys()
|
||||
name := d.Get("name").(string)
|
||||
key := d.Get("key").(string)
|
||||
enabled := d.Get("enabled").(bool)
|
||||
|
||||
log.Printf("[DEBUG] Creating ssh key with name %s, key %s, enabled %s",
|
||||
name, key, enabled)
|
||||
|
||||
info, err := client.CreateSSHKey(name, key, enabled)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating ssh key %s: %s", name, err)
|
||||
}
|
||||
|
||||
d.SetId(info.Name)
|
||||
updateSSHKeyResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSSHKeyResourceData(d *schema.ResourceData, info *compute.SSHKeyInfo) {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("key", info.Key)
|
||||
d.Set("enabled", info.Enabled)
|
||||
}
|
||||
|
||||
func resourceSSHKeyRead(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d)
|
||||
client := meta.(*OPCClient).SSHKeys()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of ssh key %s", name)
|
||||
result, err := client.GetSSHKey(name)
|
||||
if err != nil {
|
||||
// SSH Key does not exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading ssh key %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of ssh key %s: %#v", name, result)
|
||||
updateSSHKeyResourceData(d, result)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSSHKeyUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d)
|
||||
|
||||
client := meta.(*OPCClient).SSHKeys()
|
||||
name := d.Get("name").(string)
|
||||
key := d.Get("key").(string)
|
||||
enabled := d.Get("enabled").(bool)
|
||||
|
||||
log.Printf("[DEBUG] Updating ssh key with name %s, key %s, enabled %s",
|
||||
name, key, enabled)
|
||||
|
||||
info, err := client.UpdateSSHKey(name, key, enabled)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating ssh key %s: %s", name, err)
|
||||
}
|
||||
|
||||
updateSSHKeyResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceSSHKeyDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d)
|
||||
client := meta.(*OPCClient).SSHKeys()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Deleting ssh key volume %s", name)
|
||||
if err := client.DeleteSSHKey(name); err != nil {
|
||||
return fmt.Errorf("Error deleting ssh key %s: %s", name, err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,301 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/oracle/terraform-provider-compute/sdk/compute"
|
||||
"log"
|
||||
)
|
||||
|
||||
func resourceStorageVolume() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: resourceStorageVolumeCreate,
|
||||
Read: resourceStorageVolumeRead,
|
||||
Update: resourceStorageVolumeUpdate,
|
||||
Delete: resourceStorageVolumeDelete,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"size": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"sizeInBytes": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
|
||||
"description": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
},
|
||||
|
||||
"storage": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: "/oracle/public/storage/default",
|
||||
},
|
||||
|
||||
"tags": &schema.Schema{
|
||||
Type: schema.TypeList,
|
||||
Optional: true,
|
||||
ForceNew: false,
|
||||
Elem: &schema.Schema{Type: schema.TypeString},
|
||||
},
|
||||
|
||||
"bootableImage": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"bootableImageVersion": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: -1,
|
||||
},
|
||||
|
||||
"snapshot": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"account": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"snapshotId": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func resourceStorageVolumeCreate(d *schema.ResourceData, meta interface{}) error {
|
||||
log.Printf("[DEBUG] Resource data: %#v", d)
|
||||
|
||||
sv := meta.(*OPCClient).StorageVolumes()
|
||||
name := d.Get("name").(string)
|
||||
properties := []string{d.Get("storage").(string)}
|
||||
|
||||
spec := sv.NewStorageVolumeSpec(
|
||||
d.Get("size").(string),
|
||||
properties,
|
||||
name)
|
||||
|
||||
if d.Get("description").(string) != "" {
|
||||
spec.SetDescription(d.Get("description").(string))
|
||||
}
|
||||
|
||||
spec.SetTags(getTags(d))
|
||||
|
||||
if d.Get("bootableImage") != "" {
|
||||
spec.SetBootableImage(d.Get("bootableImage").(string), d.Get("bootableImageVersion").(int))
|
||||
}
|
||||
|
||||
if len(d.Get("snapshot").(*schema.Set).List()) > 0 {
|
||||
snapshotDetails := d.Get("snapshot").(*schema.Set).List()[0].(map[string]interface{})
|
||||
spec.SetSnapshot(
|
||||
snapshotDetails["name"].(string),
|
||||
snapshotDetails["account"].(string),
|
||||
)
|
||||
}
|
||||
|
||||
if d.Get("snapshotId") != "" {
|
||||
spec.SetSnapshotID(d.Get("snapshotId").(string))
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Creating storage volume %s with spec %#v", name, spec)
|
||||
err := sv.CreateStorageVolume(spec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating storage volume %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for storage volume %s to come online", name)
|
||||
info, err := sv.WaitForStorageVolumeOnline(name, meta.(*OPCClient).MaxRetryTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error waiting for storage volume %s to come online: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Created storage volume %s: %#v", name, info)
|
||||
|
||||
cachedAttachments, attachmentsFound := meta.(*OPCClient).storageAttachmentsByVolumeCache[name]
|
||||
if attachmentsFound {
|
||||
log.Printf("[DEBUG] Rebuilding storage attachments for volume %s", name)
|
||||
for _, cachedAttachment := range cachedAttachments {
|
||||
log.Printf("[DEBUG] Rebuilding storage attachments between volume %s and instance %s",
|
||||
name,
|
||||
cachedAttachment.instanceName)
|
||||
|
||||
attachmentInfo, err := meta.(*OPCClient).StorageAttachments().CreateStorageAttachment(
|
||||
cachedAttachment.index,
|
||||
cachedAttachment.instanceName,
|
||||
name,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Error recreating storage attachment between volume %s and instance %s: %s",
|
||||
name,
|
||||
*cachedAttachment.instanceName,
|
||||
err)
|
||||
}
|
||||
err = meta.(*OPCClient).StorageAttachments().WaitForStorageAttachmentCreated(
|
||||
attachmentInfo.Name,
|
||||
meta.(*OPCClient).MaxRetryTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"Error recreating storage attachment between volume %s and instance %s: %s",
|
||||
name,
|
||||
*cachedAttachment.instanceName,
|
||||
err)
|
||||
}
|
||||
}
|
||||
meta.(*OPCClient).storageAttachmentsByVolumeCache[name] = nil
|
||||
}
|
||||
|
||||
d.SetId(name)
|
||||
updateResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTags(d *schema.ResourceData) []string {
|
||||
tags := []string{}
|
||||
for _, i := range d.Get("tags").([]interface{}) {
|
||||
tags = append(tags, i.(string))
|
||||
}
|
||||
return tags
|
||||
}
|
||||
|
||||
func updateResourceData(d *schema.ResourceData, info *compute.StorageVolumeInfo) error {
|
||||
d.Set("name", info.Name)
|
||||
d.Set("description", info.Description)
|
||||
d.Set("storage", info.Properties[0])
|
||||
d.Set("sizeInBytes", info.Size)
|
||||
d.Set("tags", info.Tags)
|
||||
d.Set("bootableImage", info.ImageList)
|
||||
d.Set("bootableImageVersion", info.ImageListEntry)
|
||||
if info.Snapshot != "" {
|
||||
d.Set("snapshot", map[string]interface{}{
|
||||
"name": info.Snapshot,
|
||||
"account": info.SnapshotAccount,
|
||||
})
|
||||
}
|
||||
d.Set("snapshotId", info.SnapshotID)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceStorageVolumeRead(d *schema.ResourceData, meta interface{}) error {
|
||||
sv := meta.(*OPCClient).StorageVolumes()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
log.Printf("[DEBUG] Reading state of storage volume %s", name)
|
||||
result, err := sv.GetStorageVolume(name)
|
||||
if err != nil {
|
||||
// Volume doesn't exist
|
||||
if compute.WasNotFoundError(err) {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("Error reading storage volume %s: %s", name, err)
|
||||
}
|
||||
|
||||
if len(result.Result) == 0 {
|
||||
// Volume doesn't exist
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Read state of storage volume %s: %#v", name, &result.Result[0])
|
||||
updateResourceData(d, &result.Result[0])
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceStorageVolumeUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||
sv := meta.(*OPCClient).StorageVolumes()
|
||||
name := d.Get("name").(string)
|
||||
description := d.Get("description").(string)
|
||||
size := d.Get("size").(string)
|
||||
tags := getTags(d)
|
||||
|
||||
log.Printf("[DEBUG] Updating storage volume %s with size %s, description %s, tags %#v", name, size, description, tags)
|
||||
err := sv.UpdateStorageVolume(name, size, description, tags)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error updating storage volume %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for updated storage volume %s to come online", name)
|
||||
info, err := sv.WaitForStorageVolumeOnline(name, meta.(*OPCClient).MaxRetryTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error waiting for updated storage volume %s to come online: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Updated storage volume %s: %#v", name, info)
|
||||
updateResourceData(d, info)
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceStorageVolumeDelete(d *schema.ResourceData, meta interface{}) error {
|
||||
sv := meta.(*OPCClient).StorageVolumes()
|
||||
name := d.Get("name").(string)
|
||||
|
||||
sva := meta.(*OPCClient).StorageAttachments()
|
||||
attachments, err := sva.GetStorageAttachmentsForVolume(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving storage attachments for volume %s: %s", name, err)
|
||||
}
|
||||
|
||||
attachmentsToCache := make([]storageAttachment, len(*attachments))
|
||||
for index, attachment := range *attachments {
|
||||
log.Printf("[DEBUG] Deleting storage attachment %s for volume %s", attachment.Name, name)
|
||||
sva.DeleteStorageAttachment(attachment.Name)
|
||||
sva.WaitForStorageAttachmentDeleted(attachment.Name, meta.(*OPCClient).MaxRetryTimeout)
|
||||
attachmentsToCache[index] = storageAttachment{
|
||||
index: attachment.Index,
|
||||
instanceName: compute.InstanceNameFromString(attachment.InstanceName),
|
||||
}
|
||||
}
|
||||
meta.(*OPCClient).storageAttachmentsByVolumeCache[name] = attachmentsToCache
|
||||
|
||||
log.Printf("[DEBUG] Deleting storage volume %s", name)
|
||||
err = sv.DeleteStorageVolume(name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error deleting storage volume %s: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Waiting for storage volume %s to finish deleting", name)
|
||||
err = sv.WaitForStorageVolumeDeleted(name, meta.(*OPCClient).MaxRetryTimeout)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error waiting for storage volume %s to finish deleting: %s", name, err)
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Deleted storage volume %s", name)
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package opc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAccOPCStorageVolume_Basic(t *testing.T) {
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: opcResourceCheck(
|
||||
"opc_compute_storage_volume.test_volume",
|
||||
testAccCheckStorageVolumeDestroyed),
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccStorageVolumeBasic,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
opcResourceCheck(
|
||||
"opc_compute_storage_volume.test_volume",
|
||||
testAccCheckStorageVolumeExists),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckStorageVolumeExists(state *OPCResourceState) error {
|
||||
sv := state.StorageVolumes()
|
||||
volumeName := state.Attributes["name"]
|
||||
|
||||
info, err := sv.GetStorageVolume(volumeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving state of volume %s: %s", volumeName, err)
|
||||
}
|
||||
|
||||
if len(info.Result) == 0 {
|
||||
return fmt.Errorf("No info found for volume %s", volumeName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testAccCheckStorageVolumeDestroyed(state *OPCResourceState) error {
|
||||
sv := state.StorageVolumes()
|
||||
|
||||
volumeName := state.Attributes["name"]
|
||||
|
||||
info, err := sv.GetStorageVolume(volumeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error retrieving state of volume %s: %s", volumeName, err)
|
||||
}
|
||||
|
||||
if len(info.Result) != 0 {
|
||||
return fmt.Errorf("Volume %s still exists", volumeName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const testAccStorageVolumeBasic = `
|
||||
resource "opc_compute_storage_volume" "test_volume" {
|
||||
size = "3g"
|
||||
description = "My volume"
|
||||
name = "test_volume_b"
|
||||
tags = ["foo", "bar", "baz"]
|
||||
}
|
||||
`
|
Loading…
Reference in New Issue