Initial Oracle Compute Cloud provider

This commit is contained in:
Stephen Cross 2017-03-29 16:30:08 +00:00
parent 3c296dc5d0
commit c5d1f8f88f
18 changed files with 2198 additions and 0 deletions

View File

@ -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
}

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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"]
}
`